xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 11973:480f5412d630)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11973Swyllys.ingersoll@sun.com  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains the functions that are shared among
280Sstevel@tonic-gate  * the various services this tool will ultimately provide.
2917Sdinak  * The functions in this file return PKCS#11 CK_RV errors.
3017Sdinak  * Only one session and one login per token is supported
3117Sdinak  * at this time.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <ctype.h>
383089Swyllys #include <sys/types.h>
393089Swyllys #include <sys/stat.h>
403089Swyllys #include <fcntl.h>
413089Swyllys #include <tzfile.h>
420Sstevel@tonic-gate #include <cryptoutil.h>
430Sstevel@tonic-gate #include <security/cryptoki.h>
443089Swyllys #include <kmfapi.h>
450Sstevel@tonic-gate 
463089Swyllys #include "common.h"
4717Sdinak 
4817Sdinak /* Local status variables. */
4917Sdinak static boolean_t	initialized = B_FALSE;
5017Sdinak static boolean_t	session_opened = B_FALSE;
5117Sdinak static boolean_t	logged_in = B_FALSE;
5217Sdinak 
53864Sdinak /* Supporting structures and global variables for getopt_av(). */
54864Sdinak typedef struct	av_opts_s {
55864Sdinak 	int		shortnm;	/* short name character */
56864Sdinak 	char		*longnm;	/* long name string, NOT terminated */
57864Sdinak 	int		longnm_len;	/* length of long name string */
58864Sdinak 	boolean_t	has_arg;	/* takes optional argument */
59864Sdinak } av_opts;
60864Sdinak static av_opts		*opts_av = NULL;
61864Sdinak static const char	*_save_optstr = NULL;
62864Sdinak static int		_save_numopts = 0;
63864Sdinak 
64864Sdinak int			optind_av = 1;
65864Sdinak char			*optarg_av = NULL;
66864Sdinak 
673089Swyllys static void close_sess(CK_SESSION_HANDLE);
683089Swyllys static void logout_token(CK_SESSION_HANDLE);
693089Swyllys 
70*11973Swyllys.ingersoll@sun.com struct oid_table_entry {
71*11973Swyllys.ingersoll@sun.com 	const KMF_OID *oid;
72*11973Swyllys.ingersoll@sun.com 	char *name;
73*11973Swyllys.ingersoll@sun.com };
74*11973Swyllys.ingersoll@sun.com 
75*11973Swyllys.ingersoll@sun.com struct oid_table_entry oid_table[] = {
76*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp112r1, "secp112r1"},
77*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp112r2, "secp112r2"},
78*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp128r1, "secp128r1"},
79*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp128r2, "secp128r2"},
80*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160k1, "secp160k1"},
81*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160r1, "secp160r1"},
82*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160r2, "secp160r2"},
83*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp192k1, "secp192k1"},
84*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp192r1, "secp192r1"},
85*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp224k1, "secp224k1"},
86*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp224r1, "secp224r1"},
87*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp256k1, "secp256k1"},
88*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp256r1, "secp256r1"},
89*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp384r1, "secp384r1"},
90*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp521r1, "secp521r1"},
91*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect113r1, "sect113r1"},
92*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect113r2, "sect113r2"},
93*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect131r1, "sect131r1"},
94*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect131r2, "sect131r2"},
95*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163k1, "sect163k1"},
96*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163r1, "sect163r1"},
97*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163r2, "sect163r2"},
98*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect193r1, "sect193r1"},
99*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect193r2, "sect193r2"},
100*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect233k1, "sect233k1"},
101*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect233r1, "sect233r1"},
102*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect239k1, "sect239k1"},
103*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect283k1, "sect283k1"},
104*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect283r1, "sect283r1"},
105*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect409k1, "sect409k1"},
106*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect409r1, "sect409r1"},
107*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect571k1, "sect571k1"},
108*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect571r1, "sect571r1"},
109*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
110*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
111*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
112*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
113*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
114*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
115*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
116*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
117*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
118*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
119*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
120*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
121*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
122*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
123*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
124*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
125*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_prime192v2, "prime192v2"},
126*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_prime192v3, "prime192v3"},
127*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_MD5, "md5"},
128*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA1, "sha1"},
129*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA256, "sha256"},
130*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA384, "sha384"},
131*11973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA512, "sha512"}
132*11973Swyllys.ingersoll@sun.com };
133*11973Swyllys.ingersoll@sun.com int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
134*11973Swyllys.ingersoll@sun.com #define	number_of_curves (number_of_oids - 5)
135*11973Swyllys.ingersoll@sun.com 
13617Sdinak /*
13717Sdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
13817Sdinak  * along with setting/resetting state variables.
13917Sdinak  */
1406669Swyllys static CK_RV
1416669Swyllys init_pkcs11(void)
14217Sdinak {
14317Sdinak 	CK_RV		rv = CKR_OK;
14417Sdinak 
14517Sdinak 	/* If C_Initialize() already called, nothing to do here. */
14617Sdinak 	if (initialized == B_TRUE)
14717Sdinak 		return (CKR_OK);
14817Sdinak 
14917Sdinak 	/* Reset state variables because C_Initialize() not yet done. */
15017Sdinak 	session_opened = B_FALSE;
15117Sdinak 	logged_in = B_FALSE;
15217Sdinak 
15317Sdinak 	/* Initialize PKCS#11 library. */
15417Sdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
15517Sdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
15617Sdinak 		return (rv);
15717Sdinak 	}
15817Sdinak 
15917Sdinak 	initialized = B_TRUE;
16017Sdinak 	return (CKR_OK);
16117Sdinak }
16217Sdinak 
16317Sdinak /*
16417Sdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
16517Sdinak  * if any, are closed, and thereby any logins are logged out also.
16617Sdinak  */
16717Sdinak void
16817Sdinak final_pk11(CK_SESSION_HANDLE sess)
16917Sdinak {
17017Sdinak 
17117Sdinak 	/* If the library wasn't initialized, nothing to do here. */
17217Sdinak 	if (!initialized)
17317Sdinak 		return;
17417Sdinak 
17517Sdinak 	/* Make sure the sesion is closed first. */
17617Sdinak 	close_sess(sess);
17717Sdinak 
17817Sdinak 	(void) C_Finalize(NULL);
17917Sdinak 	initialized = B_FALSE;
18017Sdinak }
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate /*
18317Sdinak  * Close PKCS#11 session and reset state variables.  Any logins are
18417Sdinak  * logged out.
18517Sdinak  */
1863089Swyllys static void
18717Sdinak close_sess(CK_SESSION_HANDLE sess)
18817Sdinak {
18917Sdinak 
19017Sdinak 	if (sess == NULL) {
19117Sdinak 		return;
19217Sdinak 	}
19317Sdinak 
19417Sdinak 	/* If session is already closed, nothing to do here. */
19517Sdinak 	if (!session_opened)
19617Sdinak 		return;
1970Sstevel@tonic-gate 
19817Sdinak 	/* Make sure user is logged out of token. */
19917Sdinak 	logout_token(sess);
20017Sdinak 
20117Sdinak 	(void) C_CloseSession(sess);
20217Sdinak 	session_opened = B_FALSE;
20317Sdinak }
20417Sdinak 
20517Sdinak /*
20617Sdinak  * Log user out of token and reset status variable.
20717Sdinak  */
2083089Swyllys static void
20917Sdinak logout_token(CK_SESSION_HANDLE sess)
21017Sdinak {
21117Sdinak 
21217Sdinak 	if (sess == NULL) {
21317Sdinak 		return;
21417Sdinak 	}
21517Sdinak 
21617Sdinak 	/* If already logged out, nothing to do here. */
21717Sdinak 	if (!logged_in)
21817Sdinak 		return;
21917Sdinak 
22017Sdinak 	(void) C_Logout(sess);
22117Sdinak 	logged_in = B_FALSE;
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
22517Sdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
22617Sdinak  * If two prompts are given, the PIN is confirmed with second prompt.
22717Sdinak  * Note that getphassphrase() may return data in static memory area.
22817Sdinak  */
22917Sdinak CK_RV
23017Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
23117Sdinak {
2326051Swyllys 	char *save_phrase, *phrase1, *phrase2;
2330Sstevel@tonic-gate 
23417Sdinak 	/* Prompt user for a PIN. */
23517Sdinak 	if (prompt1 == NULL) {
23617Sdinak 		return (CKR_ARGUMENTS_BAD);
23717Sdinak 	}
23817Sdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
23917Sdinak 		return (CKR_FUNCTION_FAILED);
24017Sdinak 	}
24117Sdinak 
24217Sdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
24317Sdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
24417Sdinak 		return (CKR_HOST_MEMORY);
24517Sdinak 
24617Sdinak 	/* If second prompt given, PIN confirmation is requested. */
24717Sdinak 	if (prompt2 != NULL) {
24817Sdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
24917Sdinak 			free(save_phrase);
25017Sdinak 			return (CKR_FUNCTION_FAILED);
25117Sdinak 		}
25217Sdinak 		if (strcmp(save_phrase, phrase2) != 0) {
25317Sdinak 			free(save_phrase);
25417Sdinak 			return (CKR_PIN_INCORRECT);
25517Sdinak 		}
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
25817Sdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
25917Sdinak 	*pinlen = strlen(save_phrase);
26017Sdinak 	return (CKR_OK);
26117Sdinak }
26217Sdinak 
2636051Swyllys int
2646051Swyllys yn_to_int(char *ynstr)
2656051Swyllys {
2666051Swyllys 	char *y = gettext("yes");
2676051Swyllys 	char *n = gettext("no");
2686051Swyllys 	if (ynstr == NULL)
2696051Swyllys 		return (-1);
2706051Swyllys 
2716051Swyllys 	if (strncasecmp(ynstr, y, 1) == 0)
2726051Swyllys 		return (1);
2736051Swyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
2746051Swyllys 		return (0);
2756051Swyllys 	else
2766051Swyllys 		return (-1);
2776051Swyllys }
2786051Swyllys 
27917Sdinak /*
28017Sdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
28117Sdinak  * default prompt is used.  If not message for invalid input is supplied,
28217Sdinak  * a default will not be provided.  If the user provides no response,
28317Sdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
28417Sdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
28517Sdinak  */
28617Sdinak boolean_t
28717Sdinak yesno(char *prompt, char *invalid, boolean_t dflt)
28817Sdinak {
2896051Swyllys 	char	*response, buf[1024];
2906051Swyllys 	int	ans;
29117Sdinak 
29217Sdinak 	if (prompt == NULL)
29317Sdinak 		prompt = gettext("Enter (y)es or (n)o? ");
29417Sdinak 
29517Sdinak 	for (;;) {
29617Sdinak 		/* Prompt user. */
29717Sdinak 		(void) printf("%s", prompt);
29817Sdinak 		(void) fflush(stdout);
29917Sdinak 
30017Sdinak 		/* Get the response. */
30117Sdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
30217Sdinak 			break;		/* go to default response */
30317Sdinak 
30417Sdinak 		/* Skip any leading white space. */
30517Sdinak 		while (isspace(*response))
30617Sdinak 			response++;
30717Sdinak 		if (*response == '\0')
30817Sdinak 			break;		/* go to default response */
30917Sdinak 
3106051Swyllys 		ans = yn_to_int(response);
3116051Swyllys 		if (ans == 1)
31217Sdinak 			return (B_TRUE);
3136051Swyllys 		else if (ans == 0)
31417Sdinak 			return (B_FALSE);
31517Sdinak 
31617Sdinak 		/* Indicate invalid input, and try again. */
31717Sdinak 		if (invalid != NULL)
3185051Swyllys 			(void) printf("%s", invalid);
31917Sdinak 	}
32017Sdinak 	return (dflt);
32117Sdinak }
32217Sdinak 
32317Sdinak /*
32417Sdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
32517Sdinak  * the size of the slot list buffer until the call is successful or an
32617Sdinak  * irrecoverable error occurs.
32717Sdinak  */
32817Sdinak CK_RV
32917Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
33017Sdinak {
33117Sdinak 	CK_ULONG	tmp_count = 0;
33217Sdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
33317Sdinak 	int		rv = CKR_OK;
33417Sdinak 
33517Sdinak 	if (!initialized)
3366669Swyllys 		if ((rv = init_pkcs11()) != CKR_OK)
33717Sdinak 			return (rv);
33817Sdinak 
33917Sdinak 	/*
34017Sdinak 	 * Get the slot count first because we don't know how many
34117Sdinak 	 * slots there are and how many of those slots even have tokens.
34217Sdinak 	 * Don't specify an arbitrary buffer size for the slot list;
34317Sdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
34417Sdinak 	 * Also select only those slots that have tokens in them,
34517Sdinak 	 * because this tool has no need to know about empty slots.
34617Sdinak 	 */
34717Sdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
34817Sdinak 		return (rv);
34917Sdinak 
35017Sdinak 	if (tmp_count == 0) {
35117Sdinak 		*slot_list = NULL_PTR;
35217Sdinak 		*slot_count = 0;
35317Sdinak 		return (CKR_OK);
35417Sdinak 	}
35517Sdinak 
35617Sdinak 	/* Allocate initial space for the slot list. */
35717Sdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
35817Sdinak 	    sizeof (CK_SLOT_ID))) == NULL)
35917Sdinak 		return (CKR_HOST_MEMORY);
36017Sdinak 
36117Sdinak 	/* Then get the slot list itself. */
36217Sdinak 	for (;;) {
36317Sdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
36417Sdinak 			*slot_list = tmp_list;
36517Sdinak 			*slot_count = tmp_count;
36617Sdinak 			break;
36717Sdinak 		}
36817Sdinak 
36917Sdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
37017Sdinak 			free(tmp_list);
37117Sdinak 			break;
37217Sdinak 		}
37317Sdinak 
37417Sdinak 		/* If the number of slots grew, try again. */
37517Sdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
37617Sdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
37717Sdinak 			free(tmp_list);
37817Sdinak 			rv = CKR_HOST_MEMORY;
37917Sdinak 			break;
38017Sdinak 		}
38117Sdinak 		tmp_list = tmp2_list;
38217Sdinak 	}
38317Sdinak 
38417Sdinak 	return (rv);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate /*
388864Sdinak  * Breaks out the getopt-style option string into a structure that can be
389864Sdinak  * traversed later for calls to getopt_av().  Option string is NOT altered,
390864Sdinak  * but the struct fields point to locations within option string.
391864Sdinak  */
392864Sdinak static int
393864Sdinak populate_opts(char *optstring)
394864Sdinak {
395864Sdinak 	int		i;
396864Sdinak 	av_opts		*temp;
397864Sdinak 	char		*marker;
398864Sdinak 
399864Sdinak 	if (optstring == NULL || *optstring == '\0')
400864Sdinak 		return (0);
401864Sdinak 
402864Sdinak 	/*
403864Sdinak 	 * This tries to imitate getopt(3c) Each option must conform to:
404864Sdinak 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
405864Sdinak 	 * If long name is missing, the short name is used for long name.
406864Sdinak 	 */
407864Sdinak 	for (i = 0; *optstring != '\0'; i++) {
408864Sdinak 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
409864Sdinak 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
4103089Swyllys 			if (opts_av != NULL)
4113089Swyllys 				free(opts_av);
412864Sdinak 			opts_av = NULL;
413864Sdinak 			return (0);
4143089Swyllys 		} else {
415864Sdinak 			opts_av = (av_opts *)temp;
4163089Swyllys 		}
417864Sdinak 
4183089Swyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
419864Sdinak 		marker = optstring;		/* may need optstring later */
420864Sdinak 
421864Sdinak 		opts_av[i].shortnm = *marker++;	/* set short name */
422864Sdinak 
423864Sdinak 		if (*marker == ':') {		/* check for opt arg */
424864Sdinak 			marker++;
425864Sdinak 			opts_av[i].has_arg = B_TRUE;
426864Sdinak 		}
427864Sdinak 
428864Sdinak 		if (*marker == '(') {		/* check and set long name */
429864Sdinak 			marker++;
430864Sdinak 			opts_av[i].longnm = marker;
431864Sdinak 			opts_av[i].longnm_len = strcspn(marker, ")");
432864Sdinak 			optstring = marker + opts_av[i].longnm_len + 1;
433864Sdinak 		} else {
434864Sdinak 			/* use short name option character */
435864Sdinak 			opts_av[i].longnm = optstring;
436864Sdinak 			opts_av[i].longnm_len = 1;
437864Sdinak 			optstring = marker;
438864Sdinak 		}
439864Sdinak 	}
440864Sdinak 
441864Sdinak 	return (i);
442864Sdinak }
443864Sdinak 
444864Sdinak /*
445864Sdinak  * getopt_av() is very similar to getopt(3c) in that the takes an option
446864Sdinak  * string, compares command line arguments for matches, and returns a single
447864Sdinak  * letter option when a match is found.  However, getopt_av() differs from
448864Sdinak  * getopt(3c) by requiring that only longname options and values be found
449864Sdinak  * on the command line and all leading dashes are omitted.  In other words,
450864Sdinak  * it tries to enforce only longname "option=value" arguments on the command
451864Sdinak  * line.  Boolean options are not allowed either.
452864Sdinak  */
453864Sdinak int
454864Sdinak getopt_av(int argc, char * const *argv, const char *optstring)
455864Sdinak {
456864Sdinak 	int	i;
457864Sdinak 	int	len;
4583089Swyllys 	char   *cur_option;
459864Sdinak 
460864Sdinak 	if (optind_av >= argc)
461864Sdinak 		return (EOF);
462864Sdinak 
463864Sdinak 	/* First time or when optstring changes from previous one */
464864Sdinak 	if (_save_optstr != optstring) {
465864Sdinak 		if (opts_av != NULL)
4665051Swyllys 			free(opts_av);
467864Sdinak 		opts_av = NULL;
468864Sdinak 		_save_optstr = optstring;
469864Sdinak 		_save_numopts = populate_opts((char *)optstring);
470864Sdinak 	}
471864Sdinak 
472864Sdinak 	for (i = 0; i < _save_numopts; i++) {
4733089Swyllys 		cur_option = argv[optind_av];
4743089Swyllys 
4753089Swyllys 		if (strcmp(cur_option, "--") == 0) {
476864Sdinak 			optind_av++;
477864Sdinak 			break;
478864Sdinak 		}
479864Sdinak 
4803089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
4813089Swyllys 			len = 1;
4823089Swyllys 			cur_option++; /* remove "-" */
4833089Swyllys 		} else {
4843089Swyllys 			len = strcspn(cur_option, "=");
4853089Swyllys 		}
486864Sdinak 
4873089Swyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
488864Sdinak 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
489864Sdinak 			/* matched */
490864Sdinak 			if (!opts_av[i].has_arg) {
491864Sdinak 				optind_av++;
492864Sdinak 				return (opts_av[i].shortnm);
493864Sdinak 			}
494864Sdinak 
495864Sdinak 			/* needs optarg */
4963089Swyllys 			if (cur_option[len] == '=') {
4973089Swyllys 				optarg_av = &(cur_option[len+1]);
498864Sdinak 				optind_av++;
499864Sdinak 				return (opts_av[i].shortnm);
500864Sdinak 			}
501864Sdinak 
502864Sdinak 			optarg_av = NULL;
503864Sdinak 			optind_av++;
504864Sdinak 			return ((int)'?');
505864Sdinak 		}
506864Sdinak 	}
507864Sdinak 
508864Sdinak 	return (EOF);
509864Sdinak }
5103089Swyllys 
5113089Swyllys KMF_KEYSTORE_TYPE
5123089Swyllys KS2Int(char *keystore_str)
5133089Swyllys {
5143089Swyllys 	if (keystore_str == NULL)
5153089Swyllys 		return (0);
5166051Swyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
5173089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
5186051Swyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
5193089Swyllys 		return (KMF_KEYSTORE_NSS);
5206051Swyllys 	else if (strcasecmp(keystore_str, "file") == 0)
5213089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
5223089Swyllys 	else
5233089Swyllys 		return (0);
5243089Swyllys }
5253089Swyllys 
526*11973Swyllys.ingersoll@sun.com /*
527*11973Swyllys.ingersoll@sun.com  * compare_oids
528*11973Swyllys.ingersoll@sun.com  * return 1 if equal
529*11973Swyllys.ingersoll@sun.com  */
530*11973Swyllys.ingersoll@sun.com boolean_t
531*11973Swyllys.ingersoll@sun.com compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
532*11973Swyllys.ingersoll@sun.com {
533*11973Swyllys.ingersoll@sun.com 	return ((oid1->Length == oid2->Length) &&
534*11973Swyllys.ingersoll@sun.com 	    !memcmp(oid1->Data, oid2->Data, oid1->Length));
535*11973Swyllys.ingersoll@sun.com }
5363089Swyllys 
5373089Swyllys int
538*11973Swyllys.ingersoll@sun.com Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
539*11973Swyllys.ingersoll@sun.com     KMF_ALGORITHM_INDEX *sigAlg)
5403089Swyllys {
5413089Swyllys 	if (algm == NULL) {
542*11973Swyllys.ingersoll@sun.com 		/* Default to SHA1+RSA */
54310744Swyllys.ingersoll@sun.com 		*sigAlg = KMF_ALGID_SHA1WithRSA;
5443089Swyllys 		*ktype = KMF_RSA;
5453089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
546*11973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
547*11973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
548*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithDSA;
549*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
550*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithDSA;
551*11973Swyllys.ingersoll@sun.com 		else
552*11973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
5533089Swyllys 		*ktype = KMF_DSA;
5543089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
555*11973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
556*11973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
557*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithRSA;
558*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
559*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithRSA;
560*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA384))
561*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA384WithRSA;
562*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA512))
563*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA512WithRSA;
564*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_MD5))
565*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_MD5WithRSA;
566*11973Swyllys.ingersoll@sun.com 		else
567*11973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
5683089Swyllys 		*ktype = KMF_RSA;
569*11973Swyllys.ingersoll@sun.com 	} else if (strcasecmp(algm, "EC") == 0) {
570*11973Swyllys.ingersoll@sun.com 		/* EC keys may be used with some SHA2 hashes */
571*11973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
572*11973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
573*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithECDSA;
574*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
575*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithECDSA;
576*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA384))
577*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA384WithECDSA;
578*11973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA512))
579*11973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA512WithECDSA;
580*11973Swyllys.ingersoll@sun.com 		else
581*11973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
582*11973Swyllys.ingersoll@sun.com 
583*11973Swyllys.ingersoll@sun.com 		*ktype = KMF_ECDSA;
5843089Swyllys 	} else {
5853089Swyllys 		return (-1);
5863089Swyllys 	}
5873089Swyllys 	return (0);
5883089Swyllys }
5893089Swyllys 
5903089Swyllys int
5913089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
5923089Swyllys {
5933089Swyllys 	if (algm == NULL)
5943089Swyllys 		*ktype = KMF_AES;
5953089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
5963089Swyllys 		*ktype = KMF_AES;
5973089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
5983089Swyllys 		*ktype = KMF_RC4;
5993089Swyllys 	else if (strcasecmp(algm, "des") == 0)
6003089Swyllys 		*ktype = KMF_DES;
6013089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
6023089Swyllys 		*ktype = KMF_DES3;
6033812Shylee 	else if (strcasecmp(algm, "generic") == 0)
6043812Shylee 		*ktype = KMF_GENERIC_SECRET;
6053089Swyllys 	else
6063089Swyllys 		return (-1);
6073089Swyllys 
6083089Swyllys 	return (0);
6093089Swyllys }
6103089Swyllys 
6113089Swyllys int
6123089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
6133089Swyllys {
6143089Swyllys 	int num;
6153089Swyllys 	char timetok[6];
6163089Swyllys 
6176051Swyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
6183089Swyllys 		/* default to 1 year lifetime */
6193089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
6203089Swyllys 		return (0);
6213089Swyllys 	}
6223089Swyllys 
6233089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
6243089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
6253089Swyllys 		return (-1);
6263089Swyllys 
6276051Swyllys 	if (strcasecmp(timetok, "day") == 0||
6286051Swyllys 	    strcasecmp(timetok, "days") == 0) {
6293089Swyllys 		*ltime = num * SECSPERDAY;
6306051Swyllys 	} else if (strcasecmp(timetok, "hour") == 0||
6316051Swyllys 	    strcasecmp(timetok, "hours") == 0) {
6323089Swyllys 		*ltime = num * SECSPERHOUR;
6336051Swyllys 	} else if (strcasecmp(timetok, "year") == 0 ||
6346051Swyllys 	    strcasecmp(timetok, "years") == 0) {
6353089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
6363089Swyllys 	} else {
6373089Swyllys 		*ltime = 0;
6383089Swyllys 		return (-1);
6393089Swyllys 	}
6403089Swyllys 
6413089Swyllys 	return (0);
6423089Swyllys }
6433089Swyllys 
6443089Swyllys int
6453089Swyllys OT2Int(char *objclass)
6463089Swyllys {
6473089Swyllys 	char *c = NULL;
6483089Swyllys 	int retval = 0;
6493089Swyllys 
6503089Swyllys 	if (objclass == NULL)
6513089Swyllys 		return (-1);
6523089Swyllys 
6533089Swyllys 	c = strchr(objclass, ':');
6543089Swyllys 	if (c != NULL) {
6556051Swyllys 		if (strcasecmp(c, ":private") == 0)
6563089Swyllys 			retval = PK_PRIVATE_OBJ;
6576051Swyllys 		else if (strcasecmp(c, ":public") == 0)
6583089Swyllys 			retval = PK_PUBLIC_OBJ;
6596051Swyllys 		else if (strcasecmp(c, ":both") == 0)
6603089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
6613089Swyllys 		else /* unrecognized option */
6623089Swyllys 			return (-1);
6633089Swyllys 
6643089Swyllys 		*c = '\0';
6653089Swyllys 	}
6663089Swyllys 
6676051Swyllys 	if (strcasecmp(objclass, "public") == 0) {
6683089Swyllys 		if (retval)
6693089Swyllys 			return (-1);
6705051Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
6716051Swyllys 	} else if (strcasecmp(objclass, "private") == 0) {
6723089Swyllys 		if (retval)
6733089Swyllys 			return (-1);
6743089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
6756051Swyllys 	} else if (strcasecmp(objclass, "both") == 0) {
6763089Swyllys 		if (retval)
6773089Swyllys 			return (-1);
6783089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
6796051Swyllys 	} else if (strcasecmp(objclass, "cert") == 0) {
6803089Swyllys 		return (retval | PK_CERT_OBJ);
6816051Swyllys 	} else if (strcasecmp(objclass, "key") == 0) {
6823089Swyllys 		if (retval == 0) /* return all keys */
6833089Swyllys 			return (retval | PK_KEY_OBJ);
6843089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
6853089Swyllys 			/* return all keys */
6863089Swyllys 			return (retval | PK_KEY_OBJ);
6873089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
6883089Swyllys 			/* Only return public keys */
6893089Swyllys 			return (retval | PK_PUBKEY_OBJ);
6903089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
6913089Swyllys 			/* Only return private keys */
6923089Swyllys 			return (retval | PK_PRIKEY_OBJ);
6936051Swyllys 	} else if (strcasecmp(objclass, "crl") == 0) {
6943089Swyllys 		if (retval)
6953089Swyllys 			return (-1);
6963089Swyllys 		return (retval | PK_CRL_OBJ);
6973089Swyllys 	}
6983089Swyllys 
6993089Swyllys 	if (retval == 0) /* No matches found */
7003089Swyllys 		retval = -1;
7013089Swyllys 	return (retval);
7023089Swyllys }
7033089Swyllys 
7043089Swyllys KMF_ENCODE_FORMAT
7053089Swyllys Str2Format(char *formstr)
7063089Swyllys {
7076051Swyllys 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
7083089Swyllys 		return (KMF_FORMAT_ASN1);
7096051Swyllys 	if (strcasecmp(formstr, "pem") == 0)
7103089Swyllys 		return (KMF_FORMAT_PEM);
7116051Swyllys 	if (strcasecmp(formstr, "pkcs12") == 0)
7123089Swyllys 		return (KMF_FORMAT_PKCS12);
7136051Swyllys 	if (strcasecmp(formstr, "raw") == 0)
7145051Swyllys 		return (KMF_FORMAT_RAWKEY);
7153089Swyllys 
7163089Swyllys 	return (KMF_FORMAT_UNDEF);
7173089Swyllys }
7183089Swyllys 
7193089Swyllys KMF_RETURN
7206051Swyllys select_token(void *kmfhandle, char *token, int readonly)
7213089Swyllys {
7225051Swyllys 	KMF_ATTRIBUTE attlist[10];
7235051Swyllys 	int i = 0;
7245051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
7253089Swyllys 	KMF_RETURN rv = KMF_OK;
7263089Swyllys 
7273089Swyllys 	if (token == NULL)
7283089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
7293089Swyllys 
7305051Swyllys 	kmf_set_attr_at_index(attlist, i,
7315051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
7325051Swyllys 	    sizeof (kstype));
7335051Swyllys 	i++;
7343089Swyllys 
7355051Swyllys 	if (token) {
7365051Swyllys 		kmf_set_attr_at_index(attlist, i,
7375051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
7385051Swyllys 		    strlen(token));
7395051Swyllys 		i++;
7405051Swyllys 	}
7415051Swyllys 
7425051Swyllys 	kmf_set_attr_at_index(attlist, i,
7435051Swyllys 	    KMF_READONLY_ATTR, &readonly,
7445051Swyllys 	    sizeof (readonly));
7455051Swyllys 	i++;
7465051Swyllys 
7475051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
7483089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
7493089Swyllys 		rv = KMF_OK;
7503089Swyllys 	return (rv);
7513089Swyllys }
7523089Swyllys 
7533089Swyllys KMF_RETURN
7543089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
7553089Swyllys {
7565051Swyllys 	KMF_ATTRIBUTE attlist[10];
7575051Swyllys 	int i = 0;
7585051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
7593089Swyllys 	KMF_RETURN rv = KMF_OK;
7605051Swyllys 
7615051Swyllys 	kmf_set_attr_at_index(attlist, i,
7625051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
7635051Swyllys 	    sizeof (kstype));
7645051Swyllys 	i++;
7653089Swyllys 
7665051Swyllys 	if (dir) {
7675051Swyllys 		kmf_set_attr_at_index(attlist, i,
7685051Swyllys 		    KMF_DIRPATH_ATTR, dir,
7695051Swyllys 		    strlen(dir));
7705051Swyllys 		i++;
7715051Swyllys 	}
7723089Swyllys 
7735051Swyllys 	if (prefix) {
7745051Swyllys 		kmf_set_attr_at_index(attlist, i,
7755051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
7765051Swyllys 		    strlen(prefix));
7775051Swyllys 		i++;
7785051Swyllys 
7795051Swyllys 		kmf_set_attr_at_index(attlist, i,
7805051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
7815051Swyllys 		    strlen(prefix));
7825051Swyllys 		i++;
7835051Swyllys 	}
7845051Swyllys 
7855051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
7863089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
7873089Swyllys 		rv = KMF_OK;
7883089Swyllys 
7893089Swyllys 	return (rv);
7903089Swyllys }
7913089Swyllys 
7923089Swyllys KMF_RETURN
7933089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
7943089Swyllys {
7953089Swyllys 	KMF_RETURN rv = KMF_OK;
7963089Swyllys 	char prompt[1024];
7973089Swyllys 
7983089Swyllys 	/*
7993089Swyllys 	 * Get the password to use for the PK12 encryption.
8003089Swyllys 	 */
8013089Swyllys 	(void) strlcpy(prompt,
8025051Swyllys 	    gettext("Enter password to use for "
8035051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
8043089Swyllys 
8053089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
8065051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
8073089Swyllys 		cred->cred = NULL;
8083089Swyllys 		cred->credlen = 0;
8093089Swyllys 	}
8103089Swyllys 
8113089Swyllys 	return (rv);
8123089Swyllys }
8133089Swyllys 
8145221Swyllys #define	FILENAME_PROMPT gettext("Filename:")
8155221Swyllys #define	FILENAME_MINLEN	1
8165221Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
8173089Swyllys 
8185221Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
8195221Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
8205221Swyllys 	"[Some-State]:")
8215221Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
8225221Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
8235221Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
8245221Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
8255221Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
8265221Swyllys 
8275221Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
8285221Swyllys 	"0x01020304):")
8295221Swyllys #define	SERNO_MINLEN	3
8305221Swyllys #define	SERNO_MAXLEN	42
8315221Swyllys 
8325221Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
8335221Swyllys #define	LABEL_MINLEN	1
8345221Swyllys #define	LABEL_MAXLEN	1024
8353089Swyllys 
8363089Swyllys #define	COUNTRY_DEFAULT "US"
8375221Swyllys #define	STATE_DEFAULT	NULL
8385221Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
8393089Swyllys 
8403089Swyllys #define	SUBNAMESIZ	1024
8413089Swyllys #define	RDN_MIN		1
8423089Swyllys #define	RDN_MAX		64
8433089Swyllys #define	COUNTRYNAME_MIN	2
8443089Swyllys #define	COUNTRYNAME_MAX	2
8453089Swyllys 
8463089Swyllys static char *
8473089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
8483089Swyllys {
8493089Swyllys 	char buf[1024];
8503089Swyllys 	char *response = NULL;
8513089Swyllys 	char *ret = NULL;
8523089Swyllys 	int len;
8533089Swyllys 
8543089Swyllys 	for (;;) {
8553089Swyllys 		(void) printf("\t%s", prompt);
8563089Swyllys 		(void) fflush(stdout);
8573089Swyllys 
8583089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
8593089Swyllys 		if (response == NULL) {
8603089Swyllys 			if (default_str != NULL) {
8613089Swyllys 				ret = strdup(default_str);
8623089Swyllys 			}
8633089Swyllys 			break;
8643089Swyllys 		}
8653089Swyllys 
8663089Swyllys 		/* Skip any leading white space. */
8673089Swyllys 		while (isspace(*response))
8683089Swyllys 			response++;
8693089Swyllys 		if (*response == '\0') {
8703089Swyllys 			if (default_str != NULL) {
8713089Swyllys 				ret = strdup(default_str);
8723089Swyllys 			}
8733089Swyllys 			break;
8743089Swyllys 		}
8753089Swyllys 
8763089Swyllys 		len = strlen(response);
8773089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
8783089Swyllys 		len--;
8793089Swyllys 		if (len >= min_len && len <= max_len) {
8803089Swyllys 			ret = strdup(response);
8813089Swyllys 			break;
8823089Swyllys 		}
8833089Swyllys 
8843089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
8853089Swyllys 
8863089Swyllys 	}
8873089Swyllys 
8883089Swyllys 	return (ret);
8893089Swyllys }
8903089Swyllys 
8913089Swyllys int
8925221Swyllys get_filename(char *txt, char **result)
8935221Swyllys {
8945221Swyllys 	char prompt[1024];
8955221Swyllys 	char *fname = NULL;
8965221Swyllys 
8975221Swyllys 	(void) snprintf(prompt, sizeof (prompt),
8985221Swyllys 	    gettext("Enter filename for the %s: "),
8995221Swyllys 	    txt);
9005221Swyllys 	fname = get_input_string(prompt, NULL,
9015221Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
9025221Swyllys 	*result = fname;
9035221Swyllys 	return (0);
9045221Swyllys }
9055221Swyllys 
9065221Swyllys int
9075221Swyllys get_certlabel(char **result)
9085221Swyllys {
9095221Swyllys 	char *label = NULL;
9105221Swyllys 
9115221Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
9125221Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
9135221Swyllys 	*result = label;
9145221Swyllys 	return (0);
9155221Swyllys }
9165221Swyllys 
9175221Swyllys int
9185221Swyllys get_serial(char **result)
9195221Swyllys {
9205221Swyllys 	char *serial = NULL;
9215221Swyllys 
9225221Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
9235221Swyllys 	    SERNO_MAXLEN);
9245221Swyllys 
9255221Swyllys 	*result = serial;
9265221Swyllys 	return (0);
9275221Swyllys }
9285221Swyllys 
9295221Swyllys int
9303089Swyllys get_subname(char **result)
9313089Swyllys {
9323089Swyllys 	char *country = NULL;
9333089Swyllys 	char *state = NULL;
9343089Swyllys 	char *locality = NULL;
9353089Swyllys 	char *org = NULL;
9363089Swyllys 	char *unit = NULL;
9373089Swyllys 	char *name = NULL;
9383089Swyllys 	char *email = NULL;
9393089Swyllys 	char *subname = NULL;
9403089Swyllys 
9413089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
9423089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
9433089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
9443089Swyllys 	if (country == NULL)
9453089Swyllys 		return (-1);
9463089Swyllys 
9473089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
9483089Swyllys 	    RDN_MIN, RDN_MAX);
9493089Swyllys 
9503089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
9513089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
9523089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
9533089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
9543089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
9553089Swyllys 
9563089Swyllys 	/* Now create a subject name from the input strings */
9573089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
9583089Swyllys 		goto out;
9593089Swyllys 
9603089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
9613089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
9623089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
9635221Swyllys 	if (state != NULL) {
9645221Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
9655221Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
9665221Swyllys 	}
9673089Swyllys 
9685221Swyllys 	if (locality != NULL) {
9695221Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
9703089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
9713089Swyllys 	}
9723089Swyllys 
9735221Swyllys 	if (org != NULL) {
9745221Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
9753089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
9763089Swyllys 	}
9773089Swyllys 
9785221Swyllys 	if (unit != NULL) {
9795221Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
9803089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
9813089Swyllys 	}
9823089Swyllys 
9835221Swyllys 	if (name != NULL) {
9845221Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
9853089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
9863089Swyllys 	}
9873089Swyllys 
9885221Swyllys 	if (email != NULL) {
9895221Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
9903089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
9913089Swyllys 	}
9923089Swyllys 
9933089Swyllys out:
9943089Swyllys 	if (country)
9953089Swyllys 		free(country);
9963089Swyllys 	if (state)
9973089Swyllys 		free(state);
9983089Swyllys 	if (locality)
9993089Swyllys 		free(locality);
10003089Swyllys 	if (org)
10013089Swyllys 		free(org);
10023089Swyllys 	if (unit)
10033089Swyllys 		free(unit);
10043089Swyllys 	if (name)
10053089Swyllys 		free(name);
10063089Swyllys 	if (email)
10073089Swyllys 		free(email);
10083089Swyllys 
10093089Swyllys 	if (subname == NULL)
10103089Swyllys 		return (-1);
10113089Swyllys 	else {
10123089Swyllys 		*result = subname;
10133089Swyllys 		return (0);
10143089Swyllys 	}
10153089Swyllys }
10163089Swyllys 
10173089Swyllys /*
10183089Swyllys  * Parse a string of KeyUsage values and convert
10193089Swyllys  * them to the correct KU Bits.
10203089Swyllys  * The field may be marked "critical" by prepending
10213089Swyllys  * "critical:" to the list.
10223089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
10233089Swyllys  */
10243089Swyllys KMF_RETURN
10253089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
10263089Swyllys {
10273089Swyllys 	KMF_RETURN ret = KMF_OK;
10283089Swyllys 	uint16_t kuval;
10293089Swyllys 	char *k;
10303089Swyllys 
10313089Swyllys 	*kubits = 0;
10326051Swyllys 	if (kustr == NULL || strlen(kustr) == 0)
10333089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10343089Swyllys 
10353089Swyllys 	/* Check to see if this is critical */
10366051Swyllys 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
10373089Swyllys 		*critical = TRUE;
10383089Swyllys 		kustr += strlen("critical:");
10393089Swyllys 	} else {
10403089Swyllys 		*critical = FALSE;
10413089Swyllys 	}
10423089Swyllys 
10433089Swyllys 	k = strtok(kustr, ",");
10443089Swyllys 	while (k != NULL) {
10455051Swyllys 		kuval = kmf_string_to_ku(k);
10463089Swyllys 		if (kuval == 0) {
10473089Swyllys 			*kubits = 0;
10483089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
10493089Swyllys 		}
10503089Swyllys 		*kubits |= kuval;
10513089Swyllys 		k = strtok(NULL, ",");
10523089Swyllys 	}
10533089Swyllys 
10543089Swyllys 	return (ret);
10553089Swyllys }
10563089Swyllys 
10573089Swyllys /*
10583089Swyllys  * Verify the alternate subject label is real or invalid.
10593089Swyllys  *
10603089Swyllys  * The field may be marked "critical" by prepending
10613089Swyllys  * "critical:" to the list.
10623089Swyllys  * EX:  "critical:IP=1.2.3.4"
10633089Swyllys  */
10643089Swyllys KMF_RETURN
10653089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
10663089Swyllys {
10673089Swyllys 	char *p;
10683089Swyllys 	KMF_RETURN rv = KMF_OK;
10693089Swyllys 
10703089Swyllys 	/* Check to see if this is critical */
10716051Swyllys 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
10723089Swyllys 		*critical = TRUE;
10733089Swyllys 		arg += strlen("critical:");
10743089Swyllys 	} else {
10753089Swyllys 		*critical = FALSE;
10763089Swyllys 	}
10773089Swyllys 
10783089Swyllys 	/* Make sure there is an "=" sign */
10793089Swyllys 	p = strchr(arg, '=');
10803089Swyllys 	if (p == NULL)
10813089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10823089Swyllys 
10833089Swyllys 	p[0] = '\0';
10843089Swyllys 
10853089Swyllys 	if (strcmp(arg, "IP") == 0)
10863089Swyllys 		*type = GENNAME_IPADDRESS;
10873089Swyllys 	else if (strcmp(arg, "DNS") == 0)
10883089Swyllys 		*type = GENNAME_DNSNAME;
10893089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
10903089Swyllys 		*type = GENNAME_RFC822NAME;
10913089Swyllys 	else if (strcmp(arg, "URI") == 0)
10923089Swyllys 		*type = GENNAME_URI;
10933089Swyllys 	else if (strcmp(arg, "DN") == 0)
10943089Swyllys 		*type = GENNAME_DIRECTORYNAME;
10953089Swyllys 	else if (strcmp(arg, "RID") == 0)
10963089Swyllys 		*type = GENNAME_REGISTEREDID;
10976051Swyllys 	else if (strcmp(arg, "KRB") == 0)
10986051Swyllys 		*type = GENNAME_KRB5PRINC;
10996051Swyllys 	else if (strcmp(arg, "UPN") == 0)
11006051Swyllys 		*type = GENNAME_SCLOGON_UPN;
11013089Swyllys 	else
11023089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
11033089Swyllys 
11043089Swyllys 	p[0] = '=';
11053089Swyllys 
11063089Swyllys 	return (rv);
11073089Swyllys }
11083089Swyllys 
11093089Swyllys int
11103089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
11113089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
11123089Swyllys {
11133089Swyllys 	char	prompt[1024];
11148132SWyllys.Ingersoll@Sun.COM 	char	temptoken[32];
11153089Swyllys 	char	*p = NULL;
11168132SWyllys.Ingersoll@Sun.COM 	char	*t = NULL;
11179126SWyllys.Ingersoll@Sun.COM 	int	len;
11183089Swyllys 
11199126SWyllys.Ingersoll@Sun.COM 	(void) memset(temptoken, 0, sizeof (temptoken));
11203089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
11213089Swyllys 		p = strchr(token_spec, ':');
11223089Swyllys 		if (p != NULL)
11238132SWyllys.Ingersoll@Sun.COM 			*p = 0;
11243089Swyllys 	}
11259126SWyllys.Ingersoll@Sun.COM 	len = strlen(token_spec);
11269126SWyllys.Ingersoll@Sun.COM 	if (len > sizeof (temptoken))
11279126SWyllys.Ingersoll@Sun.COM 		len = sizeof (temptoken);
11289126SWyllys.Ingersoll@Sun.COM 
11299126SWyllys.Ingersoll@Sun.COM 	(void) strncpy(temptoken, token_spec, len);
11308132SWyllys.Ingersoll@Sun.COM 
11318132SWyllys.Ingersoll@Sun.COM 	/*
11328132SWyllys.Ingersoll@Sun.COM 	 * Strip trailing whitespace
11338132SWyllys.Ingersoll@Sun.COM 	 */
11349126SWyllys.Ingersoll@Sun.COM 	t = temptoken + (len - 1);
11358132SWyllys.Ingersoll@Sun.COM 	while (isspace(*t) && t >= temptoken) {
11368132SWyllys.Ingersoll@Sun.COM 		*t = 0x00;
11378132SWyllys.Ingersoll@Sun.COM 		t--;
11388132SWyllys.Ingersoll@Sun.COM 	}
11398132SWyllys.Ingersoll@Sun.COM 
11403089Swyllys 	/*
11413089Swyllys 	 * Login to the token first.
11423089Swyllys 	 */
11433089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
11448132SWyllys.Ingersoll@Sun.COM 	    gettext(DEFAULT_TOKEN_PROMPT), temptoken);
11453089Swyllys 
11463089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
11475051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
11483089Swyllys 		cred->cred = NULL;
11493089Swyllys 		cred->credlen = 0;
11503089Swyllys 	}
11513089Swyllys 
11523089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
11533089Swyllys 		*p = ':';
11543089Swyllys 	return (KMF_OK);
11553089Swyllys }
11563089Swyllys 
11573089Swyllys KMF_RETURN
11583089Swyllys verify_file(char *filename)
11593089Swyllys {
11603089Swyllys 	KMF_RETURN ret = KMF_OK;
11613089Swyllys 	int fd;
11623089Swyllys 
11633089Swyllys 	/*
11643089Swyllys 	 * Attempt to open with  the EXCL flag so that if
11653089Swyllys 	 * it already exists, the open will fail.  It will
11663089Swyllys 	 * also fail if the file cannot be created due to
11673089Swyllys 	 * permissions on the parent directory, or if the
11683089Swyllys 	 * parent directory itself does not exist.
11693089Swyllys 	 */
11703089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
11713089Swyllys 	if (fd == -1)
11723089Swyllys 		return (KMF_ERR_OPEN_FILE);
11733089Swyllys 
11743089Swyllys 	/* If we were able to create it, delete it. */
11753089Swyllys 	(void) close(fd);
11763089Swyllys 	(void) unlink(filename);
11773089Swyllys 
11783089Swyllys 	return (ret);
11793089Swyllys }
11803089Swyllys 
11813089Swyllys void
11823089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
11833089Swyllys {
11843089Swyllys 	KMF_RETURN rv1, rv2;
11853089Swyllys 	char *plugin_errmsg = NULL;
11863089Swyllys 	char *kmf_errmsg = NULL;
11873089Swyllys 
11885051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
11895051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
11903089Swyllys 
11913089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
11923089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
11935051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
11945051Swyllys 		    plugin_errmsg);
11955051Swyllys 		kmf_free_str(plugin_errmsg);
11963089Swyllys 	}
11973089Swyllys 
11983089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
11995051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
12005051Swyllys 		    kmf_errmsg);
12015051Swyllys 		kmf_free_str(kmf_errmsg);
12023089Swyllys 	}
12033089Swyllys 
12043089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
12053089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
12063089Swyllys 
12073089Swyllys }
12086051Swyllys 
12096051Swyllys static KMF_RETURN
12106051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
12116051Swyllys {
12126051Swyllys 	if (newoid != NULL && ekus != NULL) {
12136051Swyllys 		ekus->eku_count++;
12146051Swyllys 
12156051Swyllys 		ekus->critlist = realloc(ekus->critlist,
12166051Swyllys 		    ekus->eku_count * sizeof (int));
12176051Swyllys 		if (ekus->critlist != NULL)
12186051Swyllys 			ekus->critlist[ekus->eku_count-1] = critical;
12196051Swyllys 		else
12206051Swyllys 			return (KMF_ERR_MEMORY);
12216051Swyllys 
12226051Swyllys 		ekus->ekulist = realloc(
12236051Swyllys 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
12246051Swyllys 		if (ekus->ekulist != NULL)
12256051Swyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
12266051Swyllys 		else
12276051Swyllys 			return (KMF_ERR_MEMORY);
12286051Swyllys 	}
12296051Swyllys 	return (KMF_OK);
12306051Swyllys }
12316051Swyllys 
12326051Swyllys void
12336051Swyllys free_eku_list(EKU_LIST *ekus)
12346051Swyllys {
12356051Swyllys 	if (ekus != NULL && ekus->eku_count > 0) {
12366051Swyllys 		int i;
12376051Swyllys 		for (i = 0; i < ekus->eku_count; i++) {
12386051Swyllys 			kmf_free_data(&ekus->ekulist[i]);
12396051Swyllys 		}
12406051Swyllys 		free(ekus->ekulist);
12416051Swyllys 		free(ekus->critlist);
124210818Swyllys.ingersoll@sun.com 		free(ekus);
12436051Swyllys 	}
12446051Swyllys }
12456051Swyllys 
12466051Swyllys static KMF_RETURN
12476051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
12486051Swyllys {
12496051Swyllys 	KMF_RETURN rv = KMF_OK;
12506051Swyllys 	KMF_OID *newoid;
12516051Swyllys 	int critical;
12526051Swyllys 
12536051Swyllys 	if (strncasecmp(ekustr, "critical:",
12546051Swyllys 	    strlen("critical:")) == 0) {
12556051Swyllys 		critical = TRUE;
12566051Swyllys 		ekustr += strlen("critical:");
12576051Swyllys 	} else {
12586051Swyllys 		critical = FALSE;
12596051Swyllys 	}
12606051Swyllys 	newoid = kmf_ekuname_to_oid(ekustr);
12616051Swyllys 	if (newoid != NULL) {
12626051Swyllys 		rv = addToEKUList(ekus, critical, newoid);
12636051Swyllys 		free(newoid);
12646051Swyllys 	} else {
12656051Swyllys 		rv = PK_ERR_USAGE;
12666051Swyllys 	}
12676051Swyllys 
12686051Swyllys 	return (rv);
12696051Swyllys }
12706051Swyllys 
12716051Swyllys KMF_RETURN
12726051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
12736051Swyllys {
12746051Swyllys 	KMF_RETURN rv = KMF_OK;
12756051Swyllys 	char *p;
12766051Swyllys 	EKU_LIST *ekus = NULL;
12776051Swyllys 
12786051Swyllys 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
12796051Swyllys 		return (0);
12806051Swyllys 
128110818Swyllys.ingersoll@sun.com 	ekus = calloc(sizeof (EKU_LIST), 1);
128210818Swyllys.ingersoll@sun.com 	if (ekus == NULL)
128310818Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
128410818Swyllys.ingersoll@sun.com 
12856051Swyllys 	/*
12866051Swyllys 	 * The list should be comma separated list of EKU Names.
12876051Swyllys 	 */
12886051Swyllys 	p = strtok(ekuliststr, ",");
12896051Swyllys 
12906051Swyllys 	/* If no tokens found, then maybe it's just a single EKU value */
12916051Swyllys 	if (p == NULL) {
12926051Swyllys 		rv = parse_ekus(ekuliststr, ekus);
12936051Swyllys 	}
12946051Swyllys 
12956051Swyllys 	while (p != NULL) {
12966051Swyllys 		rv = parse_ekus(p, ekus);
12976051Swyllys 
12986051Swyllys 		if (rv != KMF_OK)
12996051Swyllys 			break;
13006051Swyllys 		p = strtok(NULL, ",");
13016051Swyllys 	}
13026051Swyllys 
13036051Swyllys 	if (rv != KMF_OK)
13046051Swyllys 		free_eku_list(ekus);
13056051Swyllys 	else
13066051Swyllys 		*ekulist = ekus;
13076051Swyllys 
13086051Swyllys 	return (rv);
13096051Swyllys }
13106354Swyllys 
13116354Swyllys KMF_RETURN
13126354Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
13136354Swyllys {
13146354Swyllys 	CK_TOKEN_INFO info;
13156354Swyllys 	CK_SLOT_ID slot;
13166354Swyllys 	CK_RV ckrv;
13176354Swyllys 	KMF_RETURN rv;
13186354Swyllys 
13196354Swyllys 	*auth = 0;
13206354Swyllys 	rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
13216354Swyllys 	if (rv != KMF_OK)
13226354Swyllys 		return (rv);
13236354Swyllys 
13246354Swyllys 	ckrv = C_GetTokenInfo(slot, &info);
13256354Swyllys 	if (ckrv != KMF_OK)
13266354Swyllys 		return (KMF_ERR_INTERNAL);
13276354Swyllys 
13286354Swyllys 	*auth = (info.flags & CKF_LOGIN_REQUIRED);
13296354Swyllys 
13306354Swyllys 	return (KMF_OK);
13316354Swyllys }
1332*11973Swyllys.ingersoll@sun.com 
1333*11973Swyllys.ingersoll@sun.com void
1334*11973Swyllys.ingersoll@sun.com show_ecc_curves()
1335*11973Swyllys.ingersoll@sun.com {
1336*11973Swyllys.ingersoll@sun.com 	int i;
1337*11973Swyllys.ingersoll@sun.com 
1338*11973Swyllys.ingersoll@sun.com 	(void) printf(gettext("Supported ECC curve names:\n"));
1339*11973Swyllys.ingersoll@sun.com 	for (i = 0; i < number_of_curves; i++) {
1340*11973Swyllys.ingersoll@sun.com 		(void) printf("%s", oid_table[i].name);
1341*11973Swyllys.ingersoll@sun.com 		if (i > 0 && ((i+1) % 5) == 0)
1342*11973Swyllys.ingersoll@sun.com 			(void) printf("\n");
1343*11973Swyllys.ingersoll@sun.com 		else if (i+1 < number_of_curves)
1344*11973Swyllys.ingersoll@sun.com 			(void) printf(", ");
1345*11973Swyllys.ingersoll@sun.com 	}
1346*11973Swyllys.ingersoll@sun.com 	(void) printf("\n");
1347*11973Swyllys.ingersoll@sun.com }
1348*11973Swyllys.ingersoll@sun.com 
1349*11973Swyllys.ingersoll@sun.com KMF_OID *
1350*11973Swyllys.ingersoll@sun.com ecc_name_to_oid(char *name)
1351*11973Swyllys.ingersoll@sun.com {
1352*11973Swyllys.ingersoll@sun.com 	int i;
1353*11973Swyllys.ingersoll@sun.com 	for (i = 0; i < number_of_oids; i++) {
1354*11973Swyllys.ingersoll@sun.com 		if (strcasecmp(name, oid_table[i].name) == 0)
1355*11973Swyllys.ingersoll@sun.com 			return ((KMF_OID *)oid_table[i].oid);
1356*11973Swyllys.ingersoll@sun.com 	}
1357*11973Swyllys.ingersoll@sun.com 	return (NULL);
1358*11973Swyllys.ingersoll@sun.com }
1359