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
202c9a247fSWyllys Ingersoll  *
212c9a247fSWyllys Ingersoll  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
227c478bd9Sstevel@tonic-gate  */
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate  * This file contains the functions that are shared among
267c478bd9Sstevel@tonic-gate  * the various services this tool will ultimately provide.
277711facfSdinak  * The functions in this file return PKCS#11 CK_RV errors.
287711facfSdinak  * Only one session and one login per token is supported
297711facfSdinak  * at this time.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <ctype.h>
3699ebb4caSwyllys #include <sys/types.h>
3799ebb4caSwyllys #include <sys/stat.h>
3899ebb4caSwyllys #include <fcntl.h>
3999ebb4caSwyllys #include <tzfile.h>
407c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
417c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
4299ebb4caSwyllys #include <kmfapi.h>
437c478bd9Sstevel@tonic-gate 
4499ebb4caSwyllys #include "common.h"
457711facfSdinak 
467711facfSdinak /* Local status variables. */
477711facfSdinak static boolean_t	initialized = B_FALSE;
487711facfSdinak static boolean_t	session_opened = B_FALSE;
497711facfSdinak static boolean_t	logged_in = B_FALSE;
507c478bd9Sstevel@tonic-gate 
5149e21299Sdinak /* Supporting structures and global variables for getopt_av(). */
5249e21299Sdinak typedef struct	av_opts_s {
5349e21299Sdinak 	int		shortnm;	/* short name character */
5449e21299Sdinak 	char		*longnm;	/* long name string, NOT terminated */
5549e21299Sdinak 	int		longnm_len;	/* length of long name string */
5649e21299Sdinak 	boolean_t	has_arg;	/* takes optional argument */
5749e21299Sdinak } av_opts;
5849e21299Sdinak static av_opts		*opts_av = NULL;
5949e21299Sdinak static const char	*_save_optstr = NULL;
6049e21299Sdinak static int		_save_numopts = 0;
6149e21299Sdinak 
6249e21299Sdinak int			optind_av = 1;
6349e21299Sdinak char			*optarg_av = NULL;
6449e21299Sdinak 
6599ebb4caSwyllys static void close_sess(CK_SESSION_HANDLE);
6699ebb4caSwyllys static void logout_token(CK_SESSION_HANDLE);
6799ebb4caSwyllys 
68e65e5c2dSWyllys Ingersoll struct oid_table_entry {
69e65e5c2dSWyllys Ingersoll 	const KMF_OID *oid;
70e65e5c2dSWyllys Ingersoll 	char *name;
71e65e5c2dSWyllys Ingersoll };
72e65e5c2dSWyllys Ingersoll 
73e65e5c2dSWyllys Ingersoll struct oid_table_entry oid_table[] = {
74e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp112r1, "secp112r1"},
75e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp112r2, "secp112r2"},
76e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp128r1, "secp128r1"},
77e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp128r2, "secp128r2"},
78e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160k1, "secp160k1"},
79e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160r1, "secp160r1"},
80e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp160r2, "secp160r2"},
81e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp192k1, "secp192k1"},
82e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp192r1, "secp192r1"},
83e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp224k1, "secp224k1"},
84e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp224r1, "secp224r1"},
85e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp256k1, "secp256k1"},
86e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp256r1, "secp256r1"},
87e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp384r1, "secp384r1"},
88e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_secp521r1, "secp521r1"},
89e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect113r1, "sect113r1"},
90e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect113r2, "sect113r2"},
91e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect131r1, "sect131r1"},
92e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect131r2, "sect131r2"},
93e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163k1, "sect163k1"},
94e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163r1, "sect163r1"},
95e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect163r2, "sect163r2"},
96e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect193r1, "sect193r1"},
97e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect193r2, "sect193r2"},
98e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect233k1, "sect233k1"},
99e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect233r1, "sect233r1"},
100e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect239k1, "sect239k1"},
101e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect283k1, "sect283k1"},
102e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect283r1, "sect283r1"},
103e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect409k1, "sect409k1"},
104e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect409r1, "sect409r1"},
105e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect571k1, "sect571k1"},
106e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_sect571r1, "sect571r1"},
107e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
108e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
109e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
110e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
111e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
112e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
113e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
114e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
115e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
116e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
117e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
118e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
119e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
120e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
121e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
122e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
123e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_prime192v2, "prime192v2"},
124e65e5c2dSWyllys Ingersoll 	{ &KMFOID_ECC_prime192v3, "prime192v3"},
125e65e5c2dSWyllys Ingersoll 	{ &KMFOID_MD5, "md5"},
126e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA1, "sha1"},
127e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA256, "sha256"},
128e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA384, "sha384"},
129e65e5c2dSWyllys Ingersoll 	{ &KMFOID_SHA512, "sha512"}
130e65e5c2dSWyllys Ingersoll };
131e65e5c2dSWyllys Ingersoll int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
132e65e5c2dSWyllys Ingersoll #define	number_of_curves (number_of_oids - 5)
133e65e5c2dSWyllys Ingersoll 
1347c478bd9Sstevel@tonic-gate /*
1357711facfSdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
1367711facfSdinak  * along with setting/resetting state variables.
1377c478bd9Sstevel@tonic-gate  */
138448b8615Swyllys static CK_RV
init_pkcs11(void)139448b8615Swyllys init_pkcs11(void)
1407c478bd9Sstevel@tonic-gate {
1417711facfSdinak 	CK_RV		rv = CKR_OK;
1427711facfSdinak 
1437711facfSdinak 	/* If C_Initialize() already called, nothing to do here. */
1447711facfSdinak 	if (initialized == B_TRUE)
1457711facfSdinak 		return (CKR_OK);
1467c478bd9Sstevel@tonic-gate 
1477711facfSdinak 	/* Reset state variables because C_Initialize() not yet done. */
1487711facfSdinak 	session_opened = B_FALSE;
1497711facfSdinak 	logged_in = B_FALSE;
1507c478bd9Sstevel@tonic-gate 
1517711facfSdinak 	/* Initialize PKCS#11 library. */
1527711facfSdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
1537711facfSdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
1547711facfSdinak 		return (rv);
1557711facfSdinak 	}
1567c478bd9Sstevel@tonic-gate 
1577711facfSdinak 	initialized = B_TRUE;
1587711facfSdinak 	return (CKR_OK);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate /*
1627711facfSdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
1637711facfSdinak  * if any, are closed, and thereby any logins are logged out also.
1647c478bd9Sstevel@tonic-gate  */
1657711facfSdinak void
final_pk11(CK_SESSION_HANDLE sess)1667711facfSdinak final_pk11(CK_SESSION_HANDLE sess)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 
1697711facfSdinak 	/* If the library wasn't initialized, nothing to do here. */
1707711facfSdinak 	if (!initialized)
1717711facfSdinak 		return;
1727c478bd9Sstevel@tonic-gate 
1737711facfSdinak 	/* Make sure the sesion is closed first. */
1747711facfSdinak 	close_sess(sess);
1757711facfSdinak 
1767711facfSdinak 	(void) C_Finalize(NULL);
1777711facfSdinak 	initialized = B_FALSE;
1787711facfSdinak }
1797711facfSdinak 
1807711facfSdinak /*
1817711facfSdinak  * Close PKCS#11 session and reset state variables.  Any logins are
1827711facfSdinak  * logged out.
1837711facfSdinak  */
18499ebb4caSwyllys static void
close_sess(CK_SESSION_HANDLE sess)1857711facfSdinak close_sess(CK_SESSION_HANDLE sess)
1867711facfSdinak {
1877711facfSdinak 
188*6f2b04a2SToomas Soome 	if (sess == 0) {
1897711facfSdinak 		return;
1907711facfSdinak 	}
1917711facfSdinak 
1927711facfSdinak 	/* If session is already closed, nothing to do here. */
1937711facfSdinak 	if (!session_opened)
1947711facfSdinak 		return;
1957711facfSdinak 
1967711facfSdinak 	/* Make sure user is logged out of token. */
1977711facfSdinak 	logout_token(sess);
1987711facfSdinak 
1997711facfSdinak 	(void) C_CloseSession(sess);
2007711facfSdinak 	session_opened = B_FALSE;
2017711facfSdinak }
2027711facfSdinak 
2037711facfSdinak /*
2047711facfSdinak  * Log user out of token and reset status variable.
2057711facfSdinak  */
20699ebb4caSwyllys static void
logout_token(CK_SESSION_HANDLE sess)2077711facfSdinak logout_token(CK_SESSION_HANDLE sess)
2087711facfSdinak {
2097711facfSdinak 
210*6f2b04a2SToomas Soome 	if (sess == 0) {
2117711facfSdinak 		return;
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 
2147711facfSdinak 	/* If already logged out, nothing to do here. */
2157711facfSdinak 	if (!logged_in)
2167711facfSdinak 		return;
2177711facfSdinak 
2187711facfSdinak 	(void) C_Logout(sess);
2197711facfSdinak 	logged_in = B_FALSE;
2207711facfSdinak }
2217711facfSdinak 
2227711facfSdinak /*
2237711facfSdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
2247711facfSdinak  * If two prompts are given, the PIN is confirmed with second prompt.
2257711facfSdinak  * Note that getphassphrase() may return data in static memory area.
2267711facfSdinak  */
2277711facfSdinak CK_RV
get_pin(char * prompt1,char * prompt2,CK_UTF8CHAR_PTR * pin,CK_ULONG * pinlen)2287711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
2297711facfSdinak {
230d00756ccSwyllys 	char *save_phrase, *phrase1, *phrase2;
2317711facfSdinak 
2327711facfSdinak 	/* Prompt user for a PIN. */
2337711facfSdinak 	if (prompt1 == NULL) {
2347711facfSdinak 		return (CKR_ARGUMENTS_BAD);
2357711facfSdinak 	}
2367711facfSdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
2377711facfSdinak 		return (CKR_FUNCTION_FAILED);
2387711facfSdinak 	}
2397711facfSdinak 
2407711facfSdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
2417711facfSdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
2427711facfSdinak 		return (CKR_HOST_MEMORY);
2437711facfSdinak 
2447711facfSdinak 	/* If second prompt given, PIN confirmation is requested. */
2457711facfSdinak 	if (prompt2 != NULL) {
2467711facfSdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
2477711facfSdinak 			free(save_phrase);
2487711facfSdinak 			return (CKR_FUNCTION_FAILED);
2497711facfSdinak 		}
2507711facfSdinak 		if (strcmp(save_phrase, phrase2) != 0) {
2517711facfSdinak 			free(save_phrase);
2527711facfSdinak 			return (CKR_PIN_INCORRECT);
2537711facfSdinak 		}
2547711facfSdinak 	}
2557711facfSdinak 
2567711facfSdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
2577711facfSdinak 	*pinlen = strlen(save_phrase);
2587711facfSdinak 	return (CKR_OK);
2597711facfSdinak }
2607711facfSdinak 
261d00756ccSwyllys int
yn_to_int(char * ynstr)262d00756ccSwyllys yn_to_int(char *ynstr)
263d00756ccSwyllys {
264d00756ccSwyllys 	char *y = gettext("yes");
265d00756ccSwyllys 	char *n = gettext("no");
266d00756ccSwyllys 	if (ynstr == NULL)
267d00756ccSwyllys 		return (-1);
268d00756ccSwyllys 
269d00756ccSwyllys 	if (strncasecmp(ynstr, y, 1) == 0)
270d00756ccSwyllys 		return (1);
271d00756ccSwyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
272d00756ccSwyllys 		return (0);
273d00756ccSwyllys 	else
274d00756ccSwyllys 		return (-1);
275d00756ccSwyllys }
276d00756ccSwyllys 
2777711facfSdinak /*
2787711facfSdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
2797711facfSdinak  * default prompt is used.  If not message for invalid input is supplied,
2807711facfSdinak  * a default will not be provided.  If the user provides no response,
2817711facfSdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
2827711facfSdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
2837711facfSdinak  */
2847711facfSdinak boolean_t
yesno(char * prompt,char * invalid,boolean_t dflt)2857711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt)
2867711facfSdinak {
287d00756ccSwyllys 	char	*response, buf[1024];
288d00756ccSwyllys 	int	ans;
2897711facfSdinak 
2907711facfSdinak 	if (prompt == NULL)
2917711facfSdinak 		prompt = gettext("Enter (y)es or (n)o? ");
2927711facfSdinak 
2937711facfSdinak 	for (;;) {
2947711facfSdinak 		/* Prompt user. */
2957711facfSdinak 		(void) printf("%s", prompt);
2967711facfSdinak 		(void) fflush(stdout);
2977711facfSdinak 
2987711facfSdinak 		/* Get the response. */
2997711facfSdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
3007711facfSdinak 			break;		/* go to default response */
3017711facfSdinak 
3027711facfSdinak 		/* Skip any leading white space. */
3037711facfSdinak 		while (isspace(*response))
3047711facfSdinak 			response++;
3057711facfSdinak 		if (*response == '\0')
3067711facfSdinak 			break;		/* go to default response */
3077711facfSdinak 
308d00756ccSwyllys 		ans = yn_to_int(response);
309d00756ccSwyllys 		if (ans == 1)
3107711facfSdinak 			return (B_TRUE);
311d00756ccSwyllys 		else if (ans == 0)
3127711facfSdinak 			return (B_FALSE);
3137711facfSdinak 
3147711facfSdinak 		/* Indicate invalid input, and try again. */
3157711facfSdinak 		if (invalid != NULL)
31630a5e8faSwyllys 			(void) printf("%s", invalid);
3177711facfSdinak 	}
3187711facfSdinak 	return (dflt);
3197711facfSdinak }
3207711facfSdinak 
3217711facfSdinak /*
3227711facfSdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
3237711facfSdinak  * the size of the slot list buffer until the call is successful or an
3247711facfSdinak  * irrecoverable error occurs.
3257711facfSdinak  */
3267711facfSdinak CK_RV
get_token_slots(CK_SLOT_ID_PTR * slot_list,CK_ULONG * slot_count)3277711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
3287711facfSdinak {
3297711facfSdinak 	CK_ULONG	tmp_count = 0;
3307711facfSdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
3317711facfSdinak 	int		rv = CKR_OK;
3327711facfSdinak 
3337711facfSdinak 	if (!initialized)
334448b8615Swyllys 		if ((rv = init_pkcs11()) != CKR_OK)
3357711facfSdinak 			return (rv);
3367711facfSdinak 
3377711facfSdinak 	/*
3387711facfSdinak 	 * Get the slot count first because we don't know how many
3397711facfSdinak 	 * slots there are and how many of those slots even have tokens.
3407711facfSdinak 	 * Don't specify an arbitrary buffer size for the slot list;
3417711facfSdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
3427711facfSdinak 	 * Also select only those slots that have tokens in them,
3437711facfSdinak 	 * because this tool has no need to know about empty slots.
3447711facfSdinak 	 */
3457711facfSdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
3467711facfSdinak 		return (rv);
3477711facfSdinak 
3487711facfSdinak 	if (tmp_count == 0) {
3497711facfSdinak 		*slot_list = NULL_PTR;
3507711facfSdinak 		*slot_count = 0;
3517711facfSdinak 		return (CKR_OK);
3527711facfSdinak 	}
3537711facfSdinak 
3547711facfSdinak 	/* Allocate initial space for the slot list. */
3557711facfSdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
3567711facfSdinak 	    sizeof (CK_SLOT_ID))) == NULL)
3577711facfSdinak 		return (CKR_HOST_MEMORY);
3587711facfSdinak 
3597711facfSdinak 	/* Then get the slot list itself. */
3607711facfSdinak 	for (;;) {
3617711facfSdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
3627711facfSdinak 			*slot_list = tmp_list;
3637711facfSdinak 			*slot_count = tmp_count;
3647711facfSdinak 			break;
3657711facfSdinak 		}
3667711facfSdinak 
3677711facfSdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
3687711facfSdinak 			free(tmp_list);
3697711facfSdinak 			break;
3707711facfSdinak 		}
3717711facfSdinak 
3727711facfSdinak 		/* If the number of slots grew, try again. */
3737711facfSdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
3747711facfSdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
3757711facfSdinak 			free(tmp_list);
3767711facfSdinak 			rv = CKR_HOST_MEMORY;
3777711facfSdinak 			break;
3787711facfSdinak 		}
3797711facfSdinak 		tmp_list = tmp2_list;
3807711facfSdinak 	}
3817711facfSdinak 
3827711facfSdinak 	return (rv);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate /*
38699ebb4caSwyllys  * Breaks out the getopt-style option string into a structure that can be
38799ebb4caSwyllys  * traversed later for calls to getopt_av().  Option string is NOT altered,
38899ebb4caSwyllys  * but the struct fields point to locations within option string.
3897c478bd9Sstevel@tonic-gate  */
3907c478bd9Sstevel@tonic-gate static int
populate_opts(char * optstring)39199ebb4caSwyllys populate_opts(char *optstring)
3927c478bd9Sstevel@tonic-gate {
39399ebb4caSwyllys 	int		i;
39499ebb4caSwyllys 	av_opts		*temp;
3957c478bd9Sstevel@tonic-gate 	char		*marker;
3967c478bd9Sstevel@tonic-gate 
39799ebb4caSwyllys 	if (optstring == NULL || *optstring == '\0')
39899ebb4caSwyllys 		return (0);
39999ebb4caSwyllys 
40099ebb4caSwyllys 	/*
40199ebb4caSwyllys 	 * This tries to imitate getopt(3c) Each option must conform to:
40299ebb4caSwyllys 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
40399ebb4caSwyllys 	 * If long name is missing, the short name is used for long name.
40499ebb4caSwyllys 	 */
40599ebb4caSwyllys 	for (i = 0; *optstring != '\0'; i++) {
40699ebb4caSwyllys 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
40799ebb4caSwyllys 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
40899ebb4caSwyllys 			if (opts_av != NULL)
40999ebb4caSwyllys 				free(opts_av);
41099ebb4caSwyllys 			opts_av = NULL;
41199ebb4caSwyllys 			return (0);
41299ebb4caSwyllys 		} else {
41399ebb4caSwyllys 			opts_av = (av_opts *)temp;
41499ebb4caSwyllys 		}
4157c478bd9Sstevel@tonic-gate 
41699ebb4caSwyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
41799ebb4caSwyllys 		marker = optstring;		/* may need optstring later */
4187c478bd9Sstevel@tonic-gate 
41999ebb4caSwyllys 		opts_av[i].shortnm = *marker++;	/* set short name */
42099ebb4caSwyllys 
42199ebb4caSwyllys 		if (*marker == ':') {		/* check for opt arg */
42299ebb4caSwyllys 			marker++;
42399ebb4caSwyllys 			opts_av[i].has_arg = B_TRUE;
42499ebb4caSwyllys 		}
42599ebb4caSwyllys 
42699ebb4caSwyllys 		if (*marker == '(') {		/* check and set long name */
42799ebb4caSwyllys 			marker++;
42899ebb4caSwyllys 			opts_av[i].longnm = marker;
42999ebb4caSwyllys 			opts_av[i].longnm_len = strcspn(marker, ")");
43099ebb4caSwyllys 			optstring = marker + opts_av[i].longnm_len + 1;
43199ebb4caSwyllys 		} else {
43299ebb4caSwyllys 			/* use short name option character */
43399ebb4caSwyllys 			opts_av[i].longnm = optstring;
43499ebb4caSwyllys 			opts_av[i].longnm_len = 1;
43599ebb4caSwyllys 			optstring = marker;
43699ebb4caSwyllys 		}
43799ebb4caSwyllys 	}
43899ebb4caSwyllys 
43999ebb4caSwyllys 	return (i);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate /*
44399ebb4caSwyllys  * getopt_av() is very similar to getopt(3c) in that the takes an option
44499ebb4caSwyllys  * string, compares command line arguments for matches, and returns a single
44599ebb4caSwyllys  * letter option when a match is found.  However, getopt_av() differs from
44699ebb4caSwyllys  * getopt(3c) by requiring that only longname options and values be found
44799ebb4caSwyllys  * on the command line and all leading dashes are omitted.  In other words,
44899ebb4caSwyllys  * it tries to enforce only longname "option=value" arguments on the command
44999ebb4caSwyllys  * line.  Boolean options are not allowed either.
4507c478bd9Sstevel@tonic-gate  */
45199ebb4caSwyllys int
getopt_av(int argc,char * const * argv,const char * optstring)45299ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring)
4537c478bd9Sstevel@tonic-gate {
45499ebb4caSwyllys 	int	i;
45599ebb4caSwyllys 	int	len;
45699ebb4caSwyllys 	char   *cur_option;
4577c478bd9Sstevel@tonic-gate 
45899ebb4caSwyllys 	if (optind_av >= argc)
45999ebb4caSwyllys 		return (EOF);
4607c478bd9Sstevel@tonic-gate 
46199ebb4caSwyllys 	/* First time or when optstring changes from previous one */
46299ebb4caSwyllys 	if (_save_optstr != optstring) {
46399ebb4caSwyllys 		if (opts_av != NULL)
46430a5e8faSwyllys 			free(opts_av);
46599ebb4caSwyllys 		opts_av = NULL;
46699ebb4caSwyllys 		_save_optstr = optstring;
46799ebb4caSwyllys 		_save_numopts = populate_opts((char *)optstring);
46899ebb4caSwyllys 	}
4697c478bd9Sstevel@tonic-gate 
47099ebb4caSwyllys 	for (i = 0; i < _save_numopts; i++) {
47199ebb4caSwyllys 		cur_option = argv[optind_av];
4727c478bd9Sstevel@tonic-gate 
47399ebb4caSwyllys 		if (strcmp(cur_option, "--") == 0) {
47499ebb4caSwyllys 			optind_av++;
47599ebb4caSwyllys 			break;
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 
47899ebb4caSwyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
47999ebb4caSwyllys 			len = 1;
48099ebb4caSwyllys 			cur_option++; /* remove "-" */
48199ebb4caSwyllys 		} else {
48299ebb4caSwyllys 			len = strcspn(cur_option, "=");
48399ebb4caSwyllys 		}
4847c478bd9Sstevel@tonic-gate 
48599ebb4caSwyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
48699ebb4caSwyllys 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
48799ebb4caSwyllys 			/* matched */
48899ebb4caSwyllys 			if (!opts_av[i].has_arg) {
48999ebb4caSwyllys 				optind_av++;
49099ebb4caSwyllys 				return (opts_av[i].shortnm);
49199ebb4caSwyllys 			}
49299ebb4caSwyllys 
49399ebb4caSwyllys 			/* needs optarg */
49499ebb4caSwyllys 			if (cur_option[len] == '=') {
49599ebb4caSwyllys 				optarg_av = &(cur_option[len+1]);
49699ebb4caSwyllys 				optind_av++;
49799ebb4caSwyllys 				return (opts_av[i].shortnm);
49899ebb4caSwyllys 			}
49999ebb4caSwyllys 
50099ebb4caSwyllys 			optarg_av = NULL;
50199ebb4caSwyllys 			optind_av++;
50299ebb4caSwyllys 			return ((int)'?');
50399ebb4caSwyllys 		}
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
50699ebb4caSwyllys 	return (EOF);
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate 
50999ebb4caSwyllys KMF_KEYSTORE_TYPE
KS2Int(char * keystore_str)51099ebb4caSwyllys KS2Int(char *keystore_str)
51149e21299Sdinak {
51299ebb4caSwyllys 	if (keystore_str == NULL)
51399ebb4caSwyllys 		return (0);
514d00756ccSwyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
51599ebb4caSwyllys 		return (KMF_KEYSTORE_PK11TOKEN);
516d00756ccSwyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
51799ebb4caSwyllys 		return (KMF_KEYSTORE_NSS);
518d00756ccSwyllys 	else if (strcasecmp(keystore_str, "file") == 0)
51999ebb4caSwyllys 		return (KMF_KEYSTORE_OPENSSL);
52099ebb4caSwyllys 	else
52199ebb4caSwyllys 		return (0);
52299ebb4caSwyllys }
52349e21299Sdinak 
524e65e5c2dSWyllys Ingersoll /*
525e65e5c2dSWyllys Ingersoll  * compare_oids
526e65e5c2dSWyllys Ingersoll  * return 1 if equal
527e65e5c2dSWyllys Ingersoll  */
528e65e5c2dSWyllys Ingersoll boolean_t
compare_oids(KMF_OID * oid1,const KMF_OID * oid2)529e65e5c2dSWyllys Ingersoll compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
530e65e5c2dSWyllys Ingersoll {
531e65e5c2dSWyllys Ingersoll 	return ((oid1->Length == oid2->Length) &&
532e65e5c2dSWyllys Ingersoll 	    !memcmp(oid1->Data, oid2->Data, oid1->Length));
533e65e5c2dSWyllys Ingersoll }
53449e21299Sdinak 
53599ebb4caSwyllys int
Str2KeyType(char * algm,KMF_OID * hashoid,KMF_KEY_ALG * ktype,KMF_ALGORITHM_INDEX * sigAlg)536e65e5c2dSWyllys Ingersoll Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
537e65e5c2dSWyllys Ingersoll     KMF_ALGORITHM_INDEX *sigAlg)
53899ebb4caSwyllys {
53999ebb4caSwyllys 	if (algm == NULL) {
540e65e5c2dSWyllys Ingersoll 		/* Default to SHA1+RSA */
5414165f465SWyllys Ingersoll 		*sigAlg = KMF_ALGID_SHA1WithRSA;
54299ebb4caSwyllys 		*ktype = KMF_RSA;
54399ebb4caSwyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
544e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
545e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
546e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithDSA;
547e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
548e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithDSA;
549e65e5c2dSWyllys Ingersoll 		else
550e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
55199ebb4caSwyllys 		*ktype = KMF_DSA;
55299ebb4caSwyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
553e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
554e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
555e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithRSA;
556e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
557e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithRSA;
558e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA384))
559e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA384WithRSA;
560e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA512))
561e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA512WithRSA;
562e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_MD5))
563e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_MD5WithRSA;
564e65e5c2dSWyllys Ingersoll 		else
565e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
56699ebb4caSwyllys 		*ktype = KMF_RSA;
567e65e5c2dSWyllys Ingersoll 	} else if (strcasecmp(algm, "EC") == 0) {
568e65e5c2dSWyllys Ingersoll 		/* EC keys may be used with some SHA2 hashes */
569e65e5c2dSWyllys Ingersoll 		if (hashoid == NULL ||
570e65e5c2dSWyllys Ingersoll 		    compare_oids(hashoid, &KMFOID_SHA1))
571e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA1WithECDSA;
572e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA256))
573e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA256WithECDSA;
574e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA384))
575e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA384WithECDSA;
576e65e5c2dSWyllys Ingersoll 		else if (compare_oids(hashoid, &KMFOID_SHA512))
577e65e5c2dSWyllys Ingersoll 			*sigAlg = KMF_ALGID_SHA512WithECDSA;
578e65e5c2dSWyllys Ingersoll 		else
579e65e5c2dSWyllys Ingersoll 			return (-1); /* unsupported hash/key combo */
580e65e5c2dSWyllys Ingersoll 
581e65e5c2dSWyllys Ingersoll 		*ktype = KMF_ECDSA;
58299ebb4caSwyllys 	} else {
58399ebb4caSwyllys 		return (-1);
58449e21299Sdinak 	}
58599ebb4caSwyllys 	return (0);
58649e21299Sdinak }
58749e21299Sdinak 
58899ebb4caSwyllys int
Str2SymKeyType(char * algm,KMF_KEY_ALG * ktype)58999ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
59049e21299Sdinak {
59199ebb4caSwyllys 	if (algm == NULL)
59299ebb4caSwyllys 		*ktype = KMF_AES;
59399ebb4caSwyllys 	else if (strcasecmp(algm, "aes") == 0)
59499ebb4caSwyllys 		*ktype = KMF_AES;
59599ebb4caSwyllys 	else if (strcasecmp(algm, "arcfour") == 0)
59699ebb4caSwyllys 		*ktype = KMF_RC4;
59799ebb4caSwyllys 	else if (strcasecmp(algm, "des") == 0)
59899ebb4caSwyllys 		*ktype = KMF_DES;
59999ebb4caSwyllys 	else if (strcasecmp(algm, "3des") == 0)
60099ebb4caSwyllys 		*ktype = KMF_DES3;
601c197cb9dShylee 	else if (strcasecmp(algm, "generic") == 0)
602c197cb9dShylee 		*ktype = KMF_GENERIC_SECRET;
60399ebb4caSwyllys 	else
60499ebb4caSwyllys 		return (-1);
60549e21299Sdinak 
60699ebb4caSwyllys 	return (0);
60749e21299Sdinak }
60849e21299Sdinak 
60949e21299Sdinak int
Str2Lifetime(char * ltimestr,uint32_t * ltime)61099ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
61149e21299Sdinak {
61299ebb4caSwyllys 	int num;
61399ebb4caSwyllys 	char timetok[6];
61449e21299Sdinak 
615d00756ccSwyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
61699ebb4caSwyllys 		/* default to 1 year lifetime */
61799ebb4caSwyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
61899ebb4caSwyllys 		return (0);
61949e21299Sdinak 	}
62049e21299Sdinak 
62199ebb4caSwyllys 	(void) memset(timetok, 0, sizeof (timetok));
62299ebb4caSwyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
62399ebb4caSwyllys 		return (-1);
62449e21299Sdinak 
625