17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*e65e5c2dSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * This file contains the functions that are shared among
287c478bd9Sstevel@tonic-gate  * the various services this tool will ultimately provide.
297711facfSdinak  * The functions in this file return PKCS#11 CK_RV errors.
307711facfSdinak  * Only one session and one login per token is supported
317711facfSdinak  * at this time.
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
3899ebb4caSwyllys #include <sys/types.h>
3999ebb4caSwyllys #include <sys/stat.h>
4099ebb4caSwyllys #include <fcntl.h>
4199ebb4caSwyllys #include <tzfile.h>
427c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
437c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
4499ebb4caSwyllys #include <kmfapi.h>
457c478bd9Sstevel@tonic-gate 
4699ebb4caSwyllys #include "common.h"
477711facfSdinak 
487711facfSdinak /* Local status variables. */
497711facfSdinak static boolean_t	initialized = B_FALSE;
507711facfSdinak static boolean_t	session_opened = B_FALSE;
517711facfSdinak static boolean_t	logged_in = B_FALSE;
527c478bd9Sstevel@tonic-gate 
5349e21299Sdinak /* Supporting structures and global variables for getopt_av(). */
5449e21299Sdinak typedef struct	av_opts_s {
5549e21299Sdinak 	int		shortnm;	/* short name character */
5649e21299Sdinak 	char		*longnm;	/* long name string, NOT terminated */
5749e21299Sdinak 	int		longnm_len;	/* length of long name string */
5849e21299Sdinak 	boolean_t	has_arg;	/* takes optional argument */
5949e21299Sdinak } av_opts;
6049e21299Sdinak static av_opts		*opts_av = NULL;
6149e21299Sdinak static const char	*_save_optstr = NULL;
6249e21299Sdinak static int		_save_numopts = 0;
6349e21299Sdinak 
6449e21299Sdinak int			optind_av = 1;
6549e21299Sdinak char			*optarg_av = NULL;
6649e21299Sdinak 
6799ebb4caSwyllys static void close_sess(CK_SESSION_HANDLE);
6899ebb4caSwyllys static void logout_token(CK_SESSION_HANDLE);
6999ebb4caSwyllys 
70*e65e5c2dSWyllys Ingersoll struct oid_table_entry {
71*e65e5c2dSWyllys Ingersoll 	const KMF_OID *oid;
72*e65e5c2dSWyllys Ingersoll 	char *name;
73*e65e5c2dSWyllys Ingersoll };
74*e65e5c2dSWyllys Ingersoll 
75*e65e5c2dSWyllys Ingersoll struct oid_table_entry oid_table[] = {
76*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp112r1, "secp112r1"},
77*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp112r2, "secp112r2"},
78*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp128r1, "secp128r1"},
79*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp128r2, "secp128r2"},
80*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160k1, "secp160k1"},
81*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160r1, "secp160r1"},
82*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160r2, "secp160r2"},
83*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp192k1, "secp192k1"},
84*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp192r1, "secp192r1"},
85*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp224k1, "secp224k1"},
86*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp224r1, "secp224r1"},
87*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp256k1, "secp256k1"},
88*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp256r1, "secp256r1"},
89*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp384r1, "secp384r1"},
90*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp521r1, "secp521r1"},
91*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect113r1, "sect113r1"},
92*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect113r2, "sect113r2"},
93*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect131r1, "sect131r1"},
94*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect131r2, "sect131r2"},
95*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163k1, "sect163k1"},
96*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163r1, "sect163r1"},
97*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163r2, "sect163r2"},
98*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect193r1, "sect193r1"},
99*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect193r2, "sect193r2"},
100*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect233k1, "sect233k1"},
101*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect233r1, "sect233r1"},
102*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect239k1, "sect239k1"},
103*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect283k1, "sect283k1"},
104*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect283r1, "sect283r1"},
105*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect409k1, "sect409k1"},
106*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect409r1, "sect409r1"},
107*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect571k1, "sect571k1"},
108*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect571r1, "sect571r1"},
109*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
110*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
111*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
112*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
113*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
114*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
115*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
116*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
117*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
118*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
119*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
120*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
121*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
122*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
123*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
124*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
125*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_prime192v2, "prime192v2"},
126*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_prime192v3, "prime192v3"},
127*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_MD5, "md5"},
128*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA1, "sha1"},
129*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA256, "sha256"},
130*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA384, "sha384"},
131*e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA512, "sha512"}
132*e65e5c2dSWyllys Ingersoll };
133*e65e5c2dSWyllys Ingersoll int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
134*e65e5c2dSWyllys Ingersoll #define	number_of_curves (number_of_oids - 5)
135*e65e5c2dSWyllys Ingersoll 
1367c478bd9Sstevel@tonic-gate /*
1377711facfSdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
1387711facfSdinak  * along with setting/resetting state variables.
1397c478bd9Sstevel@tonic-gate  */
140448b8615Swyllys static CK_RV
141448b8615Swyllys init_pkcs11(void)
1427c478bd9Sstevel@tonic-gate {
1437711facfSdinak 	CK_RV		rv = CKR_OK;
1447711facfSdinak 
1457711facfSdinak 	/* If C_Initialize() already called, nothing to do here. */
1467711facfSdinak 	if (initialized == B_TRUE)
1477711facfSdinak 		return (CKR_OK);
1487c478bd9Sstevel@tonic-gate 
1497711facfSdinak 	/* Reset state variables because C_Initialize() not yet done. */
1507711facfSdinak 	session_opened = B_FALSE;
1517711facfSdinak 	logged_in = B_FALSE;
1527c478bd9Sstevel@tonic-gate 
1537711facfSdinak 	/* Initialize PKCS#11 library. */
1547711facfSdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
1557711facfSdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
1567711facfSdinak 		return (rv);
1577711facfSdinak 	}
1587c478bd9Sstevel@tonic-gate 
1597711facfSdinak 	initialized = B_TRUE;
1607711facfSdinak 	return (CKR_OK);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647711facfSdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
1657711facfSdinak  * if any, are closed, and thereby any logins are logged out also.
1667c478bd9Sstevel@tonic-gate  */
1677711facfSdinak void
1687711facfSdinak final_pk11(CK_SESSION_HANDLE sess)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 
1717711facfSdinak 	/* If the library wasn't initialized, nothing to do here. */
1727711facfSdinak 	if (!initialized)
1737711facfSdinak 		return;
1747c478bd9Sstevel@tonic-gate 
1757711facfSdinak 	/* Make sure the sesion is closed first. */
1767711facfSdinak 	close_sess(sess);
1777711facfSdinak 
1787711facfSdinak 	(void) C_Finalize(NULL);
1797711facfSdinak 	initialized = B_FALSE;
1807711facfSdinak }
1817711facfSdinak 
1827711facfSdinak /*
1837711facfSdinak  * Close PKCS#11 session and reset state variables.  Any logins are
1847711facfSdinak  * logged out.
1857711facfSdinak  */
18699ebb4caSwyllys static void
1877711facfSdinak close_sess(CK_SESSION_HANDLE sess)
1887711facfSdinak {
1897711facfSdinak 
1907711facfSdinak 	if (sess == NULL) {
1917711facfSdinak 		return;
1927711facfSdinak 	}
1937711facfSdinak 
1947711facfSdinak 	/* If session is already closed, nothing to do here. */
1957711facfSdinak 	if (!session_opened)
1967711facfSdinak 		return;
1977711facfSdinak 
1987711facfSdinak 	/* Make sure user is logged out of token. */
1997711facfSdinak 	logout_token(sess);
2007711facfSdinak 
2017711facfSdinak 	(void) C_CloseSession(sess);
2027711facfSdinak 	session_opened = B_FALSE;
2037711facfSdinak }
2047711facfSdinak 
2057711facfSdinak /*
2067711facfSdinak  * Log user out of token and reset status variable.
2077711facfSdinak  */
20899ebb4caSwyllys static void
2097711facfSdinak logout_token(CK_SESSION_HANDLE sess)
2107711facfSdinak {
2117711facfSdinak 
2127711facfSdinak 	if (sess == NULL) {
2137711facfSdinak 		return;
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate 
2167711facfSdinak 	/* If already logged out, nothing to do here. */
2177711facfSdinak 	if (!logged_in)
2187711facfSdinak 		return;
2197711facfSdinak 
2207711facfSdinak 	(void) C_Logout(sess);
2217711facfSdinak 	logged_in = B_FALSE;
2227711facfSdinak }
2237711facfSdinak 
2247711facfSdinak /*
2257711facfSdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
2267711facfSdinak  * If two prompts are given, the PIN is confirmed with second prompt.
2277711facfSdinak  * Note that getphassphrase() may return data in static memory area.
2287711facfSdinak  */
2297711facfSdinak CK_RV
2307711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
2317711facfSdinak {
232d00756ccSwyllys 	char *save_phrase, *phrase1, *phrase2;
2337711facfSdinak 
2347711facfSdinak 	/* Prompt user for a PIN. */
2357711facfSdinak 	if (prompt1 == NULL) {
2367711facfSdinak 		return (CKR_ARGUMENTS_BAD);
2377711facfSdinak 	}
2387711facfSdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
2397711facfSdinak 		return (CKR_FUNCTION_FAILED);
2407711facfSdinak 	}
2417711facfSdinak 
2427711facfSdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
2437711facfSdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
2447711facfSdinak 		return (CKR_HOST_MEMORY);
2457711facfSdinak 
2467711facfSdinak 	/* If second prompt given, PIN confirmation is requested. */
2477711facfSdinak 	if (prompt2 != NULL) {
2487711facfSdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
2497711facfSdinak 			free(save_phrase);
2507711facfSdinak 			return (CKR_FUNCTION_FAILED);
2517711facfSdinak 		}
2527711facfSdinak 		if (strcmp(save_phrase, phrase2) != 0) {
2537711facfSdinak 			free(save_phrase);
2547711facfSdinak 			return (CKR_PIN_INCORRECT);
2557711facfSdinak 		}
2567711facfSdinak 	}
2577711facfSdinak 
2587711facfSdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
2597711facfSdinak 	*pinlen = strlen(save_phrase);
2607711facfSdinak 	return (CKR_OK);
2617711facfSdinak }
2627711facfSdinak 
263d00756ccSwyllys int
264d00756ccSwyllys yn_to_int(char *ynstr)
265d00756ccSwyllys {
266d00756ccSwyllys 	char *y = gettext("yes");
267d00756ccSwyllys 	char *n = gettext("no");
268d00756ccSwyllys 	if (ynstr == NULL)
269d00756ccSwyllys 		return (-1);
270d00756ccSwyllys 
271d00756ccSwyllys 	if (strncasecmp(ynstr, y, 1) == 0)
272d00756ccSwyllys 		return (1);
273d00756ccSwyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
274d00756ccSwyllys 		return (0);
275d00756ccSwyllys 	else
276d00756ccSwyllys 		return (-1);
277d00756ccSwyllys }
278d00756ccSwyllys 
2797711facfSdinak /*
2807711facfSdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
2817711facfSdinak  * default prompt is used.  If not message for invalid input is supplied,
2827711facfSdinak  * a default will not be provided.  If the user provides no response,
2837711facfSdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
2847711facfSdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
2857711facfSdinak  */
2867711facfSdinak boolean_t
2877711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt)
2887711facfSdinak {
289d00756ccSwyllys 	char	*response, buf[1024];
290d00756ccSwyllys 	int	ans;
2917711facfSdinak 
2927711facfSdinak 	if (prompt == NULL)
2937711facfSdinak 		prompt = gettext("Enter (y)es or (n)o? ");
2947711facfSdinak 
2957711facfSdinak 	for (;;) {
2967711facfSdinak 		/* Prompt user. */
2977711facfSdinak 		(void) printf("%s", prompt);
2987711facfSdinak 		(void) fflush(stdout);
2997711facfSdinak 
3007711facfSdinak 		/* Get the response. */
3017711facfSdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
3027711facfSdinak 			break;		/* go to default response */
3037711facfSdinak 
3047711facfSdinak 		/* Skip any leading white space. */
3057711facfSdinak 		while (isspace(*response))
3067711facfSdinak 			response++;
3077711facfSdinak 		if (*response == '\0')
3087711facfSdinak 			break;		/* go to default response */
3097711facfSdinak 
310d00756ccSwyllys 		ans = yn_to_int(response);
311d00756ccSwyllys 		if (ans == 1)
3127711facfSdinak 			return (B_TRUE);
313d00756ccSwyllys 		else if (ans == 0)
3147711facfSdinak 			return (B_FALSE);
3157711facfSdinak 
3167711facfSdinak 		/* Indicate invalid input, and try again. */
3177711facfSdinak 		if (invalid != NULL)
31830a5e8faSwyllys 			(void) printf("%s", invalid);
3197711facfSdinak 	}
3207711facfSdinak 	return (dflt);
3217711facfSdinak }
3227711facfSdinak 
3237711facfSdinak /*
3247711facfSdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
3257711facfSdinak  * the size of the slot list buffer until the call is successful or an
3267711facfSdinak  * irrecoverable error occurs.
3277711facfSdinak  */
3287711facfSdinak CK_RV
3297711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
3307711facfSdinak {
3317711facfSdinak 	CK_ULONG	tmp_count = 0;
3327711facfSdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
3337711facfSdinak 	int		rv = CKR_OK;
3347711facfSdinak 
3357711facfSdinak 	if (!initialized)
336448b8615Swyllys 		if ((rv = init_pkcs11()) != CKR_OK)
3377711facfSdinak 			return (rv);
3387711facfSdinak 
3397711facfSdinak 	/*
3407711facfSdinak 	 * Get the slot count first because we don't know how many
3417711facfSdinak 	 * slots there are and how many of those slots even have tokens.
3427711facfSdinak 	 * Don't specify an arbitrary buffer size for the slot list;
3437711facfSdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
3447711facfSdinak 	 * Also select only those slots that have tokens in them,
3457711facfSdinak 	 * because this tool has no need to know about empty slots.
3467711facfSdinak 	 */
3477711facfSdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
3487711facfSdinak 		return (rv);
3497711facfSdinak 
3507711facfSdinak 	if (tmp_count == 0) {
3517711facfSdinak 		*slot_list = NULL_PTR;
3527711facfSdinak 		*slot_count = 0;
3537711facfSdinak 		return (CKR_OK);
3547711facfSdinak 	}
3557711facfSdinak 
3567711facfSdinak 	/* Allocate initial space for the slot list. */
3577711facfSdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
3587711facfSdinak 	    sizeof (CK_SLOT_ID))) == NULL)
3597711facfSdinak 		return (CKR_HOST_MEMORY);
3607711facfSdinak 
3617711facfSdinak 	/* Then get the slot list itself. */
3627711facfSdinak 	for (;;) {
3637711facfSdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
3647711facfSdinak 			*slot_list = tmp_list;
3657711facfSdinak 			*slot_count = tmp_count;
3667711facfSdinak 			break;
3677711facfSdinak 		}
3687711facfSdinak 
3697711facfSdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
3707711facfSdinak 			free(tmp_list);
3717711facfSdinak 			break;
3727711facfSdinak 		}
3737711facfSdinak 
3747711facfSdinak 		/* If the number of slots grew, try again. */
3757711facfSdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
3767711facfSdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
3777711facfSdinak 			free(tmp_list);
3787711facfSdinak 			rv = CKR_HOST_MEMORY;
3797711facfSdinak 			break;
3807711facfSdinak 		}
3817711facfSdinak 		tmp_list = tmp2_list;
3827711facfSdinak 	}
3837711facfSdinak 
3847711facfSdinak 	return (rv);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*
38899ebb4caSwyllys  * Breaks out the getopt-style option string into a structure that can be
38999ebb4caSwyllys  * traversed later for calls to getopt_av().  Option string is NOT altered,
39099ebb4caSwyllys  * but the struct fields point to locations within option string.
3917c478bd9Sstevel@tonic-gate  */
3927c478bd9Sstevel@tonic-gate static int
39399ebb4caSwyllys populate_opts(char *optstring)
3947c478bd9Sstevel@tonic-gate {
39599ebb4caSwyllys 	int		i;
39699ebb4caSwyllys 	av_opts		*temp;
3977c478bd9Sstevel@tonic-gate 	char		*marker;
3987c478bd9Sstevel@tonic-gate 
39999ebb4caSwyllys 	if (optstring == NULL || *optstring == '\0')
40099ebb4caSwyllys 		return (0);
40199ebb4caSwyllys 
40299ebb4caSwyllys 	/*
40399ebb4caSwyllys 	 * This tries to imitate getopt(3c) Each option must conform to:
40499ebb4caSwyllys 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
40599ebb4caSwyllys 	 * If long name is missing, the short name is used for long name.
40699ebb4caSwyllys 	 */
40799ebb4caSwyllys 	for (i = 0; *optstring != '\0'; i++) {
40899ebb4caSwyllys 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
40999ebb4caSwyllys 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
41099ebb4caSwyllys 			if (opts_av != NULL)
41199ebb4caSwyllys 				free(opts_av);
41299ebb4caSwyllys 			opts_av = NULL;
41399ebb4caSwyllys 			return (0);
41499ebb4caSwyllys 		} else {
41599ebb4caSwyllys 			opts_av = (av_opts *)temp;
41699ebb4caSwyllys 		}
4177c478bd9Sstevel@tonic-gate 
41899ebb4caSwyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
41999ebb4caSwyllys 		marker = optstring;		/* may need optstring later */
4207c478bd9Sstevel@tonic-gate 
42199ebb4caSwyllys 		opts_av[i].shortnm = *marker++;	/* set short name */
42299ebb4caSwyllys 
42399ebb4caSwyllys 		if (*marker == ':') {		/* check for opt arg */
42499ebb4caSwyllys 			marker++;
42599ebb4caSwyllys 			opts_av[i].has_arg = B_TRUE;
42699ebb4caSwyllys 		}
42799ebb4caSwyllys 
42899ebb4caSwyllys 		if (*marker == '(') {		/* check and set long name */
42999ebb4caSwyllys 			marker++;
43099ebb4caSwyllys 			opts_av[i].longnm = marker;
43199ebb4caSwyllys 			opts_av[i].longnm_len = strcspn(marker, ")");
43299ebb4caSwyllys 			optstring = marker + opts_av[i].longnm_len + 1;
43399ebb4caSwyllys 		} else {
43499ebb4caSwyllys 			/* use short name option character */
43599ebb4caSwyllys 			opts_av[i].longnm = optstring;
43699ebb4caSwyllys 			opts_av[i].longnm_len = 1;
43799ebb4caSwyllys 			optstring = marker;
43899ebb4caSwyllys 		}
43999ebb4caSwyllys 	}
44099ebb4caSwyllys 
44199ebb4caSwyllys 	return (i);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate /*
44599ebb4caSwyllys  * getopt_av() is very similar to getopt(3c) in that the takes an option
44699ebb4caSwyllys  * string, compares command line arguments for matches, and returns a single
44799ebb4caSwyllys  * letter option when a match is found.  However, getopt_av() differs from
44899ebb4caSwyllys  * getopt(3c) by requiring that only longname options and values be found
44999ebb4caSwyllys  * on the command line and all leading dashes are omitted.  In other words,
45099ebb4caSwyllys  * it tries to enforce only longname "option=value" arguments on the command
45199ebb4caSwyllys  * line.  Boolean options are not allowed either.
4527c478bd9Sstevel@tonic-gate  */
45399ebb4caSwyllys int
45499ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring)
4557c478bd9Sstevel@tonic-gate {
45699ebb4caSwyllys 	int	i;
45799ebb4caSwyllys 	int	len;
45899ebb4caSwyllys 	char   *cur_option;
4597c478bd9Sstevel@tonic-gate 
46099ebb4caSwyllys 	if (optind_av >= argc)
46199ebb4caSwyllys 		return (EOF);
4627c478bd9Sstevel@tonic-gate 
46399ebb4caSwyllys 	/* First time or when optstring changes from previous one */
46499ebb4caSwyllys 	if (_save_optstr != optstring) {
46599ebb4caSwyllys 		if (opts_av != NULL)
46630a5e8faSwyllys 			free(opts_av);
46799ebb4caSwyllys 		opts_av = NULL;
46899ebb4caSwyllys 		_save_optstr = optstring;
46999ebb4caSwyllys 		_save_numopts = populate_opts((char *)optstring);
47099ebb4caSwyllys 	}
4717c478bd9Sstevel@tonic-gate 
47299ebb4caSwyllys 	for (i = 0; i < _save_numopts; i++) {
47399ebb4caSwyllys 		cur_option = argv[optind_av];
4747c478bd9Sstevel@tonic-gate 
47599ebb4caSwyllys 		if (strcmp(cur_option, "--") == 0) {
47699ebb4caSwyllys 			optind_av++;
47799ebb4caSwyllys 			break;
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 
48099ebb4caSwyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
48199ebb4caSwyllys 			len = 1;
48299ebb4caSwyllys 			cur_option++; /* remove "-" */
48399ebb4caSwyllys 		} else {
48499ebb4caSwyllys 			len = strcspn(cur_option, "=");
48599ebb4caSwyllys 		}
4867c478bd9Sstevel@tonic-gate 
48799ebb4caSwyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
48899ebb4caSwyllys 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
48999ebb4caSwyllys 			/* matched */
49099ebb4caSwyllys 			if (!opts_av[i].has_arg) {
49199ebb4caSwyllys 				optind_av++;
49299ebb4caSwyllys 				return (opts_av[i].shortnm);
49399ebb4caSwyllys 			}
49499ebb4caSwyllys 
49599ebb4caSwyllys 			/* needs optarg */
49699ebb4caSwyllys 			if (cur_option[len] == '=') {
49799ebb4caSwyllys 				optarg_av = &(cur_option[len+1]);
49899ebb4caSwyllys 				optind_av++;
49999ebb4caSwyllys 				return (opts_av[i].shortnm);
50099ebb4caSwyllys 			}
50199ebb4caSwyllys 
50299ebb4caSwyllys 			optarg_av = NULL;
50399ebb4caSwyllys 			optind_av++;
50499ebb4caSwyllys 			return ((int)'?');
50599ebb4caSwyllys 		}
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 
50899ebb4caSwyllys 	return (EOF);
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate 
51199ebb4caSwyllys KMF_KEYSTORE_TYPE
51299ebb4caSwyllys KS2Int(char *keystore_str)
51349e21299Sdinak {
51499ebb4caSwyllys 	if (keystore_str == NULL)
51599ebb4caSwyllys 		return (0);
516d00756ccSwyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
51799ebb4caSwyllys 		return (KMF_KEYSTORE_PK11TOKEN);
518d00756ccSwyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
51999ebb4caSwyllys 		return (KMF_KEYSTORE_NSS);
520d00756ccSwyllys 	else if (strcasecmp(keystore_str, "file") == 0)
52199ebb4caSwyllys 		return (KMF_KEYSTORE_OPENSSL);
52299ebb4caSwyllys 	else
52399ebb4caSwyllys 		return (0);
52499ebb4caSwyllys }
52549e21299Sdinak 
526*e65e5c2dSWyllys Ingersoll /*
527*e65e5c2dSWyllys Ingersoll  * compare_oids
528*e65e5c2dSWyllys Ingersoll  * return 1 if equal
529*e65e5c2dSWyllys Ingersoll  */
530*e65e5c2dSWyllys Ingersoll boolean_t
531*e65e5c2dSWyllys Ingersoll compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
532*e65e5c2dSWyllys Ingersoll {
533*e65e5c2dSWyllys Ingersoll 	return ((oid1->Length == oid2->Length) &&
534*e65e5c2dSWyllys Ingersoll 	    !memcmp(oid1->Data, oid2->Data, oid1->Length));
535*e65e5c2dSWyllys Ingersoll }
53649e21299Sdinak 
53799ebb4caSwyllys int
538*e65e5c2dSWyllys Ingersoll Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
539*e65e5c2dSWyllys Ingersoll     KMF_ALGORITHM_INDEX *sigAlg)
54099ebb4caSwyllys {
54199ebb4caSwyllys 	if (algm == NULL) {
542*e65e5c2dSWyllys Ingersoll 		/* Default to SHA1+RSA */
5434165f465SWyllys Ingersoll 		*sigAlg = KMF_ALGID_SHA1WithRSA;
54499ebb4caSwyllys 		*ktype = KMF_RSA;
54599ebb4caSwyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
546*e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
547*e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
548*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithDSA;
549*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
550*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithDSA;
551*e65e5c2dSWyllys Ingersoll 		else
552*e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
55399ebb4caSwyllys 		*ktype = KMF_DSA;
55499ebb4caSwyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
555*e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
556*e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
557*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithRSA;
558*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
559*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithRSA;
560*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA384))
561*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA384WithRSA;
562*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA512))
563*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA512WithRSA;
564*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_MD5))
565*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_MD5WithRSA;
566*e65e5c2dSWyllys Ingersoll 		else
567*e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
56899ebb4caSwyllys 		*ktype = KMF_RSA;
569*e65e5c2dSWyllys Ingersoll 	} else if (strcasecmp(algm, "EC") == 0) {
570*e65e5c2dSWyllys Ingersoll 		/* EC keys may be used with some SHA2 hashes */
571*e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
572*e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
573*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithECDSA;
574*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
575*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithECDSA;
576*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA384))
577*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA384WithECDSA;
578*e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA512))
579*e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA512WithECDSA;
580*e65e5c2dSWyllys Ingersoll 		else
581*e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
582*e65e5c2dSWyllys Ingersoll 
583*e65e5c2dSWyllys Ingersoll 		*ktype = KMF_ECDSA;
58499ebb4caSwyllys 	} else {
58599ebb4caSwyllys 		return (-1);
58649e21299Sdinak 	}
58799ebb4caSwyllys 	return (0);
58849e21299Sdinak }
58949e21299Sdinak 
59099ebb4caSwyllys int
59199ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
59249e21299Sdinak {
59399ebb4caSwyllys 	if (algm == NULL)
59499ebb4caSwyllys 		*ktype = KMF_AES;
59599ebb4caSwyllys 	else if (strcasecmp(algm, "aes") == 0)
59699ebb4caSwyllys 		*ktype = KMF_AES;
59799ebb4caSwyllys 	else if (strcasecmp(algm, "arcfour") == 0)
59899ebb4caSwyllys 		*ktype = KMF_RC4;
59999ebb4caSwyllys 	else if (strcasecmp(algm, "des") == 0)
60099ebb4caSwyllys 		*ktype = KMF_DES;
60199ebb4caSwyllys 	else if (strcasecmp(algm, "3des") == 0)
60299ebb4caSwyllys 		*ktype = KMF_DES3;
603c197cb9dShylee 	else if (strcasecmp(algm, "generic") == 0)
604c197cb9dShylee 		*ktype = KMF_GENERIC_SECRET;
60599ebb4caSwyllys 	else
60699ebb4caSwyllys 		return (-1);
60749e21299Sdinak 
60899ebb4caSwyllys 	return (0);
60949e21299Sdinak }
61049e21299Sdinak 
61149e21299Sdinak int
61299ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
61349e21299Sdinak {
61499ebb4caSwyllys 	int num;
61599ebb4caSwyllys 	char timetok[6];
61649e21299Sdinak 
617d00756ccSwyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
61899ebb4caSwyllys 		/* default to 1 year lifetime */
61999ebb4caSwyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
62099ebb4caSwyllys 		return (0);
62149e21299Sdinak 	}
62249e21299Sdinak 
62399ebb4caSwyllys 	(void) memset(timetok, 0, sizeof (timetok));
62499ebb4caSwyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
62599ebb4caSwyllys 		return (-1);
62649e21299Sdinak 
627d00756ccSwyllys 	if (strcasecmp(timetok, "day") == 0||
628d00756ccSwyllys 	    strcasecmp(timetok, "days") == 0) {
62999ebb4caSwyllys 		*ltime = num * SECSPERDAY;
630d00756ccSwyllys 	} else if (strcasecmp(timetok, "hour") == 0||
631d00756ccSwyllys 	    strcasecmp(timetok, "hours") == 0) {
63299ebb4caSwyllys 		*ltime = num * SECSPERHOUR;
633d00756ccSwyllys 	} else if (strcasecmp(timetok, "year") == 0 ||
634d00756ccSwyllys 	    strcasecmp(timetok, "years") == 0) {
63599ebb4caSwyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
63699ebb4caSwyllys 	} else {
63799ebb4caSwyllys 		*ltime = 0;
63849e21299Sdinak 		return (-1);
63949e21299Sdinak 	}
64049e21299Sdinak 
64199ebb4caSwyllys 	return (0);
64299ebb4caSwyllys }
64349e21299Sdinak 
64499ebb4caSwyllys int
64599ebb4caSwyllys OT2Int(char *objclass)
64699ebb4caSwyllys {
64799ebb4caSwyllys 	char *c = NULL;
64899ebb4caSwyllys 	int retval = 0;
64949e21299Sdinak 
65099ebb4caSwyllys 	if (objclass == NULL)
65199ebb4caSwyllys 		return (-1);
65249e21299Sdinak 
65399ebb4caSwyllys 	c = strchr(objclass, ':');
65499ebb4caSwyllys 	if (c != NULL) {
655d00756ccSwyllys 		if (strcasecmp(c, ":private") == 0)
65699ebb4caSwyllys 			retval = PK_PRIVATE_OBJ;
657d00756ccSwyllys 		else if (strcasecmp(c, ":public") == 0)
65899ebb4caSwyllys 			retval = PK_PUBLIC_OBJ;
659d00756ccSwyllys 		else if (strcasecmp(c, ":both") == 0)
66099ebb4caSwyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
66199ebb4caSwyllys 		else /* unrecognized option */
66299ebb4caSwyllys 			return (-1);
66399ebb4caSwyllys 
66499ebb4caSwyllys 		*c = '\0';
66599ebb4caSwyllys 	}
66699ebb4caSwyllys 
667d00756ccSwyllys 	if (strcasecmp(objclass, "public") == 0) {
66899ebb4caSwyllys 		if (retval)
66999ebb4caSwyllys 			return (-1);
67030a5e8faSwyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
671d00756ccSwyllys 	} else if (strcasecmp(objclass, "private") == 0) {
67299ebb4caSwyllys 		if (retval)
67399ebb4caSwyllys 			return (-1);
67499ebb4caSwyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
675d00756ccSwyllys 	} else if (strcasecmp(objclass, "both") == 0) {
67699ebb4caSwyllys 		if (retval)
67799ebb4caSwyllys 			return (-1);
67899ebb4caSwyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
679d00756ccSwyllys 	} else if (strcasecmp(objclass, "cert") == 0) {
68099ebb4caSwyllys 		return (retval | PK_CERT_OBJ);
681d00756ccSwyllys 	} else if (strcasecmp(objclass, "key") == 0) {
68299ebb4caSwyllys 		if (retval == 0) /* return all keys */
68399ebb4caSwyllys 			return (retval | PK_KEY_OBJ);
68499ebb4caSwyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
68599ebb4caSwyllys 			/* return all keys */
68699ebb4caSwyllys 			return (retval | PK_KEY_OBJ);
68799ebb4caSwyllys 		else if (retval & PK_PUBLIC_OBJ)
68899ebb4caSwyllys 			/* Only return public keys */
68999ebb4caSwyllys 			return (retval | PK_PUBKEY_OBJ);
69099ebb4caSwyllys 		else if (retval & PK_PRIVATE_OBJ)
69199ebb4caSwyllys 			/* Only return private keys */
69299ebb4caSwyllys 			return (retval | PK_PRIKEY_OBJ);
693d00756ccSwyllys 	} else if (strcasecmp(objclass, "crl") == 0) {
69499ebb4caSwyllys 		if (retval)
69599ebb4caSwyllys 			return (-1);
69699ebb4caSwyllys 		return (retval | PK_CRL_OBJ);
69799ebb4caSwyllys 	}
69899ebb4caSwyllys 
69999ebb4caSwyllys 	if (retval == 0) /* No matches found */
70099ebb4caSwyllys 		retval = -1;
70199ebb4caSwyllys 	return (retval);
70249e21299Sdinak }
70349e21299Sdinak 
70499ebb4caSwyllys KMF_ENCODE_FORMAT
70599ebb4caSwyllys Str2Format(char *formstr)
7067c478bd9Sstevel@tonic-gate {
707d00756ccSwyllys 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
70899ebb4caSwyllys 		return (KMF_FORMAT_ASN1);
709d00756ccSwyllys 	if (strcasecmp(formstr, "pem") == 0)
71099ebb4caSwyllys 		return (KMF_FORMAT_PEM);
711d00756ccSwyllys 	if (strcasecmp(formstr, "pkcs12") == 0)
71299ebb4caSwyllys 		return (KMF_FORMAT_PKCS12);
713d00756ccSwyllys 	if (strcasecmp(formstr, "raw") == 0)
71430a5e8faSwyllys 		return (KMF_FORMAT_RAWKEY);
71599ebb4caSwyllys 
71699ebb4caSwyllys 	return (KMF_FORMAT_UNDEF);
71799ebb4caSwyllys }
7187c478bd9Sstevel@tonic-gate 
71999ebb4caSwyllys KMF_RETURN
720d00756ccSwyllys select_token(void *kmfhandle, char *token, int readonly)
72199ebb4caSwyllys {
72230a5e8faSwyllys 	KMF_ATTRIBUTE attlist[10];
72330a5e8faSwyllys 	int i = 0;
72430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
72599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
7267711facfSdinak 
72799ebb4caSwyllys 	if (token == NULL)
72899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
7297c478bd9Sstevel@tonic-gate 
73030a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
73130a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
73230a5e8faSwyllys 	    sizeof (kstype));
73330a5e8faSwyllys 	i++;
7347711facfSdinak 
73530a5e8faSwyllys 	if (token) {
73630a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
73730a5e8faSwyllys 		    KMF_TOKEN_LABEL_ATTR, token,
73830a5e8faSwyllys 		    strlen(token));
73930a5e8faSwyllys 		i++;
74030a5e8faSwyllys 	}
74130a5e8faSwyllys 
74230a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
74330a5e8faSwyllys 	    KMF_READONLY_ATTR, &readonly,
74430a5e8faSwyllys 	    sizeof (readonly));
74530a5e8faSwyllys 	i++;
74630a5e8faSwyllys 
74730a5e8faSwyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
74899ebb4caSwyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
74999ebb4caSwyllys 		rv = KMF_OK;
75099ebb4caSwyllys 	return (rv);
7517711facfSdinak }
7527711facfSdinak 
75399ebb4caSwyllys KMF_RETURN
75499ebb4caSwyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
7557711facfSdinak {
75630a5e8faSwyllys 	KMF_ATTRIBUTE attlist[10];
75730a5e8faSwyllys 	int i = 0;
75830a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
75999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
7607711facfSdinak 
76130a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
76230a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
76330a5e8faSwyllys 	    sizeof (kstype));
76430a5e8faSwyllys 	i++;
76530a5e8faSwyllys 
76630a5e8faSwyllys 	if (dir) {
76730a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
76830a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dir,
76930a5e8faSwyllys 		    strlen(dir));
77030a5e8faSwyllys 		i++;
77130a5e8faSwyllys 	}
77230a5e8faSwyllys 
77330a5e8faSwyllys 	if (prefix) {
77430a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
77530a5e8faSwyllys 		    KMF_CERTPREFIX_ATTR, prefix,
77630a5e8faSwyllys 		    strlen(prefix));
77730a5e8faSwyllys 		i++;
77830a5e8faSwyllys 
77930a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
78030a5e8faSwyllys 		    KMF_KEYPREFIX_ATTR, prefix,
78130a5e8faSwyllys 		    strlen(prefix));
78230a5e8faSwyllys 		i++;
78330a5e8faSwyllys 	}
7847711facfSdinak 
78530a5e8faSwyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
78699ebb4caSwyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
78799ebb4caSwyllys 		rv = KMF_OK;
7887c478bd9Sstevel@tonic-gate 
78999ebb4caSwyllys 	return (rv);
79099ebb4caSwyllys }
7917711facfSdinak 
79299ebb4caSwyllys KMF_RETURN
79399ebb4caSwyllys get_pk12_password(KMF_CREDENTIAL *cred)
79499ebb4caSwyllys {
79599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
79699ebb4caSwyllys 	char prompt[1024];
7977711facfSdinak 
7987711facfSdinak 	/*
79999ebb4caSwyllys 	 * Get the password to use for the PK12 encryption.
8007711facfSdinak 	 */
80199ebb4caSwyllys 	(void) strlcpy(prompt,
80230a5e8faSwyllys 	    gettext("Enter password to use for "
80330a5e8faSwyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
8047711facfSdinak 
80599ebb4caSwyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
80630a5e8faSwyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
80799ebb4caSwyllys 		cred->cred = NULL;
80899ebb4caSwyllys 		cred->credlen = 0;
8097711facfSdinak 	}
8107711facfSdinak 
8117711facfSdinak 	return (rv);
8127711facfSdinak }
8137711facfSdinak 
8142cbed729Swyllys #define	FILENAME_PROMPT gettext("Filename:")
8152cbed729Swyllys #define	FILENAME_MINLEN	1
8162cbed729Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
8172cbed729Swyllys 
8182cbed729Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
8192cbed729Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
8202cbed729Swyllys 	"[Some-State]:")
8212cbed729Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
8222cbed729Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
8232cbed729Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
8242cbed729Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
8252cbed729Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
8262cbed729Swyllys 
8272cbed729Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
8282cbed729Swyllys 	"0x01020304):")
8292cbed729Swyllys #define	SERNO_MINLEN	3
8302cbed729Swyllys #define	SERNO_MAXLEN	42
8312cbed729Swyllys 
8322cbed729Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
8332cbed729Swyllys #define	LABEL_MINLEN	1
8342cbed729Swyllys #define	LABEL_MAXLEN	1024
8357711facfSdinak 
83699ebb4caSwyllys #define	COUNTRY_DEFAULT "US"
8372cbed729Swyllys #define	STATE_DEFAULT	NULL
8382cbed729Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
8397711facfSdinak 
84099ebb4caSwyllys #define	SUBNAMESIZ	1024
84199ebb4caSwyllys #define	RDN_MIN		1
84299ebb4caSwyllys #define	RDN_MAX		64
84399ebb4caSwyllys #define	COUNTRYNAME_MIN	2
84499ebb4caSwyllys #define	COUNTRYNAME_MAX	2
8457711facfSdinak 
84699ebb4caSwyllys static char *
84799ebb4caSwyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
84899ebb4caSwyllys {
84999ebb4caSwyllys 	char buf[1024];
85099ebb4caSwyllys 	char *response = NULL;
85199ebb4caSwyllys 	char *ret = NULL;
85299ebb4caSwyllys 	int len;
8537711facfSdinak 
85499ebb4caSwyllys 	for (;;) {
85599ebb4caSwyllys 		(void) printf("\t%s", prompt);
85699ebb4caSwyllys 		(void) fflush(stdout);
85799ebb4caSwyllys 
85899ebb4caSwyllys 		response = fgets(buf, sizeof (buf), stdin);
85999ebb4caSwyllys 		if (response == NULL) {
86099ebb4caSwyllys 			if (default_str != NULL) {
86199ebb4caSwyllys 				ret = strdup(default_str);
86299ebb4caSwyllys 			}
86399ebb4caSwyllys 			break;
86499ebb4caSwyllys 		}
86599ebb4caSwyllys 
86699ebb4caSwyllys 		/* Skip any leading white space. */
86799ebb4caSwyllys 		while (isspace(*response))
86899ebb4caSwyllys 			response++;
86999ebb4caSwyllys 		if (*response == '\0') {
87099ebb4caSwyllys 			if (default_str != NULL) {
87199ebb4caSwyllys 				ret = strdup(default_str);
87299ebb4caSwyllys 			}
87399ebb4caSwyllys 			break;
87499ebb4caSwyllys 		}
87599ebb4caSwyllys 
87699ebb4caSwyllys 		len = strlen(response);
87799ebb4caSwyllys 		response[len-1] = '\0'; /* get rid of "LF" */
87899ebb4caSwyllys 		len--;
87999ebb4caSwyllys 		if (len >= min_len && len <= max_len) {
88099ebb4caSwyllys 			ret = strdup(response);
88199ebb4caSwyllys 			break;
8827711facfSdinak 		}
8837711facfSdinak 
88499ebb4caSwyllys 		(void) printf("%s\n", INVALID_INPUT);
88599ebb4caSwyllys 
8867711facfSdinak 	}
8877711facfSdinak 
88899ebb4caSwyllys 	return (ret);
88999ebb4caSwyllys }
8907711facfSdinak 
8912cbed729Swyllys int
8922cbed729Swyllys get_filename(char *txt, char **result)
8932cbed729Swyllys {
8942cbed729Swyllys 	char prompt[1024];
8952cbed729Swyllys 	char *fname = NULL;
8962cbed729Swyllys 
8972cbed729Swyllys 	(void) snprintf(prompt, sizeof (prompt),
8982cbed729Swyllys 	    gettext("Enter filename for the %s: "),
8992cbed729Swyllys 	    txt);
9002cbed729Swyllys 	fname = get_input_string(prompt, NULL,
9012cbed729Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
9022cbed729Swyllys 	*result = fname;
9032cbed729Swyllys 	return (0);
9042cbed729Swyllys }
9052cbed729Swyllys 
9062cbed729Swyllys int
9072cbed729Swyllys get_certlabel(char **result)
9082cbed729Swyllys {
9092cbed729Swyllys 	char *label = NULL;
9102cbed729Swyllys 
9112cbed729Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
9122cbed729Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
9132cbed729Swyllys 	*result = label;
9142cbed729Swyllys 	return (0);
9152cbed729Swyllys }
9162cbed729Swyllys 
9172cbed729Swyllys int
9182cbed729Swyllys get_serial(char **result)
9192cbed729Swyllys {
9202cbed729Swyllys 	char *serial = NULL;
9212cbed729Swyllys 
9222cbed729Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
9232cbed729Swyllys 	    SERNO_MAXLEN);
9242cbed729Swyllys 
9252cbed729Swyllys 	*result = serial;
9262cbed729Swyllys 	return (0);
9272cbed729Swyllys }
9282cbed729Swyllys 
92999ebb4caSwyllys int
93099ebb4caSwyllys get_subname(char **result)
93199ebb4caSwyllys {
93299ebb4caSwyllys 	char *country = NULL;
93399ebb4caSwyllys 	char *state = NULL;
93499ebb4caSwyllys 	char *locality = NULL;
93599ebb4caSwyllys 	char *org = NULL;
93699ebb4caSwyllys 	char *unit = NULL;
93799ebb4caSwyllys 	char *name = NULL;
93899ebb4caSwyllys 	char *email = NULL;
93999ebb4caSwyllys 	char *subname = NULL;
94099ebb4caSwyllys 
94199ebb4caSwyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
94299ebb4caSwyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
94399ebb4caSwyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
94499ebb4caSwyllys 	if (country == NULL)
94599ebb4caSwyllys 		return (-1);
94699ebb4caSwyllys 
94799ebb4caSwyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
94899ebb4caSwyllys 	    RDN_MIN, RDN_MAX);
9497711facfSdinak 
95099ebb4caSwyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
95199ebb4caSwyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
95299ebb4caSwyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
95399ebb4caSwyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
95499ebb4caSwyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
9557711facfSdinak 
95699ebb4caSwyllys 	/* Now create a subject name from the input strings */
95799ebb4caSwyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
95899ebb4caSwyllys 		goto out;
95999ebb4caSwyllys 
96099ebb4caSwyllys 	(void) memset(subname, 0, SUBNAMESIZ);
96199ebb4caSwyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
96299ebb4caSwyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
9632cbed729Swyllys 	if (state != NULL) {
9642cbed729Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
9652cbed729Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
9662cbed729Swyllys 	}
9677711facfSdinak 
9682cbed729Swyllys 	if (locality != NULL) {
9692cbed729Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
97099ebb4caSwyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
9717711facfSdinak 	}
9727711facfSdinak 
9732cbed729Swyllys 	if (org != NULL) {
9742cbed729Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
97599ebb4caSwyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
9767711facfSdinak 	}
9777711facfSdinak 
9782cbed729Swyllys 	if (unit != NULL) {
9792cbed729Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
98099ebb4caSwyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
98199ebb4caSwyllys 	}
9827711facfSdinak 
9832cbed729Swyllys 	if (name != NULL) {
9842cbed729Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
98599ebb4caSwyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
9867711facfSdinak 	}
9877711facfSdinak 
9882cbed729Swyllys 	if (email != NULL) {
9892cbed729Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
99099ebb4caSwyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 
99399ebb4caSwyllys out:
99499ebb4caSwyllys 	if (country)
99599ebb4caSwyllys 		free(country);
99699ebb4caSwyllys 	if (state)
99799ebb4caSwyllys 		free(state);
99899ebb4caSwyllys 	if (locality)
99999ebb4caSwyllys 		free(locality);
100099ebb4caSwyllys 	if (org)
100199ebb4caSwyllys 		free(org);
100299ebb4caSwyllys 	if (unit)
100399ebb4caSwyllys 		free(unit);
100499ebb4caSwyllys 	if (name)
100599ebb4caSwyllys 		free(name);
100699ebb4caSwyllys 	if (email)
100799ebb4caSwyllys 		free(email);
100899ebb4caSwyllys 
100999ebb4caSwyllys 	if (subname == NULL)
101099ebb4caSwyllys 		return (-1);
101199ebb4caSwyllys 	else {
101299ebb4caSwyllys 		*result = subname;
101399ebb4caSwyllys 		return (0);
10147711facfSdinak 	}
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate /*
101899ebb4caSwyllys  * Parse a string of KeyUsage values and convert
101999ebb4caSwyllys  * them to the correct KU Bits.
102099ebb4caSwyllys  * The field may be marked "critical" by prepending
102199ebb4caSwyllys  * "critical:" to the list.
102299ebb4caSwyllys  * EX:  critical:digitialSignature,keyEncipherment
10237c478bd9Sstevel@tonic-gate  */
102499ebb4caSwyllys KMF_RETURN
102599ebb4caSwyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
10267c478bd9Sstevel@tonic-gate {
102799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
102899ebb4caSwyllys 	uint16_t kuval;
102999ebb4caSwyllys 	char *k;
103099ebb4caSwyllys 
103199ebb4caSwyllys 	*kubits = 0;
1032d00756ccSwyllys 	if (kustr == NULL || strlen(kustr) == 0)
103399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
103499ebb4caSwyllys 
103599ebb4caSwyllys 	/* Check to see if this is critical */
1036d00756ccSwyllys 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
103799ebb4caSwyllys 		*critical = TRUE;
103899ebb4caSwyllys 		kustr += strlen("critical:");
103999ebb4caSwyllys 	} else {
104099ebb4caSwyllys 		*critical = FALSE;
10417c478bd9Sstevel@tonic-gate 	}
10427711facfSdinak 
104399ebb4caSwyllys 	k = strtok(kustr, ",");
104499ebb4caSwyllys 	while (k != NULL) {
104530a5e8faSwyllys 		kuval = kmf_string_to_ku(k);
104699ebb4caSwyllys 		if (kuval == 0) {
104799ebb4caSwyllys 			*kubits = 0;
104899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
10497711facfSdinak 		}
105099ebb4caSwyllys 		*kubits |= kuval;
105199ebb4caSwyllys 		k = strtok(NULL, ",");
10527711facfSdinak 	}
10537711facfSdinak 
105499ebb4caSwyllys 	return (ret);
10557711facfSdinak }
10567711facfSdinak 
10577711facfSdinak /*
105899ebb4caSwyllys  * Verify the alternate subject label is real or invalid.
105999ebb4caSwyllys  *
106099ebb4caSwyllys  * The field may be marked "critical" by prepending
106199ebb4caSwyllys  * "critical:" to the list.
106299ebb4caSwyllys  * EX:  "critical:IP=1.2.3.4"
10637711facfSdinak  */
106499ebb4caSwyllys KMF_RETURN
106599ebb4caSwyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
10667711facfSdinak {
106799ebb4caSwyllys 	char *p;
106899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
10697711facfSdinak 
107099ebb4caSwyllys 	/* Check to see if this is critical */
1071d00756ccSwyllys 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
107299ebb4caSwyllys 		*critical = TRUE;
107399ebb4caSwyllys 		arg += strlen("critical:");
107499ebb4caSwyllys 	} else {
107599ebb4caSwyllys 		*critical = FALSE;
107699ebb4caSwyllys 	}
10777711facfSdinak 
107899ebb4caSwyllys 	/* Make sure there is an "=" sign */
107999ebb4caSwyllys 	p = strchr(arg, '=');
108099ebb4caSwyllys 	if (p == NULL)
108199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
10827711facfSdinak 
108399ebb4caSwyllys 	p[0] = '\0';
108499ebb4caSwyllys 
108599ebb4caSwyllys 	if (strcmp(arg, "IP") == 0)
108699ebb4caSwyllys 		*type = GENNAME_IPADDRESS;
108799ebb4caSwyllys 	else if (strcmp(arg, "DNS") == 0)
108899ebb4caSwyllys 		*type = GENNAME_DNSNAME;
108999ebb4caSwyllys 	else if (strcmp(arg, "EMAIL") == 0)
109099ebb4caSwyllys 		*type = GENNAME_RFC822NAME;
109199ebb4caSwyllys 	else if (strcmp(arg, "URI") == 0)
109299ebb4caSwyllys 		*type = GENNAME_URI;
109399ebb4caSwyllys 	else if (strcmp(arg, "DN") == 0)
109499ebb4caSwyllys 		*type = GENNAME_DIRECTORYNAME;
109599ebb4caSwyllys 	else if (strcmp(arg, "RID") == 0)
109699ebb4caSwyllys 		*type = GENNAME_REGISTEREDID;
1097d00756ccSwyllys 	else if (strcmp(arg, "KRB") == 0)
1098d00756ccSwyllys 		*type = GENNAME_KRB5PRINC;
1099d00756ccSwyllys 	else if (strcmp(arg, "UPN") == 0)
1100d00756ccSwyllys 		*type = GENNAME_SCLOGON_UPN;
110199ebb4caSwyllys 	else
110299ebb4caSwyllys 		rv = KMF_ERR_BAD_PARAMETER;
110399ebb4caSwyllys 
110499ebb4caSwyllys 	p[0] = '=';
110599ebb4caSwyllys 
110699ebb4caSwyllys 	return (rv);
11077c478bd9Sstevel@tonic-gate }
110849e21299Sdinak 
110999ebb4caSwyllys int
111099ebb4caSwyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
111199ebb4caSwyllys 	char *token_spec, KMF_CREDENTIAL *cred)
111249e21299Sdinak {
111399ebb4caSwyllys 	char	prompt[1024];
111472ca8cc9SWyllys Ingersoll 	char	temptoken[32];
111599ebb4caSwyllys 	char	*p = NULL;
111672ca8cc9SWyllys Ingersoll 	char	*t = NULL;
111747e946e7SWyllys Ingersoll 	int	len;
111849e21299Sdinak 
111947e946e7SWyllys Ingersoll 	(void) memset(temptoken, 0, sizeof (temptoken));
112099ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
112199ebb4caSwyllys 		p = strchr(token_spec, ':');
112299ebb4caSwyllys 		if (p != NULL)
112372ca8cc9SWyllys Ingersoll 			*p = 0;
112472ca8cc9SWyllys Ingersoll 	}
112547e946e7SWyllys Ingersoll 	len = strlen(token_spec);
112647e946e7SWyllys Ingersoll 	if (len > sizeof (temptoken))
112747e946e7SWyllys Ingersoll 		len = sizeof (temptoken);
112847e946e7SWyllys Ingersoll 
112947e946e7SWyllys Ingersoll 	(void) strncpy(temptoken, token_spec, len);
113072ca8cc9SWyllys Ingersoll 
113172ca8cc9SWyllys Ingersoll 	/*
113272ca8cc9SWyllys Ingersoll 	 * Strip trailing whitespace
113372ca8cc9SWyllys Ingersoll 	 */
113447e946e7SWyllys Ingersoll 	t = temptoken + (len - 1);
113572ca8cc9SWyllys Ingersoll 	while (isspace(*t) && t >= temptoken) {
113672ca8cc9SWyllys Ingersoll 		*t = 0x00;
113772ca8cc9SWyllys Ingersoll 		t--;
113899ebb4caSwyllys 	}
113972ca8cc9SWyllys Ingersoll 
114049e21299Sdinak 	/*
114199ebb4caSwyllys 	 * Login to the token first.
114249e21299Sdinak 	 */
114399ebb4caSwyllys 	(void) snprintf(prompt, sizeof (prompt),
114472ca8cc9SWyllys Ingersoll 	    gettext(DEFAULT_TOKEN_PROMPT), temptoken);
114549e21299Sdinak 
114699ebb4caSwyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
114730a5e8faSwyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
114899ebb4caSwyllys 		cred->cred = NULL;
114999ebb4caSwyllys 		cred->credlen = 0;
115049e21299Sdinak 	}
115149e21299Sdinak 
115299ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
115399ebb4caSwyllys 		*p = ':';
115499ebb4caSwyllys 	return (KMF_OK);
115549e21299Sdinak }
115649e21299Sdinak 
115799ebb4caSwyllys KMF_RETURN
115899ebb4caSwyllys verify_file(char *filename)
115949e21299Sdinak {
116099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
116199ebb4caSwyllys 	int fd;
116249e21299Sdinak 
116399ebb4caSwyllys 	/*
116499ebb4caSwyllys 	 * Attempt to open with  the EXCL flag so that if
116599ebb4caSwyllys 	 * it already exists, the open will fail.  It will
116699ebb4caSwyllys 	 * also fail if the file cannot be created due to
116799ebb4caSwyllys 	 * permissions on the parent directory, or if the
116899ebb4caSwyllys 	 * parent directory itself does not exist.
116999ebb4caSwyllys 	 */
117099ebb4caSwyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
117199ebb4caSwyllys 	if (fd == -1)
117299ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
117349e21299Sdinak 
117499ebb4caSwyllys 	/* If we were able to create it, delete it. */
117599ebb4caSwyllys 	(void) close(fd);
117699ebb4caSwyllys 	(void) unlink(filename);
117749e21299Sdinak 
117899ebb4caSwyllys 	return (ret);
117999ebb4caSwyllys }
118049e21299Sdinak 
118199ebb4caSwyllys void
118299ebb4caSwyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
118399ebb4caSwyllys {
118499ebb4caSwyllys 	KMF_RETURN rv1, rv2;
118599ebb4caSwyllys 	char *plugin_errmsg = NULL;
118699ebb4caSwyllys 	char *kmf_errmsg = NULL;
118749e21299Sdinak 
118830a5e8faSwyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
118930a5e8faSwyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
119049e21299Sdinak 
119199ebb4caSwyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
119299ebb4caSwyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
119330a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
119430a5e8faSwyllys 		    plugin_errmsg);
119530a5e8faSwyllys 		kmf_free_str(plugin_errmsg);
119699ebb4caSwyllys 	}
119749e21299Sdinak 
119899ebb4caSwyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
119930a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
120030a5e8faSwyllys 		    kmf_errmsg);
120130a5e8faSwyllys 		kmf_free_str(kmf_errmsg);
120249e21299Sdinak 	}
120349e21299Sdinak 
120499ebb4caSwyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
120599ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
120699ebb4caSwyllys 
120749e21299Sdinak }
1208d00756ccSwyllys 
1209d00756ccSwyllys static KMF_RETURN
1210d00756ccSwyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
1211d00756ccSwyllys {
1212d00756ccSwyllys 	if (newoid != NULL && ekus != NULL) {
1213d00756ccSwyllys 		ekus->eku_count++;
1214d00756ccSwyllys 
1215d00756ccSwyllys 		ekus->critlist = realloc(ekus->critlist,
1216d00756ccSwyllys 		    ekus->eku_count * sizeof (int));
1217d00756ccSwyllys 		if (ekus->critlist != NULL)
1218d00756ccSwyllys 			ekus->critlist[ekus->eku_count-1] = critical;
1219d00756ccSwyllys 		else
1220d00756ccSwyllys 			return (KMF_ERR_MEMORY);
1221d00756ccSwyllys 
1222d00756ccSwyllys 		ekus->ekulist = realloc(
1223d00756ccSwyllys 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
1224d00756ccSwyllys 		if (ekus->ekulist != NULL)
1225d00756ccSwyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
1226d00756ccSwyllys 		else
1227d00756ccSwyllys 			return (KMF_ERR_MEMORY);
1228d00756ccSwyllys 	}
1229d00756ccSwyllys 	return (KMF_OK);
1230d00756ccSwyllys }
1231d00756ccSwyllys 
1232d00756ccSwyllys void
1233d00756ccSwyllys free_eku_list(EKU_LIST *ekus)
1234d00756ccSwyllys {
1235d00756ccSwyllys 	if (ekus != NULL && ekus->eku_count > 0) {
1236d00756ccSwyllys 		int i;
1237d00756ccSwyllys 		for (i = 0; i < ekus->eku_count; i++) {
1238d00756ccSwyllys 			kmf_free_data(&ekus->ekulist[i]);
1239d00756ccSwyllys 		}
1240d00756ccSwyllys 		free(ekus->ekulist);
1241d00756ccSwyllys 		free(ekus->critlist);
124256664548SWyllys Ingersoll 		free(ekus);
1243d00756ccSwyllys 	}
1244d00756ccSwyllys }
1245d00756ccSwyllys 
1246d00756ccSwyllys static KMF_RETURN
1247d00756ccSwyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
1248d00756ccSwyllys {
1249d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
1250d00756ccSwyllys 	KMF_OID *newoid;
1251d00756ccSwyllys 	int critical;
1252d00756ccSwyllys 
1253d00756ccSwyllys 	if (strncasecmp(ekustr, "critical:",
1254d00756ccSwyllys 	    strlen("critical:")) == 0) {
1255d00756ccSwyllys 		critical = TRUE;
1256d00756ccSwyllys 		ekustr += strlen("critical:");
1257d00756ccSwyllys 	} else {
1258d00756ccSwyllys 		critical = FALSE;
1259d00756ccSwyllys 	}
1260d00756ccSwyllys 	newoid = kmf_ekuname_to_oid(ekustr);
1261d00756ccSwyllys 	if (newoid != NULL) {
1262d00756ccSwyllys 		rv = addToEKUList(ekus, critical, newoid);
1263d00756ccSwyllys 		free(newoid);
1264d00756ccSwyllys 	} else {
1265d00756ccSwyllys 		rv = PK_ERR_USAGE;
1266d00756ccSwyllys 	}
1267d00756ccSwyllys 
1268d00756ccSwyllys 	return (rv);
1269d00756ccSwyllys }
1270d00756ccSwyllys 
1271d00756ccSwyllys KMF_RETURN
1272d00756ccSwyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
1273d00756ccSwyllys {
1274d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
1275d00756ccSwyllys 	char *p;
1276d00756ccSwyllys 	EKU_LIST *ekus = NULL;
1277d00756ccSwyllys 
1278d00756ccSwyllys 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
1279d00756ccSwyllys 		return (0);
1280d00756ccSwyllys 
128156664548SWyllys Ingersoll 	ekus = calloc(sizeof (EKU_LIST), 1);
128256664548SWyllys Ingersoll 	if (ekus == NULL)
128356664548SWyllys Ingersoll 		return (KMF_ERR_MEMORY);
128456664548SWyllys Ingersoll 
1285d00756ccSwyllys 	/*
1286d00756ccSwyllys 	 * The list should be comma separated list of EKU Names.
1287d00756ccSwyllys 	 */
1288d00756ccSwyllys 	p = strtok(ekuliststr, ",");
1289d00756ccSwyllys 
1290d00756ccSwyllys 	/* If no tokens found, then maybe it's just a single EKU value */
1291d00756ccSwyllys 	if (p == NULL) {
1292d00756ccSwyllys 		rv = parse_ekus(ekuliststr, ekus);
1293d00756ccSwyllys 	}
1294d00756ccSwyllys 
1295d00756ccSwyllys 	while (p != NULL) {
1296d00756ccSwyllys 		rv = parse_ekus(p, ekus);
1297d00756ccSwyllys 
1298d00756ccSwyllys 		if (rv != KMF_OK)
1299d00756ccSwyllys 			break;
1300d00756ccSwyllys 		p = strtok(NULL, ",");
1301d00756ccSwyllys 	}
1302d00756ccSwyllys 
1303d00756ccSwyllys 	if (rv != KMF_OK)
1304d00756ccSwyllys 		free_eku_list(ekus);
1305d00756ccSwyllys 	else
1306d00756ccSwyllys 		*ekulist = ekus;
1307d00756ccSwyllys 
1308d00756ccSwyllys 	return (rv);
1309d00756ccSwyllys }
1310fa60c371Swyllys 
1311fa60c371Swyllys KMF_RETURN
1312fa60c371Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
1313fa60c371Swyllys {
1314fa60c371Swyllys 	CK_TOKEN_INFO info;
1315fa60c371Swyllys 	CK_SLOT_ID slot;
1316fa60c371Swyllys 	CK_RV ckrv;
1317fa60c371Swyllys 	KMF_RETURN rv;
1318fa60c371Swyllys 
1319fa60c371Swyllys 	*auth = 0;
1320fa60c371Swyllys 	rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
1321fa60c371Swyllys 	if (rv != KMF_OK)
1322fa60c371Swyllys 		return (rv);
1323fa60c371Swyllys 
1324fa60c371Swyllys 	ckrv = C_GetTokenInfo(slot, &info);
1325fa60c371Swyllys 	if (ckrv != KMF_OK)
1326fa60c371Swyllys 		return (KMF_ERR_INTERNAL);
1327fa60c371Swyllys 
1328fa60c371Swyllys 	*auth = (info.flags & CKF_LOGIN_REQUIRED);
1329fa60c371Swyllys 
1330fa60c371Swyllys 	return (KMF_OK);
1331fa60c371Swyllys }
1332*e65e5c2dSWyllys Ingersoll 
1333*e65e5c2dSWyllys Ingersoll void
1334*e65e5c2dSWyllys Ingersoll show_ecc_curves()
1335*e65e5c2dSWyllys Ingersoll {
1336*e65e5c2dSWyllys Ingersoll 	int i;
1337*e65e5c2dSWyllys Ingersoll 
1338*e65e5c2dSWyllys Ingersoll 	(void) printf(gettext("Supported ECC curve names:\n"));
1339*e65e5c2dSWyllys Ingersoll 	for (i = 0; i < number_of_curves; i++) {
1340*e65e5c2dSWyllys Ingersoll 		(void) printf("%s", oid_table[i].name);
1341*e65e5c2dSWyllys Ingersoll 		if (i > 0 && ((i+1) % 5) == 0)
1342*e65e5c2dSWyllys Ingersoll 			(void) printf("\n");
1343*e65e5c2dSWyllys Ingersoll 		else if (i+1 < number_of_curves)
1344*e65e5c2dSWyllys Ingersoll 			(void) printf(", ");
1345*e65e5c2dSWyllys Ingersoll 	}
1346*e65e5c2dSWyllys Ingersoll 	(void) printf("\n");
1347*e65e5c2dSWyllys Ingersoll }
1348*e65e5c2dSWyllys Ingersoll 
1349*e65e5c2dSWyllys Ingersoll KMF_OID *
1350*e65e5c2dSWyllys Ingersoll ecc_name_to_oid(char *name)
1351*e65e5c2dSWyllys Ingersoll {
1352*e65e5c2dSWyllys Ingersoll 	int i;
1353*e65e5c2dSWyllys Ingersoll 	for (i = 0; i < number_of_oids; i++) {
1354*e65e5c2dSWyllys Ingersoll 		if (strcasecmp(name, oid_table[i].name) == 0)
1355*e65e5c2dSWyllys Ingersoll 			return ((KMF_OID *)oid_table[i].oid);
1356*e65e5c2dSWyllys Ingersoll 	}
1357*e65e5c2dSWyllys Ingersoll 	return (NULL);
1358*e65e5c2dSWyllys Ingersoll }
1359