xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 12234:cd6642d6b7dd)
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
20*12234Swyllys.ingersoll@sun.com  *
21*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
220Sstevel@tonic-gate  */
230Sstevel@tonic-gate 
240Sstevel@tonic-gate /*
250Sstevel@tonic-gate  * This file contains the functions that are shared among
260Sstevel@tonic-gate  * the various services this tool will ultimately provide.
2717Sdinak  * The functions in this file return PKCS#11 CK_RV errors.
2817Sdinak  * Only one session and one login per token is supported
2917Sdinak  * at this time.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <ctype.h>
363089Swyllys #include <sys/types.h>
373089Swyllys #include <sys/stat.h>
383089Swyllys #include <fcntl.h>
393089Swyllys #include <tzfile.h>
400Sstevel@tonic-gate #include <cryptoutil.h>
410Sstevel@tonic-gate #include <security/cryptoki.h>
423089Swyllys #include <kmfapi.h>
430Sstevel@tonic-gate 
443089Swyllys #include "common.h"
4517Sdinak 
4617Sdinak /* Local status variables. */
4717Sdinak static boolean_t	initialized = B_FALSE;
4817Sdinak static boolean_t	session_opened = B_FALSE;
4917Sdinak static boolean_t	logged_in = B_FALSE;
5017Sdinak 
51864Sdinak /* Supporting structures and global variables for getopt_av(). */
52864Sdinak typedef struct	av_opts_s {
53864Sdinak 	int		shortnm;	/* short name character */
54864Sdinak 	char		*longnm;	/* long name string, NOT terminated */
55864Sdinak 	int		longnm_len;	/* length of long name string */
56864Sdinak 	boolean_t	has_arg;	/* takes optional argument */
57864Sdinak } av_opts;
58864Sdinak static av_opts		*opts_av = NULL;
59864Sdinak static const char	*_save_optstr = NULL;
60864Sdinak static int		_save_numopts = 0;
61864Sdinak 
62864Sdinak int			optind_av = 1;
63864Sdinak char			*optarg_av = NULL;
64864Sdinak 
653089Swyllys static void close_sess(CK_SESSION_HANDLE);
663089Swyllys static void logout_token(CK_SESSION_HANDLE);
673089Swyllys 
6811973Swyllys.ingersoll@sun.com struct oid_table_entry {
6911973Swyllys.ingersoll@sun.com 	const KMF_OID *oid;
7011973Swyllys.ingersoll@sun.com 	char *name;
7111973Swyllys.ingersoll@sun.com };
7211973Swyllys.ingersoll@sun.com 
7311973Swyllys.ingersoll@sun.com struct oid_table_entry oid_table[] = {
7411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp112r1, "secp112r1"},
7511973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp112r2, "secp112r2"},
7611973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp128r1, "secp128r1"},
7711973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp128r2, "secp128r2"},
7811973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160k1, "secp160k1"},
7911973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160r1, "secp160r1"},
8011973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp160r2, "secp160r2"},
8111973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp192k1, "secp192k1"},
8211973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp192r1, "secp192r1"},
8311973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp224k1, "secp224k1"},
8411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp224r1, "secp224r1"},
8511973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp256k1, "secp256k1"},
8611973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp256r1, "secp256r1"},
8711973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp384r1, "secp384r1"},
8811973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_secp521r1, "secp521r1"},
8911973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect113r1, "sect113r1"},
9011973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect113r2, "sect113r2"},
9111973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect131r1, "sect131r1"},
9211973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect131r2, "sect131r2"},
9311973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163k1, "sect163k1"},
9411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163r1, "sect163r1"},
9511973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect163r2, "sect163r2"},
9611973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect193r1, "sect193r1"},
9711973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect193r2, "sect193r2"},
9811973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect233k1, "sect233k1"},
9911973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect233r1, "sect233r1"},
10011973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect239k1, "sect239k1"},
10111973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect283k1, "sect283k1"},
10211973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect283r1, "sect283r1"},
10311973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect409k1, "sect409k1"},
10411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect409r1, "sect409r1"},
10511973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect571k1, "sect571k1"},
10611973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_sect571r1, "sect571r1"},
10711973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
10811973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
10911973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
11011973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
11111973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
11211973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
11311973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
11411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
11511973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
11611973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
11711973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
11811973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
11911973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
12011973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
12111973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
12211973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
12311973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_prime192v2, "prime192v2"},
12411973Swyllys.ingersoll@sun.com 	{ &KMFOID_ECC_prime192v3, "prime192v3"},
12511973Swyllys.ingersoll@sun.com 	{ &KMFOID_MD5, "md5"},
12611973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA1, "sha1"},
12711973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA256, "sha256"},
12811973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA384, "sha384"},
12911973Swyllys.ingersoll@sun.com 	{ &KMFOID_SHA512, "sha512"}
13011973Swyllys.ingersoll@sun.com };
13111973Swyllys.ingersoll@sun.com int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
13211973Swyllys.ingersoll@sun.com #define	number_of_curves (number_of_oids - 5)
13311973Swyllys.ingersoll@sun.com 
13417Sdinak /*
13517Sdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
13617Sdinak  * along with setting/resetting state variables.
13717Sdinak  */
1386669Swyllys static CK_RV
init_pkcs11(void)1396669Swyllys init_pkcs11(void)
14017Sdinak {
14117Sdinak 	CK_RV		rv = CKR_OK;
14217Sdinak 
14317Sdinak 	/* If C_Initialize() already called, nothing to do here. */
14417Sdinak 	if (initialized == B_TRUE)
14517Sdinak 		return (CKR_OK);
14617Sdinak 
14717Sdinak 	/* Reset state variables because C_Initialize() not yet done. */
14817Sdinak 	session_opened = B_FALSE;
14917Sdinak 	logged_in = B_FALSE;
15017Sdinak 
15117Sdinak 	/* Initialize PKCS#11 library. */
15217Sdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
15317Sdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
15417Sdinak 		return (rv);
15517Sdinak 	}
15617Sdinak 
15717Sdinak 	initialized = B_TRUE;
15817Sdinak 	return (CKR_OK);
15917Sdinak }
16017Sdinak 
16117Sdinak /*
16217Sdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
16317Sdinak  * if any, are closed, and thereby any logins are logged out also.
16417Sdinak  */
16517Sdinak void
final_pk11(CK_SESSION_HANDLE sess)16617Sdinak final_pk11(CK_SESSION_HANDLE sess)
16717Sdinak {
16817Sdinak 
16917Sdinak 	/* If the library wasn't initialized, nothing to do here. */
17017Sdinak 	if (!initialized)
17117Sdinak 		return;
17217Sdinak 
17317Sdinak 	/* Make sure the sesion is closed first. */
17417Sdinak 	close_sess(sess);
17517Sdinak 
17617Sdinak 	(void) C_Finalize(NULL);
17717Sdinak 	initialized = B_FALSE;
17817Sdinak }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate /*
18117Sdinak  * Close PKCS#11 session and reset state variables.  Any logins are
18217Sdinak  * logged out.
18317Sdinak  */
1843089Swyllys static void
close_sess(CK_SESSION_HANDLE sess)18517Sdinak close_sess(CK_SESSION_HANDLE sess)
18617Sdinak {
18717Sdinak 
18817Sdinak 	if (sess == NULL) {
18917Sdinak 		return;
19017Sdinak 	}
19117Sdinak 
19217Sdinak 	/* If session is already closed, nothing to do here. */
19317Sdinak 	if (!session_opened)
19417Sdinak 		return;
1950Sstevel@tonic-gate 
19617Sdinak 	/* Make sure user is logged out of token. */
19717Sdinak 	logout_token(sess);
19817Sdinak 
19917Sdinak 	(void) C_CloseSession(sess);
20017Sdinak 	session_opened = B_FALSE;
20117Sdinak }
20217Sdinak 
20317Sdinak /*
20417Sdinak  * Log user out of token and reset status variable.
20517Sdinak  */
2063089Swyllys static void
logout_token(CK_SESSION_HANDLE sess)20717Sdinak logout_token(CK_SESSION_HANDLE sess)
20817Sdinak {
20917Sdinak 
21017Sdinak 	if (sess == NULL) {
21117Sdinak 		return;
21217Sdinak 	}
21317Sdinak 
21417Sdinak 	/* If already logged out, nothing to do here. */
21517Sdinak 	if (!logged_in)
21617Sdinak 		return;
21717Sdinak 
21817Sdinak 	(void) C_Logout(sess);
21917Sdinak 	logged_in = B_FALSE;
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate /*
22317Sdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
22417Sdinak  * If two prompts are given, the PIN is confirmed with second prompt.
22517Sdinak  * Note that getphassphrase() may return data in static memory area.
22617Sdinak  */
22717Sdinak CK_RV
get_pin(char * prompt1,char * prompt2,CK_UTF8CHAR_PTR * pin,CK_ULONG * pinlen)22817Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
22917Sdinak {
2306051Swyllys 	char *save_phrase, *phrase1, *phrase2;
2310Sstevel@tonic-gate 
23217Sdinak 	/* Prompt user for a PIN. */
23317Sdinak 	if (prompt1 == NULL) {
23417Sdinak 		return (CKR_ARGUMENTS_BAD);
23517Sdinak 	}
23617Sdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
23717Sdinak 		return (CKR_FUNCTION_FAILED);
23817Sdinak 	}
23917Sdinak 
24017Sdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
24117Sdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
24217Sdinak 		return (CKR_HOST_MEMORY);
24317Sdinak 
24417Sdinak 	/* If second prompt given, PIN confirmation is requested. */
24517Sdinak 	if (prompt2 != NULL) {
24617Sdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
24717Sdinak 			free(save_phrase);
24817Sdinak 			return (CKR_FUNCTION_FAILED);
24917Sdinak 		}
25017Sdinak 		if (strcmp(save_phrase, phrase2) != 0) {
25117Sdinak 			free(save_phrase);
25217Sdinak 			return (CKR_PIN_INCORRECT);
25317Sdinak 		}
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate 
25617Sdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
25717Sdinak 	*pinlen = strlen(save_phrase);
25817Sdinak 	return (CKR_OK);
25917Sdinak }
26017Sdinak 
2616051Swyllys int
yn_to_int(char * ynstr)2626051Swyllys yn_to_int(char *ynstr)
2636051Swyllys {
2646051Swyllys 	char *y = gettext("yes");
2656051Swyllys 	char *n = gettext("no");
2666051Swyllys 	if (ynstr == NULL)
2676051Swyllys 		return (-1);
2686051Swyllys 
2696051Swyllys 	if (strncasecmp(ynstr, y, 1) == 0)
2706051Swyllys 		return (1);
2716051Swyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
2726051Swyllys 		return (0);
2736051Swyllys 	else
2746051Swyllys 		return (-1);
2756051Swyllys }
2766051Swyllys 
27717Sdinak /*
27817Sdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
27917Sdinak  * default prompt is used.  If not message for invalid input is supplied,
28017Sdinak  * a default will not be provided.  If the user provides no response,
28117Sdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
28217Sdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
28317Sdinak  */
28417Sdinak boolean_t
yesno(char * prompt,char * invalid,boolean_t dflt)28517Sdinak yesno(char *prompt, char *invalid, boolean_t dflt)
28617Sdinak {
2876051Swyllys 	char	*response, buf[1024];
2886051Swyllys 	int	ans;
28917Sdinak 
29017Sdinak 	if (prompt == NULL)
29117Sdinak 		prompt = gettext("Enter (y)es or (n)o? ");
29217Sdinak 
29317Sdinak 	for (;;) {
29417Sdinak 		/* Prompt user. */
29517Sdinak 		(void) printf("%s", prompt);
29617Sdinak 		(void) fflush(stdout);
29717Sdinak 
29817Sdinak 		/* Get the response. */
29917Sdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
30017Sdinak 			break;		/* go to default response */
30117Sdinak 
30217Sdinak 		/* Skip any leading white space. */
30317Sdinak 		while (isspace(*response))
30417Sdinak 			response++;
30517Sdinak 		if (*response == '\0')
30617Sdinak 			break;		/* go to default response */
30717Sdinak 
3086051Swyllys 		ans = yn_to_int(response);
3096051Swyllys 		if (ans == 1)
31017Sdinak 			return (B_TRUE);
3116051Swyllys 		else if (ans == 0)
31217Sdinak 			return (B_FALSE);
31317Sdinak 
31417Sdinak 		/* Indicate invalid input, and try again. */
31517Sdinak 		if (invalid != NULL)
3165051Swyllys 			(void) printf("%s", invalid);
31717Sdinak 	}
31817Sdinak 	return (dflt);
31917Sdinak }
32017Sdinak 
32117Sdinak /*
32217Sdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
32317Sdinak  * the size of the slot list buffer until the call is successful or an
32417Sdinak  * irrecoverable error occurs.
32517Sdinak  */
32617Sdinak CK_RV
get_token_slots(CK_SLOT_ID_PTR * slot_list,CK_ULONG * slot_count)32717Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
32817Sdinak {
32917Sdinak 	CK_ULONG	tmp_count = 0;
33017Sdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
33117Sdinak 	int		rv = CKR_OK;
33217Sdinak 
33317Sdinak 	if (!initialized)
3346669Swyllys 		if ((rv = init_pkcs11()) != CKR_OK)
33517Sdinak 			return (rv);
33617Sdinak 
33717Sdinak 	/*
33817Sdinak 	 * Get the slot count first because we don't know how many
33917Sdinak 	 * slots there are and how many of those slots even have tokens.
34017Sdinak 	 * Don't specify an arbitrary buffer size for the slot list;
34117Sdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
34217Sdinak 	 * Also select only those slots that have tokens in them,
34317Sdinak 	 * because this tool has no need to know about empty slots.
34417Sdinak 	 */
34517Sdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
34617Sdinak 		return (rv);
34717Sdinak 
34817Sdinak 	if (tmp_count == 0) {
34917Sdinak 		*slot_list = NULL_PTR;
35017Sdinak 		*slot_count = 0;
35117Sdinak 		return (CKR_OK);
35217Sdinak 	}
35317Sdinak 
35417Sdinak 	/* Allocate initial space for the slot list. */
35517Sdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
35617Sdinak 	    sizeof (CK_SLOT_ID))) == NULL)
35717Sdinak 		return (CKR_HOST_MEMORY);
35817Sdinak 
35917Sdinak 	/* Then get the slot list itself. */
36017Sdinak 	for (;;) {
36117Sdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
36217Sdinak 			*slot_list = tmp_list;
36317Sdinak 			*slot_count = tmp_count;
36417Sdinak 			break;
36517Sdinak 		}
36617Sdinak 
36717Sdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
36817Sdinak 			free(tmp_list);
36917Sdinak 			break;
37017Sdinak 		}
37117Sdinak 
37217Sdinak 		/* If the number of slots grew, try again. */
37317Sdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
37417Sdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
37517Sdinak 			free(tmp_list);
37617Sdinak 			rv = CKR_HOST_MEMORY;
37717Sdinak 			break;
37817Sdinak 		}
37917Sdinak 		tmp_list = tmp2_list;
38017Sdinak 	}
38117Sdinak 
38217Sdinak 	return (rv);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate /*
386864Sdinak  * Breaks out the getopt-style option string into a structure that can be
387864Sdinak  * traversed later for calls to getopt_av().  Option string is NOT altered,
388864Sdinak  * but the struct fields point to locations within option string.
389864Sdinak  */
390864Sdinak static int
populate_opts(char * optstring)391864Sdinak populate_opts(char *optstring)
392864Sdinak {
393864Sdinak 	int		i;
394864Sdinak 	av_opts		*temp;
395864Sdinak 	char		*marker;
396864Sdinak 
397864Sdinak 	if (optstring == NULL || *optstring == '\0')
398864Sdinak 		return (0);
399864Sdinak 
400864Sdinak 	/*
401864Sdinak 	 * This tries to imitate getopt(3c) Each option must conform to:
402864Sdinak 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
403864Sdinak 	 * If long name is missing, the short name is used for long name.
404864Sdinak 	 */
405864Sdinak 	for (i = 0; *optstring != '\0'; i++) {
406864Sdinak 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
407864Sdinak 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
4083089Swyllys 			if (opts_av != NULL)
4093089Swyllys 				free(opts_av);
410864Sdinak 			opts_av = NULL;
411864Sdinak 			return (0);
4123089Swyllys 		} else {
413864Sdinak 			opts_av = (av_opts *)temp;
4143089Swyllys 		}
415864Sdinak 
4163089Swyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
417864Sdinak 		marker = optstring;		/* may need optstring later */
418864Sdinak 
419864Sdinak 		opts_av[i].shortnm = *marker++;	/* set short name */
420864Sdinak 
421864Sdinak 		if (*marker == ':') {		/* check for opt arg */
422864Sdinak 			marker++;
423864Sdinak 			opts_av[i].has_arg = B_TRUE;
424864Sdinak 		}
425864Sdinak 
426864Sdinak 		if (*marker == '(') {		/* check and set long name */
427864Sdinak 			marker++;
428864Sdinak 			opts_av[i].longnm = marker;
429864Sdinak 			opts_av[i].longnm_len = strcspn(marker, ")");
430864Sdinak 			optstring = marker + opts_av[i].longnm_len + 1;
431864Sdinak 		} else {
432864Sdinak 			/* use short name option character */
433864Sdinak 			opts_av[i].longnm = optstring;
434864Sdinak 			opts_av[i].longnm_len = 1;
435864Sdinak 			optstring = marker;
436864Sdinak 		}
437864Sdinak 	}
438864Sdinak 
439864Sdinak 	return (i);
440864Sdinak }
441864Sdinak 
442864Sdinak /*
443864Sdinak  * getopt_av() is very similar to getopt(3c) in that the takes an option
444864Sdinak  * string, compares command line arguments for matches, and returns a single
445864Sdinak  * letter option when a match is found.  However, getopt_av() differs from
446864Sdinak  * getopt(3c) by requiring that only longname options and values be found
447864Sdinak  * on the command line and all leading dashes are omitted.  In other words,
448864Sdinak  * it tries to enforce only longname "option=value" arguments on the command
449864Sdinak  * line.  Boolean options are not allowed either.
450864Sdinak  */
451864Sdinak int
getopt_av(int argc,char * const * argv,const char * optstring)452864Sdinak getopt_av(int argc, char * const *argv, const char *optstring)
453864Sdinak {
454864Sdinak 	int	i;
455864Sdinak 	int	len;
4563089Swyllys 	char   *cur_option;
457864Sdinak 
458864Sdinak 	if (optind_av >= argc)
459864Sdinak 		return (EOF);
460864Sdinak 
461864Sdinak 	/* First time or when optstring changes from previous one */
462864Sdinak 	if (_save_optstr != optstring) {
463864Sdinak 		if (opts_av != NULL)
4645051Swyllys 			free(opts_av);
465864Sdinak 		opts_av = NULL;
466864Sdinak 		_save_optstr = optstring;
467864Sdinak 		_save_numopts = populate_opts((char *)optstring);
468864Sdinak 	}
469864Sdinak 
470864Sdinak 	for (i = 0; i < _save_numopts; i++) {
4713089Swyllys 		cur_option = argv[optind_av];
4723089Swyllys 
4733089Swyllys 		if (strcmp(cur_option, "--") == 0) {
474864Sdinak 			optind_av++;
475864Sdinak 			break;
476864Sdinak 		}
477864Sdinak 
4783089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
4793089Swyllys 			len = 1;
4803089Swyllys 			cur_option++; /* remove "-" */
4813089Swyllys 		} else {
4823089Swyllys 			len = strcspn(cur_option, "=");
4833089Swyllys 		}
484864Sdinak 
4853089Swyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
486864Sdinak 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
487864Sdinak 			/* matched */
488864Sdinak 			if (!opts_av[i].has_arg) {
489864Sdinak 				optind_av++;
490864Sdinak 				return (opts_av[i].shortnm);
491864Sdinak 			}
492864Sdinak 
493864Sdinak 			/* needs optarg */
4943089Swyllys 			if (cur_option[len] == '=') {
4953089Swyllys 				optarg_av = &(cur_option[len+1]);
496864Sdinak 				optind_av++;
497864Sdinak 				return (opts_av[i].shortnm);
498864Sdinak 			}
499864Sdinak 
500864Sdinak 			optarg_av = NULL;
501864Sdinak 			optind_av++;
502864Sdinak 			return ((int)'?');
503864Sdinak 		}
504864Sdinak 	}
505864Sdinak 
506864Sdinak 	return (EOF);
507864Sdinak }
5083089Swyllys 
5093089Swyllys KMF_KEYSTORE_TYPE
KS2Int(char * keystore_str)5103089Swyllys KS2Int(char *keystore_str)
5113089Swyllys {
5123089Swyllys 	if (keystore_str == NULL)
5133089Swyllys 		return (0);
5146051Swyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
5153089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
5166051Swyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
5173089Swyllys 		return (KMF_KEYSTORE_NSS);
5186051Swyllys 	else if (strcasecmp(keystore_str, "file") == 0)
5193089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
5203089Swyllys 	else
5213089Swyllys 		return (0);
5223089Swyllys }
5233089Swyllys 
52411973Swyllys.ingersoll@sun.com /*
52511973Swyllys.ingersoll@sun.com  * compare_oids
52611973Swyllys.ingersoll@sun.com  * return 1 if equal
52711973Swyllys.ingersoll@sun.com  */
52811973Swyllys.ingersoll@sun.com boolean_t
compare_oids(KMF_OID * oid1,const KMF_OID * oid2)52911973Swyllys.ingersoll@sun.com compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
53011973Swyllys.ingersoll@sun.com {
53111973Swyllys.ingersoll@sun.com 	return ((oid1->Length == oid2->Length) &&
53211973Swyllys.ingersoll@sun.com 	    !memcmp(oid1->Data, oid2->Data, oid1->Length));
53311973Swyllys.ingersoll@sun.com }
5343089Swyllys 
5353089Swyllys int
Str2KeyType(char * algm,KMF_OID * hashoid,KMF_KEY_ALG * ktype,KMF_ALGORITHM_INDEX * sigAlg)53611973Swyllys.ingersoll@sun.com Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
53711973Swyllys.ingersoll@sun.com     KMF_ALGORITHM_INDEX *sigAlg)
5383089Swyllys {
5393089Swyllys 	if (algm == NULL) {
54011973Swyllys.ingersoll@sun.com 		/* Default to SHA1+RSA */
54110744Swyllys.ingersoll@sun.com 		*sigAlg = KMF_ALGID_SHA1WithRSA;
5423089Swyllys 		*ktype = KMF_RSA;
5433089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
54411973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
54511973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
54611973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithDSA;
54711973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
54811973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithDSA;
54911973Swyllys.ingersoll@sun.com 		else
55011973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
5513089Swyllys 		*ktype = KMF_DSA;
5523089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
55311973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
55411973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
55511973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithRSA;
55611973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
55711973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithRSA;
55811973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA384))
55911973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA384WithRSA;
56011973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA512))
56111973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA512WithRSA;
56211973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_MD5))
56311973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_MD5WithRSA;
56411973Swyllys.ingersoll@sun.com 		else
56511973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
5663089Swyllys 		*ktype = KMF_RSA;
56711973Swyllys.ingersoll@sun.com 	} else if (strcasecmp(algm, "EC") == 0) {
56811973Swyllys.ingersoll@sun.com 		/* EC keys may be used with some SHA2 hashes */
56911973Swyllys.ingersoll@sun.com 		if (hashoid == NULL ||
57011973Swyllys.ingersoll@sun.com 		    compare_oids(hashoid, &KMFOID_SHA1))
57111973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA1WithECDSA;
57211973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA256))
57311973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA256WithECDSA;
57411973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA384))
57511973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA384WithECDSA;
57611973Swyllys.ingersoll@sun.com 		else if (compare_oids(hashoid, &KMFOID_SHA512))
57711973Swyllys.ingersoll@sun.com 			*sigAlg = KMF_ALGID_SHA512WithECDSA;
57811973Swyllys.ingersoll@sun.com 		else
57911973Swyllys.ingersoll@sun.com 			return (-1); /* unsupported hash/key combo */
58011973Swyllys.ingersoll@sun.com 
58111973Swyllys.ingersoll@sun.com 		*ktype = KMF_ECDSA;
5823089Swyllys 	} else {
5833089Swyllys 		return (-1);
5843089Swyllys 	}
5853089Swyllys 	return (0);
5863089Swyllys }
5873089Swyllys 
5883089Swyllys int
Str2SymKeyType(char * algm,KMF_KEY_ALG * ktype)5893089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
5903089Swyllys {
5913089Swyllys 	if (algm == NULL)
5923089Swyllys 		*ktype = KMF_AES;
5933089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
5943089Swyllys 		*ktype = KMF_AES;
5953089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
5963089Swyllys 		*ktype = KMF_RC4;
5973089Swyllys 	else if (strcasecmp(algm, "des") == 0)
5983089Swyllys 		*ktype = KMF_DES;
5993089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
6003089Swyllys 		*ktype = KMF_DES3;
6013812Shylee 	else if (strcasecmp(algm, "generic") == 0)
6023812Shylee 		*ktype = KMF_GENERIC_SECRET;
6033089Swyllys 	else
6043089Swyllys 		return (-1);
6053089Swyllys 
6063089Swyllys 	return (0);
6073089Swyllys }
6083089Swyllys 
6093089Swyllys int
Str2Lifetime(char * ltimestr,uint32_t * ltime)6103089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
6113089Swyllys {
6123089Swyllys 	int num;
6133089Swyllys 	char timetok[6];
6143089Swyllys 
6156051Swyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
6163089Swyllys 		/* default to 1 year lifetime */
6173089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
6183089Swyllys 		return (0);
6193089Swyllys 	}
6203089Swyllys 
6213089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
6223089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
6233089Swyllys 		return (-1);
6243089Swyllys 
6256051Swyllys 	if (strcasecmp(timetok, "day") == 0||
6266051Swyllys 	    strcasecmp(timetok, "days") == 0) {
6273089Swyllys 		*ltime = num * SECSPERDAY;
6286051Swyllys 	} else if (strcasecmp(timetok, "hour") == 0||
6296051Swyllys 	    strcasecmp(timetok, "hours") == 0) {
6303089Swyllys 		*ltime = num * SECSPERHOUR;
6316051Swyllys 	} else if (strcasecmp(timetok, "year") == 0 ||
6326051Swyllys 	    strcasecmp(timetok, "years") == 0) {
6333089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
6343089Swyllys 	} else {
6353089Swyllys 		*ltime = 0;
6363089Swyllys 		return (-1);
6373089Swyllys 	}
6383089Swyllys 
6393089Swyllys 	return (0);
6403089Swyllys }
6413089Swyllys 
6423089Swyllys int
OT2Int(char * objclass)6433089Swyllys OT2Int(char *objclass)
6443089Swyllys {
6453089Swyllys 	char *c = NULL;
6463089Swyllys 	int retval = 0;
6473089Swyllys 
6483089Swyllys 	if (objclass == NULL)
6493089Swyllys 		return (-1);
6503089Swyllys 
6513089Swyllys 	c = strchr(objclass, ':');
6523089Swyllys 	if (c != NULL) {
6536051Swyllys 		if (strcasecmp(c, ":private") == 0)
6543089Swyllys 			retval = PK_PRIVATE_OBJ;
6556051Swyllys 		else if (strcasecmp(c, ":public") == 0)
6563089Swyllys 			retval = PK_PUBLIC_OBJ;
6576051Swyllys 		else if (strcasecmp(c, ":both") == 0)
6583089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
6593089Swyllys 		else /* unrecognized option */
6603089Swyllys 			return (-1);
6613089Swyllys 
6623089Swyllys 		*c = '\0';
6633089Swyllys 	}
6643089Swyllys 
6656051Swyllys 	if (strcasecmp(objclass, "public") == 0) {
6663089Swyllys 		if (retval)
6673089Swyllys 			return (-1);
6685051Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
6696051Swyllys 	} else if (strcasecmp(objclass, "private") == 0) {
6703089Swyllys 		if (retval)
6713089Swyllys 			return (-1);
6723089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
6736051Swyllys 	} else if (strcasecmp(objclass, "both") == 0) {
6743089Swyllys 		if (retval)
6753089Swyllys 			return (-1);
6763089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
6776051Swyllys 	} else if (strcasecmp(objclass, "cert") == 0) {
6783089Swyllys 		return (retval | PK_CERT_OBJ);
6796051Swyllys 	} else if (strcasecmp(objclass, "key") == 0) {
6803089Swyllys 		if (retval == 0) /* return all keys */
6813089Swyllys 			return (retval | PK_KEY_OBJ);
6823089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
6833089Swyllys 			/* return all keys */
6843089Swyllys 			return (retval | PK_KEY_OBJ);
6853089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
6863089Swyllys 			/* Only return public keys */
6873089Swyllys 			return (retval | PK_PUBKEY_OBJ);
6883089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
6893089Swyllys 			/* Only return private keys */
6903089Swyllys 			return (retval | PK_PRIKEY_OBJ);
6916051Swyllys 	} else if (strcasecmp(objclass, "crl") == 0) {
6923089Swyllys 		if (retval)
6933089Swyllys 			return (-1);
6943089Swyllys 		return (retval | PK_CRL_OBJ);
6953089Swyllys 	}
6963089Swyllys 
6973089Swyllys 	if (retval == 0) /* No matches found */
6983089Swyllys 		retval = -1;
6993089Swyllys 	return (retval);
7003089Swyllys }
7013089Swyllys 
7023089Swyllys KMF_ENCODE_FORMAT
Str2Format(char * formstr)7033089Swyllys Str2Format(char *formstr)
7043089Swyllys {
7056051Swyllys 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
7063089Swyllys 		return (KMF_FORMAT_ASN1);
7076051Swyllys 	if (strcasecmp(formstr, "pem") == 0)
7083089Swyllys 		return (KMF_FORMAT_PEM);
7096051Swyllys 	if (strcasecmp(formstr, "pkcs12") == 0)
7103089Swyllys 		return (KMF_FORMAT_PKCS12);
7116051Swyllys 	if (strcasecmp(formstr, "raw") == 0)
7125051Swyllys 		return (KMF_FORMAT_RAWKEY);
7133089Swyllys 
7143089Swyllys 	return (KMF_FORMAT_UNDEF);
7153089Swyllys }
7163089Swyllys 
7173089Swyllys KMF_RETURN
select_token(void * kmfhandle,char * token,int readonly)7186051Swyllys select_token(void *kmfhandle, char *token, int readonly)
7193089Swyllys {
7205051Swyllys 	KMF_ATTRIBUTE attlist[10];
7215051Swyllys 	int i = 0;
7225051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
7233089Swyllys 	KMF_RETURN rv = KMF_OK;
7243089Swyllys 
7253089Swyllys 	if (token == NULL)
7263089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
7273089Swyllys 
7285051Swyllys 	kmf_set_attr_at_index(attlist, i,
7295051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
7305051Swyllys 	    sizeof (kstype));
7315051Swyllys 	i++;
7323089Swyllys 
7335051Swyllys 	if (token) {
7345051Swyllys 		kmf_set_attr_at_index(attlist, i,
7355051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
7365051Swyllys 		    strlen(token));
7375051Swyllys 		i++;
7385051Swyllys 	}
7395051Swyllys 
7405051Swyllys 	kmf_set_attr_at_index(attlist, i,
7415051Swyllys 	    KMF_READONLY_ATTR, &readonly,
7425051Swyllys 	    sizeof (readonly));
7435051Swyllys 	i++;
7445051Swyllys 
7455051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
7463089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
7473089Swyllys 		rv = KMF_OK;
7483089Swyllys 	return (rv);
7493089Swyllys }
7503089Swyllys 
7513089Swyllys KMF_RETURN
configure_nss(void * kmfhandle,char * dir,char * prefix)7523089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
7533089Swyllys {
7545051Swyllys 	KMF_ATTRIBUTE attlist[10];
7555051Swyllys 	int i = 0;
7565051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
7573089Swyllys 	KMF_RETURN rv = KMF_OK;
7585051Swyllys 
7595051Swyllys 	kmf_set_attr_at_index(attlist, i,
7605051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
7615051Swyllys 	    sizeof (kstype));
7625051Swyllys 	i++;
7633089Swyllys 
7645051Swyllys 	if (dir) {
7655051Swyllys 		kmf_set_attr_at_index(attlist, i,
7665051Swyllys 		    KMF_DIRPATH_ATTR, dir,
7675051Swyllys 		    strlen(dir));
7685051Swyllys 		i++;
7695051Swyllys 	}
7703089Swyllys 
7715051Swyllys 	if (prefix) {
7725051Swyllys 		kmf_set_attr_at_index(attlist, i,
7735051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
7745051Swyllys 		    strlen(prefix));
7755051Swyllys 		i++;
7765051Swyllys 
7775051Swyllys 		kmf_set_attr_at_index(attlist, i,
7785051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
7795051Swyllys 		    strlen(prefix));
7805051Swyllys 		i++;
7815051Swyllys 	}
7825051Swyllys 
7835051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
7843089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
7853089Swyllys 		rv = KMF_OK;
7863089Swyllys 
7873089Swyllys 	return (rv);
7883089Swyllys }
7893089Swyllys 
7903089Swyllys KMF_RETURN
get_pk12_password(KMF_CREDENTIAL * cred)7913089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
7923089Swyllys {
7933089Swyllys 	KMF_RETURN rv = KMF_OK;
7943089Swyllys 	char prompt[1024];
7953089Swyllys 
7963089Swyllys 	/*
7973089Swyllys 	 * Get the password to use for the PK12 encryption.
7983089Swyllys 	 */
7993089Swyllys 	(void) strlcpy(prompt,
8005051Swyllys 	    gettext("Enter password to use for "
8015051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
8023089Swyllys 
8033089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
8045051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
8053089Swyllys 		cred->cred = NULL;
8063089Swyllys 		cred->credlen = 0;
8073089Swyllys 	}
8083089Swyllys 
8093089Swyllys 	return (rv);
8103089Swyllys }
8113089Swyllys 
8125221Swyllys #define	FILENAME_PROMPT gettext("Filename:")
8135221Swyllys #define	FILENAME_MINLEN	1
8145221Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
8153089Swyllys 
8165221Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
8175221Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
8185221Swyllys 	"[Some-State]:")
8195221Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
8205221Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
8215221Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
8225221Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
8235221Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
8245221Swyllys 
8255221Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
8265221Swyllys 	"0x01020304):")
8275221Swyllys #define	SERNO_MINLEN	3
8285221Swyllys #define	SERNO_MAXLEN	42
8295221Swyllys 
8305221Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
8315221Swyllys #define	LABEL_MINLEN	1
8325221Swyllys #define	LABEL_MAXLEN	1024
8333089Swyllys 
8343089Swyllys #define	COUNTRY_DEFAULT "US"
8355221Swyllys #define	STATE_DEFAULT	NULL
8365221Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
8373089Swyllys 
8383089Swyllys #define	SUBNAMESIZ	1024
8393089Swyllys #define	RDN_MIN		1
8403089Swyllys #define	RDN_MAX		64
8413089Swyllys #define	COUNTRYNAME_MIN	2
8423089Swyllys #define	COUNTRYNAME_MAX	2
8433089Swyllys 
8443089Swyllys static char *
get_input_string(char * prompt,char * default_str,int min_len,int max_len)8453089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
8463089Swyllys {
8473089Swyllys 	char buf[1024];
8483089Swyllys 	char *response = NULL;
8493089Swyllys 	char *ret = NULL;
8503089Swyllys 	int len;
8513089Swyllys 
8523089Swyllys 	for (;;) {
8533089Swyllys 		(void) printf("\t%s", prompt);
8543089Swyllys 		(void) fflush(stdout);
8553089Swyllys 
8563089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
8573089Swyllys 		if (response == NULL) {
8583089Swyllys 			if (default_str != NULL) {
8593089Swyllys 				ret = strdup(default_str);
8603089Swyllys 			}
8613089Swyllys 			break;
8623089Swyllys 		}
8633089Swyllys 
8643089Swyllys 		/* Skip any leading white space. */
8653089Swyllys 		while (isspace(*response))
8663089Swyllys 			response++;
8673089Swyllys 		if (*response == '\0') {
8683089Swyllys 			if (default_str != NULL) {
8693089Swyllys 				ret = strdup(default_str);
8703089Swyllys 			}
8713089Swyllys 			break;
8723089Swyllys 		}
8733089Swyllys 
8743089Swyllys 		len = strlen(response);
8753089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
8763089Swyllys 		len--;
8773089Swyllys 		if (len >= min_len && len <= max_len) {
8783089Swyllys 			ret = strdup(response);
8793089Swyllys 			break;
8803089Swyllys 		}
8813089Swyllys 
8823089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
8833089Swyllys 
8843089Swyllys 	}
8853089Swyllys 
8863089Swyllys 	return (ret);
8873089Swyllys }
8883089Swyllys 
8893089Swyllys int
get_filename(char * txt,char ** result)8905221Swyllys get_filename(char *txt, char **result)
8915221Swyllys {
8925221Swyllys 	char prompt[1024];
8935221Swyllys 	char *fname = NULL;
8945221Swyllys 
8955221Swyllys 	(void) snprintf(prompt, sizeof (prompt),
8965221Swyllys 	    gettext("Enter filename for the %s: "),
8975221Swyllys 	    txt);
8985221Swyllys 	fname = get_input_string(prompt, NULL,
8995221Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
9005221Swyllys 	*result = fname;
9015221Swyllys 	return (0);
9025221Swyllys }
9035221Swyllys 
9045221Swyllys int
get_certlabel(char ** result)9055221Swyllys get_certlabel(char **result)
9065221Swyllys {
9075221Swyllys 	char *label = NULL;
9085221Swyllys 
9095221Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
9105221Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
9115221Swyllys 	*result = label;
9125221Swyllys 	return (0);
9135221Swyllys }
9145221Swyllys 
9155221Swyllys int
get_serial(char ** result)9165221Swyllys get_serial(char **result)
9175221Swyllys {
9185221Swyllys 	char *serial = NULL;
9195221Swyllys 
9205221Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
9215221Swyllys 	    SERNO_MAXLEN);
9225221Swyllys 
9235221Swyllys 	*result = serial;
9245221Swyllys 	return (0);
9255221Swyllys }
9265221Swyllys 
9275221Swyllys int
get_subname(char ** result)9283089Swyllys get_subname(char **result)
9293089Swyllys {
9303089Swyllys 	char *country = NULL;
9313089Swyllys 	char *state = NULL;
9323089Swyllys 	char *locality = NULL;
9333089Swyllys 	char *org = NULL;
9343089Swyllys 	char *unit = NULL;
9353089Swyllys 	char *name = NULL;
9363089Swyllys 	char *email = NULL;
9373089Swyllys 	char *subname = NULL;
9383089Swyllys 
9393089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
9403089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
9413089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
9423089Swyllys 	if (country == NULL)
9433089Swyllys 		return (-1);
9443089Swyllys 
9453089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
9463089Swyllys 	    RDN_MIN, RDN_MAX);
9473089Swyllys 
9483089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
9493089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
9503089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
9513089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
9523089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
9533089Swyllys 
9543089Swyllys 	/* Now create a subject name from the input strings */
9553089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
9563089Swyllys 		goto out;
9573089Swyllys 
9583089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
9593089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
9603089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
9615221Swyllys 	if (state != NULL) {
9625221Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
9635221Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
9645221Swyllys 	}
9653089Swyllys 
9665221Swyllys 	if (locality != NULL) {
9675221Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
9683089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
9693089Swyllys 	}
9703089Swyllys 
9715221Swyllys 	if (org != NULL) {
9725221Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
9733089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
9743089Swyllys 	}
9753089Swyllys 
9765221Swyllys 	if (unit != NULL) {
9775221Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
9783089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
9793089Swyllys 	}
9803089Swyllys 
9815221Swyllys 	if (name != NULL) {
9825221Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
9833089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
9843089Swyllys 	}
9853089Swyllys 
9865221Swyllys 	if (email != NULL) {
9875221Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
9883089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
9893089Swyllys 	}
9903089Swyllys 
9913089Swyllys out:
9923089Swyllys 	if (country)
9933089Swyllys 		free(country);
9943089Swyllys 	if (state)
9953089Swyllys 		free(state);
9963089Swyllys 	if (locality)
9973089Swyllys 		free(locality);
9983089Swyllys 	if (org)
9993089Swyllys 		free(org);
10003089Swyllys 	if (unit)
10013089Swyllys 		free(unit);
10023089Swyllys 	if (name)
10033089Swyllys 		free(name);
10043089Swyllys 	if (email)
10053089Swyllys 		free(email);
10063089Swyllys 
10073089Swyllys 	if (subname == NULL)
10083089Swyllys 		return (-1);
10093089Swyllys 	else {
10103089Swyllys 		*result = subname;
10113089Swyllys 		return (0);
10123089Swyllys 	}
10133089Swyllys }
10143089Swyllys 
10153089Swyllys /*
10163089Swyllys  * Parse a string of KeyUsage values and convert
10173089Swyllys  * them to the correct KU Bits.
10183089Swyllys  * The field may be marked "critical" by prepending
10193089Swyllys  * "critical:" to the list.
10203089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
10213089Swyllys  */
10223089Swyllys KMF_RETURN
verify_keyusage(char * kustr,uint16_t * kubits,int * critical)10233089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
10243089Swyllys {
10253089Swyllys 	KMF_RETURN ret = KMF_OK;
10263089Swyllys 	uint16_t kuval;
10273089Swyllys 	char *k;
10283089Swyllys 
10293089Swyllys 	*kubits = 0;
10306051Swyllys 	if (kustr == NULL || strlen(kustr) == 0)
10313089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10323089Swyllys 
10333089Swyllys 	/* Check to see if this is critical */
10346051Swyllys 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
10353089Swyllys 		*critical = TRUE;
10363089Swyllys 		kustr += strlen("critical:");
10373089Swyllys 	} else {
10383089Swyllys 		*critical = FALSE;
10393089Swyllys 	}
10403089Swyllys 
10413089Swyllys 	k = strtok(kustr, ",");
10423089Swyllys 	while (k != NULL) {
10435051Swyllys 		kuval = kmf_string_to_ku(k);
10443089Swyllys 		if (kuval == 0) {
10453089Swyllys 			*kubits = 0;
10463089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
10473089Swyllys 		}
10483089Swyllys 		*kubits |= kuval;
10493089Swyllys 		k = strtok(NULL, ",");
10503089Swyllys 	}
10513089Swyllys 
10523089Swyllys 	return (ret);
10533089Swyllys }
10543089Swyllys 
10553089Swyllys /*
10563089Swyllys  * Verify the alternate subject label is real or invalid.
10573089Swyllys  *
10583089Swyllys  * The field may be marked "critical" by prepending
10593089Swyllys  * "critical:" to the list.
10603089Swyllys  * EX:  "critical:IP=1.2.3.4"
10613089Swyllys  */
10623089Swyllys KMF_RETURN
verify_altname(char * arg,KMF_GENERALNAMECHOICES * type,int * critical)10633089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
10643089Swyllys {
10653089Swyllys 	char *p;
10663089Swyllys 	KMF_RETURN rv = KMF_OK;
10673089Swyllys 
10683089Swyllys 	/* Check to see if this is critical */
10696051Swyllys 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
10703089Swyllys 		*critical = TRUE;
10713089Swyllys 		arg += strlen("critical:");
10723089Swyllys 	} else {
10733089Swyllys 		*critical = FALSE;
10743089Swyllys 	}
10753089Swyllys 
10763089Swyllys 	/* Make sure there is an "=" sign */
10773089Swyllys 	p = strchr(arg, '=');
10783089Swyllys 	if (p == NULL)
10793089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
10803089Swyllys 
10813089Swyllys 	p[0] = '\0';
10823089Swyllys 
10833089Swyllys 	if (strcmp(arg, "IP") == 0)
10843089Swyllys 		*type = GENNAME_IPADDRESS;
10853089Swyllys 	else if (strcmp(arg, "DNS") == 0)
10863089Swyllys 		*type = GENNAME_DNSNAME;
10873089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
10883089Swyllys 		*type = GENNAME_RFC822NAME;
10893089Swyllys 	else if (strcmp(arg, "URI") == 0)
10903089Swyllys 		*type = GENNAME_URI;
10913089Swyllys 	else if (strcmp(arg, "DN") == 0)
10923089Swyllys 		*type = GENNAME_DIRECTORYNAME;
10933089Swyllys 	else if (strcmp(arg, "RID") == 0)
10943089Swyllys 		*type = GENNAME_REGISTEREDID;
10956051Swyllys 	else if (strcmp(arg, "KRB") == 0)
10966051Swyllys 		*type = GENNAME_KRB5PRINC;
10976051Swyllys 	else if (strcmp(arg, "UPN") == 0)
10986051Swyllys 		*type = GENNAME_SCLOGON_UPN;
10993089Swyllys 	else
11003089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
11013089Swyllys 
11023089Swyllys 	p[0] = '=';
11033089Swyllys 
11043089Swyllys 	return (rv);
11053089Swyllys }
11063089Swyllys 
11073089Swyllys int
get_token_password(KMF_KEYSTORE_TYPE kstype,char * token_spec,KMF_CREDENTIAL * cred)11083089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
11093089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
11103089Swyllys {
11113089Swyllys 	char	prompt[1024];
11128132SWyllys.Ingersoll@Sun.COM 	char	temptoken[32];
11133089Swyllys 	char	*p = NULL;
11148132SWyllys.Ingersoll@Sun.COM 	char	*t = NULL;
11159126SWyllys.Ingersoll@Sun.COM 	int	len;
11163089Swyllys 
11179126SWyllys.Ingersoll@Sun.COM 	(void) memset(temptoken, 0, sizeof (temptoken));
11183089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
11193089Swyllys 		p = strchr(token_spec, ':');
11203089Swyllys 		if (p != NULL)
11218132SWyllys.Ingersoll@Sun.COM 			*p = 0;
11223089Swyllys 	}
11239126SWyllys.Ingersoll@Sun.COM 	len = strlen(token_spec);
11249126SWyllys.Ingersoll@Sun.COM 	if (len > sizeof (temptoken))
11259126SWyllys.Ingersoll@Sun.COM 		len = sizeof (temptoken);
11269126SWyllys.Ingersoll@Sun.COM 
11279126SWyllys.Ingersoll@Sun.COM 	(void) strncpy(temptoken, token_spec, len);
11288132SWyllys.Ingersoll@Sun.COM 
11298132SWyllys.Ingersoll@Sun.COM 	/*
11308132SWyllys.Ingersoll@Sun.COM 	 * Strip trailing whitespace
11318132SWyllys.Ingersoll@Sun.COM 	 */
11329126SWyllys.Ingersoll@Sun.COM 	t = temptoken + (len - 1);
11338132SWyllys.Ingersoll@Sun.COM 	while (isspace(*t) && t >= temptoken) {
11348132SWyllys.Ingersoll@Sun.COM 		*t = 0x00;
11358132SWyllys.Ingersoll@Sun.COM 		t--;
11368132SWyllys.Ingersoll@Sun.COM 	}
11378132SWyllys.Ingersoll@Sun.COM 
11383089Swyllys 	/*
11393089Swyllys 	 * Login to the token first.
11403089Swyllys 	 */
11413089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
11428132SWyllys.Ingersoll@Sun.COM 	    gettext(DEFAULT_TOKEN_PROMPT), temptoken);
11433089Swyllys 
11443089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
11455051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
11463089Swyllys 		cred->cred = NULL;
11473089Swyllys 		cred->credlen = 0;
11483089Swyllys 	}
11493089Swyllys 
11503089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
11513089Swyllys 		*p = ':';
11523089Swyllys 	return (KMF_OK);
11533089Swyllys }
11543089Swyllys 
11553089Swyllys KMF_RETURN
verify_file(char * filename)11563089Swyllys verify_file(char *filename)
11573089Swyllys {
11583089Swyllys 	KMF_RETURN ret = KMF_OK;
11593089Swyllys 	int fd;
11603089Swyllys 
11613089Swyllys 	/*
11623089Swyllys 	 * Attempt to open with  the EXCL flag so that if
11633089Swyllys 	 * it already exists, the open will fail.  It will
11643089Swyllys 	 * also fail if the file cannot be created due to
11653089Swyllys 	 * permissions on the parent directory, or if the
11663089Swyllys 	 * parent directory itself does not exist.
11673089Swyllys 	 */
11683089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
1169*12234Swyllys.ingersoll@sun.com 	if (fd == -1) {
1170*12234Swyllys.ingersoll@sun.com 		if (errno == EEXIST)
1171*12234Swyllys.ingersoll@sun.com 			return (KMF_ERR_OPEN_FILE);
1172*12234Swyllys.ingersoll@sun.com 		else
1173*12234Swyllys.ingersoll@sun.com 			return (KMF_ERR_WRITE_FILE);
1174*12234Swyllys.ingersoll@sun.com 	}
11753089Swyllys 
11763089Swyllys 	/* If we were able to create it, delete it. */
11773089Swyllys 	(void) close(fd);
11783089Swyllys 	(void) unlink(filename);
11793089Swyllys 
11803089Swyllys 	return (ret);
11813089Swyllys }
11823089Swyllys 
11833089Swyllys void
display_error(void * handle,KMF_RETURN errcode,char * prefix)11843089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
11853089Swyllys {
11863089Swyllys 	KMF_RETURN rv1, rv2;
11873089Swyllys 	char *plugin_errmsg = NULL;
11883089Swyllys 	char *kmf_errmsg = NULL;
11893089Swyllys 
11905051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
11915051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
11923089Swyllys 
11933089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
11943089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
11955051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
11965051Swyllys 		    plugin_errmsg);
11975051Swyllys 		kmf_free_str(plugin_errmsg);
11983089Swyllys 	}
11993089Swyllys 
12003089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
12015051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
12025051Swyllys 		    kmf_errmsg);
12035051Swyllys 		kmf_free_str(kmf_errmsg);
12043089Swyllys 	}
12053089Swyllys 
12063089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
12073089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
12083089Swyllys 
12093089Swyllys }
12106051Swyllys 
12116051Swyllys static KMF_RETURN
addToEKUList(EKU_LIST * ekus,int critical,KMF_OID * newoid)12126051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
12136051Swyllys {
12146051Swyllys 	if (newoid != NULL && ekus != NULL) {
12156051Swyllys 		ekus->eku_count++;
12166051Swyllys 
12176051Swyllys 		ekus->critlist = realloc(ekus->critlist,
12186051Swyllys 		    ekus->eku_count * sizeof (int));
12196051Swyllys 		if (ekus->critlist != NULL)
12206051Swyllys 			ekus->critlist[ekus->eku_count-1] = critical;
12216051Swyllys 		else
12226051Swyllys 			return (KMF_ERR_MEMORY);
12236051Swyllys 
12246051Swyllys 		ekus->ekulist = realloc(
12256051Swyllys 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
12266051Swyllys 		if (ekus->ekulist != NULL)
12276051Swyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
12286051Swyllys 		else
12296051Swyllys 			return (KMF_ERR_MEMORY);
12306051Swyllys 	}
12316051Swyllys 	return (KMF_OK);
12326051Swyllys }
12336051Swyllys 
12346051Swyllys void
free_eku_list(EKU_LIST * ekus)12356051Swyllys free_eku_list(EKU_LIST *ekus)
12366051Swyllys {
12376051Swyllys 	if (ekus != NULL && ekus->eku_count > 0) {
12386051Swyllys 		int i;
12396051Swyllys 		for (i = 0; i < ekus->eku_count; i++) {
12406051Swyllys 			kmf_free_data(&ekus->ekulist[i]);
12416051Swyllys 		}
12426051Swyllys 		free(ekus->ekulist);
12436051Swyllys 		free(ekus->critlist);
124410818Swyllys.ingersoll@sun.com 		free(ekus);
12456051Swyllys 	}
12466051Swyllys }
12476051Swyllys 
12486051Swyllys static KMF_RETURN
parse_ekus(char * ekustr,EKU_LIST * ekus)12496051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
12506051Swyllys {
12516051Swyllys 	KMF_RETURN rv = KMF_OK;
12526051Swyllys 	KMF_OID *newoid;
12536051Swyllys 	int critical;
12546051Swyllys 
12556051Swyllys 	if (strncasecmp(ekustr, "critical:",
12566051Swyllys 	    strlen("critical:")) == 0) {
12576051Swyllys 		critical = TRUE;
12586051Swyllys 		ekustr += strlen("critical:");
12596051Swyllys 	} else {
12606051Swyllys 		critical = FALSE;
12616051Swyllys 	}
12626051Swyllys 	newoid = kmf_ekuname_to_oid(ekustr);
12636051Swyllys 	if (newoid != NULL) {
12646051Swyllys 		rv = addToEKUList(ekus, critical, newoid);
12656051Swyllys 		free(newoid);
12666051Swyllys 	} else {
12676051Swyllys 		rv = PK_ERR_USAGE;
12686051Swyllys 	}
12696051Swyllys 
12706051Swyllys 	return (rv);
12716051Swyllys }
12726051Swyllys 
12736051Swyllys KMF_RETURN
verify_ekunames(char * ekuliststr,EKU_LIST ** ekulist)12746051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
12756051Swyllys {
12766051Swyllys 	KMF_RETURN rv = KMF_OK;
12776051Swyllys 	char *p;
12786051Swyllys 	EKU_LIST *ekus = NULL;
12796051Swyllys 
12806051Swyllys 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
12816051Swyllys 		return (0);
12826051Swyllys 
128310818Swyllys.ingersoll@sun.com 	ekus = calloc(sizeof (EKU_LIST), 1);
128410818Swyllys.ingersoll@sun.com 	if (ekus == NULL)
128510818Swyllys.ingersoll@sun.com 		return (KMF_ERR_MEMORY);
128610818Swyllys.ingersoll@sun.com 
12876051Swyllys 	/*
12886051Swyllys 	 * The list should be comma separated list of EKU Names.
12896051Swyllys 	 */
12906051Swyllys 	p = strtok(ekuliststr, ",");
12916051Swyllys 
12926051Swyllys 	/* If no tokens found, then maybe it's just a single EKU value */
12936051Swyllys 	if (p == NULL) {
12946051Swyllys 		rv = parse_ekus(ekuliststr, ekus);
12956051Swyllys 	}
12966051Swyllys 
12976051Swyllys 	while (p != NULL) {
12986051Swyllys 		rv = parse_ekus(p, ekus);
12996051Swyllys 
13006051Swyllys 		if (rv != KMF_OK)
13016051Swyllys 			break;
13026051Swyllys 		p = strtok(NULL, ",");
13036051Swyllys 	}
13046051Swyllys 
13056051Swyllys 	if (rv != KMF_OK)
13066051Swyllys 		free_eku_list(ekus);
13076051Swyllys 	else
13086051Swyllys 		*ekulist = ekus;
13096051Swyllys 
13106051Swyllys 	return (rv);
13116051Swyllys }
13126354Swyllys 
13136354Swyllys KMF_RETURN
token_auth_needed(KMF_HANDLE_T handle,char * tokenlabel,int * auth)13146354Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
13156354Swyllys {
13166354Swyllys 	CK_TOKEN_INFO info;
13176354Swyllys 	CK_SLOT_ID slot;
13186354Swyllys 	CK_RV ckrv;
13196354Swyllys 	KMF_RETURN rv;
13206354Swyllys 
13216354Swyllys 	*auth = 0;
13226354Swyllys 	rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
13236354Swyllys 	if (rv != KMF_OK)
13246354Swyllys 		return (rv);
13256354Swyllys 
13266354Swyllys 	ckrv = C_GetTokenInfo(slot, &info);
13276354Swyllys 	if (ckrv != KMF_OK)
13286354Swyllys 		return (KMF_ERR_INTERNAL);
13296354Swyllys 
13306354Swyllys 	*auth = (info.flags & CKF_LOGIN_REQUIRED);
13316354Swyllys 
13326354Swyllys 	return (KMF_OK);
13336354Swyllys }
133411973Swyllys.ingersoll@sun.com 
133511973Swyllys.ingersoll@sun.com void
show_ecc_curves()133611973Swyllys.ingersoll@sun.com show_ecc_curves()
133711973Swyllys.ingersoll@sun.com {
133811973Swyllys.ingersoll@sun.com 	int i;
133911973Swyllys.ingersoll@sun.com 
134011973Swyllys.ingersoll@sun.com 	(void) printf(gettext("Supported ECC curve names:\n"));
134111973Swyllys.ingersoll@sun.com 	for (i = 0; i < number_of_curves; i++) {
134211973Swyllys.ingersoll@sun.com 		(void) printf("%s", oid_table[i].name);
134311973Swyllys.ingersoll@sun.com 		if (i > 0 && ((i+1) % 5) == 0)
134411973Swyllys.ingersoll@sun.com 			(void) printf("\n");
134511973Swyllys.ingersoll@sun.com 		else if (i+1 < number_of_curves)
134611973Swyllys.ingersoll@sun.com 			(void) printf(", ");
134711973Swyllys.ingersoll@sun.com 	}
134811973Swyllys.ingersoll@sun.com 	(void) printf("\n");
134911973Swyllys.ingersoll@sun.com }
135011973Swyllys.ingersoll@sun.com 
135111973Swyllys.ingersoll@sun.com KMF_OID *
ecc_name_to_oid(char * name)135211973Swyllys.ingersoll@sun.com ecc_name_to_oid(char *name)
135311973Swyllys.ingersoll@sun.com {
135411973Swyllys.ingersoll@sun.com 	int i;
135511973Swyllys.ingersoll@sun.com 	for (i = 0; i < number_of_oids; i++) {
135611973Swyllys.ingersoll@sun.com 		if (strcasecmp(name, oid_table[i].name) == 0)
135711973Swyllys.ingersoll@sun.com 			return ((KMF_OID *)oid_table[i].oid);
135811973Swyllys.ingersoll@sun.com 	}
135911973Swyllys.ingersoll@sun.com 	return (NULL);
136011973Swyllys.ingersoll@sun.com }
1361