xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 5051:cbbb7c8b40a9)
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 /*
223812Shylee  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * This file contains the functions that are shared among
300Sstevel@tonic-gate  * the various services this tool will ultimately provide.
3117Sdinak  * The functions in this file return PKCS#11 CK_RV errors.
3217Sdinak  * Only one session and one login per token is supported
3317Sdinak  * at this time.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <string.h>
390Sstevel@tonic-gate #include <ctype.h>
403089Swyllys #include <sys/types.h>
413089Swyllys #include <sys/stat.h>
423089Swyllys #include <fcntl.h>
433089Swyllys #include <tzfile.h>
440Sstevel@tonic-gate #include <cryptoutil.h>
450Sstevel@tonic-gate #include <security/cryptoki.h>
463089Swyllys #include <kmfapi.h>
470Sstevel@tonic-gate 
483089Swyllys #include "common.h"
4917Sdinak 
5017Sdinak /* Local status variables. */
5117Sdinak static boolean_t	initialized = B_FALSE;
5217Sdinak static boolean_t	session_opened = B_FALSE;
5317Sdinak static boolean_t	logged_in = B_FALSE;
5417Sdinak 
55864Sdinak /* Supporting structures and global variables for getopt_av(). */
56864Sdinak typedef struct	av_opts_s {
57864Sdinak 	int		shortnm;	/* short name character */
58864Sdinak 	char		*longnm;	/* long name string, NOT terminated */
59864Sdinak 	int		longnm_len;	/* length of long name string */
60864Sdinak 	boolean_t	has_arg;	/* takes optional argument */
61864Sdinak } av_opts;
62864Sdinak static av_opts		*opts_av = NULL;
63864Sdinak static const char	*_save_optstr = NULL;
64864Sdinak static int		_save_numopts = 0;
65864Sdinak 
66864Sdinak int			optind_av = 1;
67864Sdinak char			*optarg_av = NULL;
68864Sdinak 
693089Swyllys static void close_sess(CK_SESSION_HANDLE);
703089Swyllys static void logout_token(CK_SESSION_HANDLE);
713089Swyllys 
7217Sdinak /*
7317Sdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
7417Sdinak  * along with setting/resetting state variables.
7517Sdinak  */
7617Sdinak CK_RV
7717Sdinak init_pk11(void)
7817Sdinak {
7917Sdinak 	CK_RV		rv = CKR_OK;
8017Sdinak 
8117Sdinak 	/* If C_Initialize() already called, nothing to do here. */
8217Sdinak 	if (initialized == B_TRUE)
8317Sdinak 		return (CKR_OK);
8417Sdinak 
8517Sdinak 	/* Reset state variables because C_Initialize() not yet done. */
8617Sdinak 	session_opened = B_FALSE;
8717Sdinak 	logged_in = B_FALSE;
8817Sdinak 
8917Sdinak 	/* Initialize PKCS#11 library. */
9017Sdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
9117Sdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
9217Sdinak 		return (rv);
9317Sdinak 	}
9417Sdinak 
9517Sdinak 	initialized = B_TRUE;
9617Sdinak 	return (CKR_OK);
9717Sdinak }
9817Sdinak 
9917Sdinak /*
10017Sdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
10117Sdinak  * if any, are closed, and thereby any logins are logged out also.
10217Sdinak  */
10317Sdinak void
10417Sdinak final_pk11(CK_SESSION_HANDLE sess)
10517Sdinak {
10617Sdinak 
10717Sdinak 	/* If the library wasn't initialized, nothing to do here. */
10817Sdinak 	if (!initialized)
10917Sdinak 		return;
11017Sdinak 
11117Sdinak 	/* Make sure the sesion is closed first. */
11217Sdinak 	close_sess(sess);
11317Sdinak 
11417Sdinak 	(void) C_Finalize(NULL);
11517Sdinak 	initialized = B_FALSE;
11617Sdinak }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /*
11917Sdinak  * Close PKCS#11 session and reset state variables.  Any logins are
12017Sdinak  * logged out.
12117Sdinak  */
1223089Swyllys static void
12317Sdinak close_sess(CK_SESSION_HANDLE sess)
12417Sdinak {
12517Sdinak 
12617Sdinak 	if (sess == NULL) {
12717Sdinak 		return;
12817Sdinak 	}
12917Sdinak 
13017Sdinak 	/* If session is already closed, nothing to do here. */
13117Sdinak 	if (!session_opened)
13217Sdinak 		return;
1330Sstevel@tonic-gate 
13417Sdinak 	/* Make sure user is logged out of token. */
13517Sdinak 	logout_token(sess);
13617Sdinak 
13717Sdinak 	(void) C_CloseSession(sess);
13817Sdinak 	session_opened = B_FALSE;
13917Sdinak }
14017Sdinak 
14117Sdinak /*
14217Sdinak  * Log user out of token and reset status variable.
14317Sdinak  */
1443089Swyllys static void
14517Sdinak logout_token(CK_SESSION_HANDLE sess)
14617Sdinak {
14717Sdinak 
14817Sdinak 	if (sess == NULL) {
14917Sdinak 		return;
15017Sdinak 	}
15117Sdinak 
15217Sdinak 	/* If already logged out, nothing to do here. */
15317Sdinak 	if (!logged_in)
15417Sdinak 		return;
15517Sdinak 
15617Sdinak 	(void) C_Logout(sess);
15717Sdinak 	logged_in = B_FALSE;
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate /*
16117Sdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
16217Sdinak  * If two prompts are given, the PIN is confirmed with second prompt.
16317Sdinak  * Note that getphassphrase() may return data in static memory area.
16417Sdinak  */
16517Sdinak CK_RV
16617Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
16717Sdinak {
16817Sdinak 	char		*save_phrase, *phrase1, *phrase2;
16917Sdinak 
1703089Swyllys 
1713089Swyllys #ifdef DEBUG
1723089Swyllys 	if (getenv("TOKENPIN") != NULL) {
1733089Swyllys 		*pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN"));
1743089Swyllys 		*pinlen = strlen((char *)(*pin));
1753089Swyllys 		return (CKR_OK);
1763089Swyllys 	}
1773089Swyllys #endif /* DEBUG */
1780Sstevel@tonic-gate 
17917Sdinak 	/* Prompt user for a PIN. */
18017Sdinak 	if (prompt1 == NULL) {
18117Sdinak 		return (CKR_ARGUMENTS_BAD);
18217Sdinak 	}
18317Sdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
18417Sdinak 		return (CKR_FUNCTION_FAILED);
18517Sdinak 	}
18617Sdinak 
18717Sdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
18817Sdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
18917Sdinak 		return (CKR_HOST_MEMORY);
19017Sdinak 
19117Sdinak 	/* If second prompt given, PIN confirmation is requested. */
19217Sdinak 	if (prompt2 != NULL) {
19317Sdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
19417Sdinak 			free(save_phrase);
19517Sdinak 			return (CKR_FUNCTION_FAILED);
19617Sdinak 		}
19717Sdinak 		if (strcmp(save_phrase, phrase2) != 0) {
19817Sdinak 			free(save_phrase);
19917Sdinak 			return (CKR_PIN_INCORRECT);
20017Sdinak 		}
2010Sstevel@tonic-gate 	}
2020Sstevel@tonic-gate 
20317Sdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
20417Sdinak 	*pinlen = strlen(save_phrase);
20517Sdinak 	return (CKR_OK);
20617Sdinak }
20717Sdinak 
20817Sdinak /*
20917Sdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
21017Sdinak  * default prompt is used.  If not message for invalid input is supplied,
21117Sdinak  * a default will not be provided.  If the user provides no response,
21217Sdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
21317Sdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
21417Sdinak  */
21517Sdinak boolean_t
21617Sdinak yesno(char *prompt, char *invalid, boolean_t dflt)
21717Sdinak {
21817Sdinak 	char		*response, buf[1024];
21917Sdinak 	char		*yes = gettext("yes");
22017Sdinak 	char		*no = gettext("no");
22117Sdinak 
2223089Swyllys 
2233089Swyllys #ifdef DEBUG
2243089Swyllys 	/* If debugging or testing, return TRUE and avoid prompting */
2253089Swyllys 	if (getenv("TOKENPIN") != NULL) {
2263089Swyllys 		return (B_TRUE);
2273089Swyllys 	}
2283089Swyllys #endif /* DEBUG */
22917Sdinak 
23017Sdinak 	if (prompt == NULL)
23117Sdinak 		prompt = gettext("Enter (y)es or (n)o? ");
23217Sdinak 
23317Sdinak 	for (;;) {
23417Sdinak 		/* Prompt user. */
23517Sdinak 		(void) printf("%s", prompt);
23617Sdinak 		(void) fflush(stdout);
23717Sdinak 
23817Sdinak 		/* Get the response. */
23917Sdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
24017Sdinak 			break;		/* go to default response */
24117Sdinak 
24217Sdinak 		/* Skip any leading white space. */
24317Sdinak 		while (isspace(*response))
24417Sdinak 			response++;
24517Sdinak 		if (*response == '\0')
24617Sdinak 			break;		/* go to default response */
24717Sdinak 
24817Sdinak 		/* Is it valid input?  Return appropriately. */
24917Sdinak 		if (strncasecmp(response, yes, 1) == 0)
25017Sdinak 			return (B_TRUE);
25117Sdinak 		if (strncasecmp(response, no, 1) == 0)
25217Sdinak 			return (B_FALSE);
25317Sdinak 
25417Sdinak 		/* Indicate invalid input, and try again. */
25517Sdinak 		if (invalid != NULL)
256*5051Swyllys 			(void) printf("%s", invalid);
25717Sdinak 	}
25817Sdinak 	return (dflt);
25917Sdinak }
26017Sdinak 
26117Sdinak /*
26217Sdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
26317Sdinak  * the size of the slot list buffer until the call is successful or an
26417Sdinak  * irrecoverable error occurs.
26517Sdinak  */
26617Sdinak CK_RV
26717Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
26817Sdinak {
26917Sdinak 	CK_ULONG	tmp_count = 0;
27017Sdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
27117Sdinak 	int		rv = CKR_OK;
27217Sdinak 
27317Sdinak 	if (!initialized)
27417Sdinak 		if ((rv = init_pk11()) != CKR_OK)
27517Sdinak 			return (rv);
27617Sdinak 
27717Sdinak 	/*
27817Sdinak 	 * Get the slot count first because we don't know how many
27917Sdinak 	 * slots there are and how many of those slots even have tokens.
28017Sdinak 	 * Don't specify an arbitrary buffer size for the slot list;
28117Sdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
28217Sdinak 	 * Also select only those slots that have tokens in them,
28317Sdinak 	 * because this tool has no need to know about empty slots.
28417Sdinak 	 */
28517Sdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
28617Sdinak 		return (rv);
28717Sdinak 
28817Sdinak 	if (tmp_count == 0) {
28917Sdinak 		*slot_list = NULL_PTR;
29017Sdinak 		*slot_count = 0;
29117Sdinak 		return (CKR_OK);
29217Sdinak 	}
29317Sdinak 
29417Sdinak 	/* Allocate initial space for the slot list. */
29517Sdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
29617Sdinak 	    sizeof (CK_SLOT_ID))) == NULL)
29717Sdinak 		return (CKR_HOST_MEMORY);
29817Sdinak 
29917Sdinak 	/* Then get the slot list itself. */
30017Sdinak 	for (;;) {
30117Sdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
30217Sdinak 			*slot_list = tmp_list;
30317Sdinak 			*slot_count = tmp_count;
30417Sdinak 			break;
30517Sdinak 		}
30617Sdinak 
30717Sdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
30817Sdinak 			free(tmp_list);
30917Sdinak 			break;
31017Sdinak 		}
31117Sdinak 
31217Sdinak 		/* If the number of slots grew, try again. */
31317Sdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
31417Sdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
31517Sdinak 			free(tmp_list);
31617Sdinak 			rv = CKR_HOST_MEMORY;
31717Sdinak 			break;
31817Sdinak 		}
31917Sdinak 		tmp_list = tmp2_list;
32017Sdinak 	}
32117Sdinak 
32217Sdinak 	return (rv);
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate /*
326864Sdinak  * Breaks out the getopt-style option string into a structure that can be
327864Sdinak  * traversed later for calls to getopt_av().  Option string is NOT altered,
328864Sdinak  * but the struct fields point to locations within option string.
329864Sdinak  */
330864Sdinak static int
331864Sdinak populate_opts(char *optstring)
332864Sdinak {
333864Sdinak 	int		i;
334864Sdinak 	av_opts		*temp;
335864Sdinak 	char		*marker;
336864Sdinak 
337864Sdinak 	if (optstring == NULL || *optstring == '\0')
338864Sdinak 		return (0);
339864Sdinak 
340864Sdinak 	/*
341864Sdinak 	 * This tries to imitate getopt(3c) Each option must conform to:
342864Sdinak 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
343864Sdinak 	 * If long name is missing, the short name is used for long name.
344864Sdinak 	 */
345864Sdinak 	for (i = 0; *optstring != '\0'; i++) {
346864Sdinak 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
347864Sdinak 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
3483089Swyllys 			if (opts_av != NULL)
3493089Swyllys 				free(opts_av);
350864Sdinak 			opts_av = NULL;
351864Sdinak 			return (0);
3523089Swyllys 		} else {
353864Sdinak 			opts_av = (av_opts *)temp;
3543089Swyllys 		}
355864Sdinak 
3563089Swyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
357864Sdinak 		marker = optstring;		/* may need optstring later */
358864Sdinak 
359864Sdinak 		opts_av[i].shortnm = *marker++;	/* set short name */
360864Sdinak 
361864Sdinak 		if (*marker == ':') {		/* check for opt arg */
362864Sdinak 			marker++;
363864Sdinak 			opts_av[i].has_arg = B_TRUE;
364864Sdinak 		}
365864Sdinak 
366864Sdinak 		if (*marker == '(') {		/* check and set long name */
367864Sdinak 			marker++;
368864Sdinak 			opts_av[i].longnm = marker;
369864Sdinak 			opts_av[i].longnm_len = strcspn(marker, ")");
370864Sdinak 			optstring = marker + opts_av[i].longnm_len + 1;
371864Sdinak 		} else {
372864Sdinak 			/* use short name option character */
373864Sdinak 			opts_av[i].longnm = optstring;
374864Sdinak 			opts_av[i].longnm_len = 1;
375864Sdinak 			optstring = marker;
376864Sdinak 		}
377864Sdinak 	}
378864Sdinak 
379864Sdinak 	return (i);
380864Sdinak }
381864Sdinak 
382864Sdinak /*
383864Sdinak  * getopt_av() is very similar to getopt(3c) in that the takes an option
384864Sdinak  * string, compares command line arguments for matches, and returns a single
385864Sdinak  * letter option when a match is found.  However, getopt_av() differs from
386864Sdinak  * getopt(3c) by requiring that only longname options and values be found
387864Sdinak  * on the command line and all leading dashes are omitted.  In other words,
388864Sdinak  * it tries to enforce only longname "option=value" arguments on the command
389864Sdinak  * line.  Boolean options are not allowed either.
390864Sdinak  */
391864Sdinak int
392864Sdinak getopt_av(int argc, char * const *argv, const char *optstring)
393864Sdinak {
394864Sdinak 	int	i;
395864Sdinak 	int	len;
3963089Swyllys 	char   *cur_option;
397864Sdinak 
398864Sdinak 	if (optind_av >= argc)
399864Sdinak 		return (EOF);
400864Sdinak 
401864Sdinak 	/* First time or when optstring changes from previous one */
402864Sdinak 	if (_save_optstr != optstring) {
403864Sdinak 		if (opts_av != NULL)
404*5051Swyllys 			free(opts_av);
405864Sdinak 		opts_av = NULL;
406864Sdinak 		_save_optstr = optstring;
407864Sdinak 		_save_numopts = populate_opts((char *)optstring);
408864Sdinak 	}
409864Sdinak 
410864Sdinak 	for (i = 0; i < _save_numopts; i++) {
4113089Swyllys 		cur_option = argv[optind_av];
4123089Swyllys 
4133089Swyllys 		if (strcmp(cur_option, "--") == 0) {
414864Sdinak 			optind_av++;
415864Sdinak 			break;
416864Sdinak 		}
417864Sdinak 
4183089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
4193089Swyllys 			len = 1;
4203089Swyllys 			cur_option++; /* remove "-" */
4213089Swyllys 		} else {
4223089Swyllys 			len = strcspn(cur_option, "=");
4233089Swyllys 		}
424864Sdinak 
4253089Swyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
426864Sdinak 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
427864Sdinak 			/* matched */
428864Sdinak 			if (!opts_av[i].has_arg) {
429864Sdinak 				optind_av++;
430864Sdinak 				return (opts_av[i].shortnm);
431864Sdinak 			}
432864Sdinak 
433864Sdinak 			/* needs optarg */
4343089Swyllys 			if (cur_option[len] == '=') {
4353089Swyllys 				optarg_av = &(cur_option[len+1]);
436864Sdinak 				optind_av++;
437864Sdinak 				return (opts_av[i].shortnm);
438864Sdinak 			}
439864Sdinak 
440864Sdinak 			optarg_av = NULL;
441864Sdinak 			optind_av++;
442864Sdinak 			return ((int)'?');
443864Sdinak 		}
444864Sdinak 	}
445864Sdinak 
446864Sdinak 	return (EOF);
447864Sdinak }
4483089Swyllys 
4493089Swyllys KMF_KEYSTORE_TYPE
4503089Swyllys KS2Int(char *keystore_str)
4513089Swyllys {
4523089Swyllys 	if (keystore_str == NULL)
4533089Swyllys 		return (0);
4543089Swyllys 	if (!strcasecmp(keystore_str, "pkcs11"))
4553089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
4563089Swyllys 	else if (!strcasecmp(keystore_str, "nss"))
4573089Swyllys 		return (KMF_KEYSTORE_NSS);
4583089Swyllys 	else if (!strcasecmp(keystore_str, "file"))
4593089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
4603089Swyllys 	else
4613089Swyllys 		return (0);
4623089Swyllys }
4633089Swyllys 
4643089Swyllys 
4653089Swyllys int
4663089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
4673089Swyllys {
4683089Swyllys 	if (algm == NULL) {
4693089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4703089Swyllys 		*ktype = KMF_RSA;
4713089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
4723089Swyllys 		*sigAlg = KMF_ALGID_SHA1WithDSA;
4733089Swyllys 		*ktype = KMF_DSA;
4743089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
4753089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4763089Swyllys 		*ktype = KMF_RSA;
4773089Swyllys 	} else {
4783089Swyllys 		return (-1);
4793089Swyllys 	}
4803089Swyllys 	return (0);
4813089Swyllys }
4823089Swyllys 
4833089Swyllys int
4843089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
4853089Swyllys {
4863089Swyllys 	if (algm == NULL)
4873089Swyllys 		*ktype = KMF_AES;
4883089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
4893089Swyllys 		*ktype = KMF_AES;
4903089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
4913089Swyllys 		*ktype = KMF_RC4;
4923089Swyllys 	else if (strcasecmp(algm, "des") == 0)
4933089Swyllys 		*ktype = KMF_DES;
4943089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
4953089Swyllys 		*ktype = KMF_DES3;
4963812Shylee 	else if (strcasecmp(algm, "generic") == 0)
4973812Shylee 		*ktype = KMF_GENERIC_SECRET;
4983089Swyllys 	else
4993089Swyllys 		return (-1);
5003089Swyllys 
5013089Swyllys 	return (0);
5023089Swyllys }
5033089Swyllys 
5043089Swyllys int
5053089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
5063089Swyllys {
5073089Swyllys 	int num;
5083089Swyllys 	char timetok[6];
5093089Swyllys 
5103089Swyllys 	if (ltimestr == NULL || !strlen(ltimestr)) {
5113089Swyllys 		/* default to 1 year lifetime */
5123089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
5133089Swyllys 		return (0);
5143089Swyllys 	}
5153089Swyllys 
5163089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
5173089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
5183089Swyllys 		return (-1);
5193089Swyllys 
5203089Swyllys 	if (!strcasecmp(timetok, "day") ||
5213089Swyllys 	    !strcasecmp(timetok, "days")) {
5223089Swyllys 		*ltime = num * SECSPERDAY;
5233089Swyllys 	} else if (!strcasecmp(timetok, "hour") ||
524*5051Swyllys 	    !strcasecmp(timetok, "hours")) {
5253089Swyllys 		*ltime = num * SECSPERHOUR;
5263089Swyllys 	} else if (!strcasecmp(timetok, "year") ||
527*5051Swyllys 	    !strcasecmp(timetok, "years")) {
5283089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
5293089Swyllys 	} else {
5303089Swyllys 		*ltime = 0;
5313089Swyllys 		return (-1);
5323089Swyllys 	}
5333089Swyllys 
5343089Swyllys 	return (0);
5353089Swyllys }
5363089Swyllys 
5373089Swyllys int
5383089Swyllys OT2Int(char *objclass)
5393089Swyllys {
5403089Swyllys 	char *c = NULL;
5413089Swyllys 	int retval = 0;
5423089Swyllys 
5433089Swyllys 	if (objclass == NULL)
5443089Swyllys 		return (-1);
5453089Swyllys 
5463089Swyllys 	c = strchr(objclass, ':');
5473089Swyllys 	if (c != NULL) {
5483089Swyllys 		if (!strcasecmp(c, ":private"))
5493089Swyllys 			retval = PK_PRIVATE_OBJ;
5503089Swyllys 		else if (!strcasecmp(c, ":public"))
5513089Swyllys 			retval = PK_PUBLIC_OBJ;
5523089Swyllys 		else if (!strcasecmp(c, ":both"))
5533089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
5543089Swyllys 		else /* unrecognized option */
5553089Swyllys 			return (-1);
5563089Swyllys 
5573089Swyllys 		*c = '\0';
5583089Swyllys 	}
5593089Swyllys 
5603089Swyllys 	if (!strcasecmp(objclass, "public")) {
5613089Swyllys 		if (retval)
5623089Swyllys 			return (-1);
563*5051Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
5643089Swyllys 	} else if (!strcasecmp(objclass, "private")) {
5653089Swyllys 		if (retval)
5663089Swyllys 			return (-1);
5673089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
5683089Swyllys 	} else if (!strcasecmp(objclass, "both")) {
5693089Swyllys 		if (retval)
5703089Swyllys 			return (-1);
5713089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
5723089Swyllys 	} else if (!strcasecmp(objclass, "cert")) {
5733089Swyllys 		return (retval | PK_CERT_OBJ);
5743089Swyllys 	} else if (!strcasecmp(objclass, "key")) {
5753089Swyllys 		if (retval == 0) /* return all keys */
5763089Swyllys 			return (retval | PK_KEY_OBJ);
5773089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
5783089Swyllys 			/* return all keys */
5793089Swyllys 			return (retval | PK_KEY_OBJ);
5803089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
5813089Swyllys 			/* Only return public keys */
5823089Swyllys 			return (retval | PK_PUBKEY_OBJ);
5833089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
5843089Swyllys 			/* Only return private keys */
5853089Swyllys 			return (retval | PK_PRIKEY_OBJ);
5863089Swyllys 	} else if (!strcasecmp(objclass, "crl")) {
5873089Swyllys 		if (retval)
5883089Swyllys 			return (-1);
5893089Swyllys 		return (retval | PK_CRL_OBJ);
5903089Swyllys 	}
5913089Swyllys 
5923089Swyllys 	if (retval == 0) /* No matches found */
5933089Swyllys 		retval = -1;
5943089Swyllys 	return (retval);
5953089Swyllys }
5963089Swyllys 
5973089Swyllys KMF_ENCODE_FORMAT
5983089Swyllys Str2Format(char *formstr)
5993089Swyllys {
6003089Swyllys 	if (formstr == NULL || !strcasecmp(formstr, "der"))
6013089Swyllys 		return (KMF_FORMAT_ASN1);
6023089Swyllys 	if (!strcasecmp(formstr, "pem"))
6033089Swyllys 		return (KMF_FORMAT_PEM);
6043089Swyllys 	if (!strcasecmp(formstr, "pkcs12"))
6053089Swyllys 		return (KMF_FORMAT_PKCS12);
606*5051Swyllys 	if (!strcasecmp(formstr, "raw"))
607*5051Swyllys 		return (KMF_FORMAT_RAWKEY);
6083089Swyllys 
6093089Swyllys 	return (KMF_FORMAT_UNDEF);
6103089Swyllys }
6113089Swyllys 
6123089Swyllys 
6133089Swyllys KMF_RETURN
6143089Swyllys select_token(void *kmfhandle, char *token,
6153089Swyllys 	int readonly)
6163089Swyllys {
617*5051Swyllys 	KMF_ATTRIBUTE attlist[10];
618*5051Swyllys 	int i = 0;
619*5051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
6203089Swyllys 	KMF_RETURN rv = KMF_OK;
6213089Swyllys 
6223089Swyllys 	if (token == NULL)
6233089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
6243089Swyllys 
625*5051Swyllys 	kmf_set_attr_at_index(attlist, i,
626*5051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
627*5051Swyllys 	    sizeof (kstype));
628*5051Swyllys 	i++;
6293089Swyllys 
630*5051Swyllys 	if (token) {
631*5051Swyllys 		kmf_set_attr_at_index(attlist, i,
632*5051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
633*5051Swyllys 		    strlen(token));
634*5051Swyllys 		i++;
635*5051Swyllys 	}
636*5051Swyllys 
637*5051Swyllys 	kmf_set_attr_at_index(attlist, i,
638*5051Swyllys 	    KMF_READONLY_ATTR, &readonly,
639*5051Swyllys 	    sizeof (readonly));
640*5051Swyllys 	i++;
641*5051Swyllys 
642*5051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6433089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
6443089Swyllys 		rv = KMF_OK;
6453089Swyllys 	return (rv);
6463089Swyllys }
6473089Swyllys 
6483089Swyllys 
6493089Swyllys KMF_RETURN
6503089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
6513089Swyllys {
652*5051Swyllys 
653*5051Swyllys 	KMF_ATTRIBUTE attlist[10];
654*5051Swyllys 	int i = 0;
655*5051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
6563089Swyllys 	KMF_RETURN rv = KMF_OK;
657*5051Swyllys 
658*5051Swyllys 	kmf_set_attr_at_index(attlist, i,
659*5051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
660*5051Swyllys 	    sizeof (kstype));
661*5051Swyllys 	i++;
6623089Swyllys 
663*5051Swyllys 	if (dir) {
664*5051Swyllys 		kmf_set_attr_at_index(attlist, i,
665*5051Swyllys 		    KMF_DIRPATH_ATTR, dir,
666*5051Swyllys 		    strlen(dir));
667*5051Swyllys 		i++;
668*5051Swyllys 	}
6693089Swyllys 
670*5051Swyllys 	if (prefix) {
671*5051Swyllys 		kmf_set_attr_at_index(attlist, i,
672*5051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
673*5051Swyllys 		    strlen(prefix));
674*5051Swyllys 		i++;
675*5051Swyllys 
676*5051Swyllys 		kmf_set_attr_at_index(attlist, i,
677*5051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
678*5051Swyllys 		    strlen(prefix));
679*5051Swyllys 		i++;
680*5051Swyllys 	}
681*5051Swyllys 
682*5051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6833089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
6843089Swyllys 		rv = KMF_OK;
6853089Swyllys 
6863089Swyllys 	return (rv);
6873089Swyllys }
6883089Swyllys 
6893089Swyllys 
6903089Swyllys KMF_RETURN
6913089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
6923089Swyllys {
6933089Swyllys 	KMF_RETURN rv = KMF_OK;
6943089Swyllys 	char prompt[1024];
6953089Swyllys 
6963089Swyllys 	/*
6973089Swyllys 	 * Get the password to use for the PK12 encryption.
6983089Swyllys 	 */
6993089Swyllys 	(void) strlcpy(prompt,
700*5051Swyllys 	    gettext("Enter password to use for "
701*5051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
7023089Swyllys 
7033089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
704*5051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
7053089Swyllys 		cred->cred = NULL;
7063089Swyllys 		cred->credlen = 0;
7073089Swyllys 	}
7083089Swyllys 
7093089Swyllys 	return (rv);
7103089Swyllys }
7113089Swyllys 
7123089Swyllys 
7133089Swyllys #define	COUNTRY_PROMPT	"Country Name (2 letter code) [US]:"
7143089Swyllys #define	STATE_PROMPT	"State or Province Name (full name) [Some-State]:"
7153089Swyllys #define	LOCALITY_PROMPT	"Locality Name (eg, city) []:"
7163089Swyllys #define	ORG_PROMPT	"Organization Name (eg, company) []:"
7173089Swyllys #define	UNIT_PROMPT	"Organizational Unit Name (eg, section) []:"
7183089Swyllys #define	NAME_PROMPT	"Common Name (eg, YOUR name) []:"
7193089Swyllys #define	EMAIL_PROMPT	"Email Address []:"
7203089Swyllys 
7213089Swyllys #define	COUNTRY_DEFAULT "US"
7223089Swyllys #define	STATE_DEFAULT	"Some-State"
7233089Swyllys #define	INVALID_INPUT 	"Invalid input; please re-enter ..."
7243089Swyllys 
7253089Swyllys #define	SUBNAMESIZ	1024
7263089Swyllys #define	RDN_MIN		1
7273089Swyllys #define	RDN_MAX		64
7283089Swyllys #define	COUNTRYNAME_MIN	2
7293089Swyllys #define	COUNTRYNAME_MAX	2
7303089Swyllys 
7313089Swyllys static char *
7323089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
7333089Swyllys {
7343089Swyllys 	char buf[1024];
7353089Swyllys 	char *response = NULL;
7363089Swyllys 	char *ret = NULL;
7373089Swyllys 	int len;
7383089Swyllys 
7393089Swyllys 	for (;;) {
7403089Swyllys 		(void) printf("\t%s", prompt);
7413089Swyllys 		(void) fflush(stdout);
7423089Swyllys 
7433089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
7443089Swyllys 		if (response == NULL) {
7453089Swyllys 			if (default_str != NULL) {
7463089Swyllys 				ret = strdup(default_str);
7473089Swyllys 			}
7483089Swyllys 			break;
7493089Swyllys 		}
7503089Swyllys 
7513089Swyllys 		/* Skip any leading white space. */
7523089Swyllys 		while (isspace(*response))
7533089Swyllys 			response++;
7543089Swyllys 		if (*response == '\0') {
7553089Swyllys 			if (default_str != NULL) {
7563089Swyllys 				ret = strdup(default_str);
7573089Swyllys 			}
7583089Swyllys 			break;
7593089Swyllys 		}
7603089Swyllys 
7613089Swyllys 		len = strlen(response);
7623089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
7633089Swyllys 		len--;
7643089Swyllys 		if (len >= min_len && len <= max_len) {
7653089Swyllys 			ret = strdup(response);
7663089Swyllys 			break;
7673089Swyllys 		}
7683089Swyllys 
7693089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
7703089Swyllys 
7713089Swyllys 	}
7723089Swyllys 
7733089Swyllys 	return (ret);
7743089Swyllys }
7753089Swyllys 
7763089Swyllys int
7773089Swyllys get_subname(char **result)
7783089Swyllys {
7793089Swyllys 	char *country = NULL;
7803089Swyllys 	char *state = NULL;
7813089Swyllys 	char *locality = NULL;
7823089Swyllys 	char *org = NULL;
7833089Swyllys 	char *unit = NULL;
7843089Swyllys 	char *name = NULL;
7853089Swyllys 	char *email = NULL;
7863089Swyllys 	char *subname = NULL;
7873089Swyllys 
7883089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
7893089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
7903089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
7913089Swyllys 	if (country == NULL)
7923089Swyllys 		return (-1);
7933089Swyllys 
7943089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
7953089Swyllys 	    RDN_MIN, RDN_MAX);
7963089Swyllys 	if (state == NULL) {
7973089Swyllys 		goto out;
7983089Swyllys 	}
7993089Swyllys 
8003089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
8013089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
8023089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
8033089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
8043089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
8053089Swyllys 
8063089Swyllys 	/* Now create a subject name from the input strings */
8073089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
8083089Swyllys 		goto out;
8093089Swyllys 
8103089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
8113089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
8123089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
8133089Swyllys 	(void) strlcat(subname, ", ", SUBNAMESIZ);
8143089Swyllys 	(void) strlcat(subname, "ST=", SUBNAMESIZ);
8153089Swyllys 	(void) strlcat(subname, state, SUBNAMESIZ);
8163089Swyllys 
8173089Swyllys 	if (locality) {
8183089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
8193089Swyllys 		(void) strlcat(subname, "L=", SUBNAMESIZ);
8203089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
8213089Swyllys 	}
8223089Swyllys 
8233089Swyllys 	if (org) {
8243089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
8253089Swyllys 		(void) strlcat(subname, "O=", SUBNAMESIZ);
8263089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
8273089Swyllys 	}
8283089Swyllys 
8293089Swyllys 	if (unit) {
8303089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
8313089Swyllys 		(void) strlcat(subname, "OU=", SUBNAMESIZ);
8323089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
8333089Swyllys 	}
8343089Swyllys 
8353089Swyllys 	if (name) {
8363089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
8373089Swyllys 		(void) strlcat(subname, "CN=", SUBNAMESIZ);
8383089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
8393089Swyllys 	}
8403089Swyllys 
8413089Swyllys 	if (email) {
8423089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
8433089Swyllys 		(void) strlcat(subname, "E=", SUBNAMESIZ);
8443089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
8453089Swyllys 	}
8463089Swyllys 
8473089Swyllys out:
8483089Swyllys 	if (country)
8493089Swyllys 		free(country);
8503089Swyllys 	if (state)
8513089Swyllys 		free(state);
8523089Swyllys 	if (locality)
8533089Swyllys 		free(locality);
8543089Swyllys 	if (org)
8553089Swyllys 		free(org);
8563089Swyllys 	if (unit)
8573089Swyllys 		free(unit);
8583089Swyllys 	if (name)
8593089Swyllys 		free(name);
8603089Swyllys 	if (email)
8613089Swyllys 		free(email);
8623089Swyllys 
8633089Swyllys 	if (subname == NULL)
8643089Swyllys 		return (-1);
8653089Swyllys 	else {
8663089Swyllys 		*result = subname;
8673089Swyllys 		return (0);
8683089Swyllys 	}
8693089Swyllys }
8703089Swyllys 
8713089Swyllys /*
8723089Swyllys  * Parse a string of KeyUsage values and convert
8733089Swyllys  * them to the correct KU Bits.
8743089Swyllys  * The field may be marked "critical" by prepending
8753089Swyllys  * "critical:" to the list.
8763089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
8773089Swyllys  */
8783089Swyllys KMF_RETURN
8793089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
8803089Swyllys {
8813089Swyllys 	KMF_RETURN ret = KMF_OK;
8823089Swyllys 	uint16_t kuval;
8833089Swyllys 	char *k;
8843089Swyllys 
8853089Swyllys 	*kubits = 0;
8863089Swyllys 	if (kustr == NULL || !strlen(kustr))
8873089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
8883089Swyllys 
8893089Swyllys 	/* Check to see if this is critical */
8903089Swyllys 	if (!strncasecmp(kustr, "critical:", strlen("critical:"))) {
8913089Swyllys 		*critical = TRUE;
8923089Swyllys 		kustr += strlen("critical:");
8933089Swyllys 	} else {
8943089Swyllys 		*critical = FALSE;
8953089Swyllys 	}
8963089Swyllys 
8973089Swyllys 	k = strtok(kustr, ",");
8983089Swyllys 	while (k != NULL) {
899*5051Swyllys 		kuval = kmf_string_to_ku(k);
9003089Swyllys 		if (kuval == 0) {
9013089Swyllys 			*kubits = 0;
9023089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
9033089Swyllys 		}
9043089Swyllys 		*kubits |= kuval;
9053089Swyllys 		k = strtok(NULL, ",");
9063089Swyllys 	}
9073089Swyllys 
9083089Swyllys 	return (ret);
9093089Swyllys }
9103089Swyllys 
9113089Swyllys /*
9123089Swyllys  * Verify the alternate subject label is real or invalid.
9133089Swyllys  *
9143089Swyllys  * The field may be marked "critical" by prepending
9153089Swyllys  * "critical:" to the list.
9163089Swyllys  * EX:  "critical:IP=1.2.3.4"
9173089Swyllys  */
9183089Swyllys KMF_RETURN
9193089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
9203089Swyllys {
9213089Swyllys 	char *p;
9223089Swyllys 	KMF_RETURN rv = KMF_OK;
9233089Swyllys 
9243089Swyllys 	/* Check to see if this is critical */
9253089Swyllys 	if (!strncasecmp(arg, "critical:", strlen("critical:"))) {
9263089Swyllys 		*critical = TRUE;
9273089Swyllys 		arg += strlen("critical:");
9283089Swyllys 	} else {
9293089Swyllys 		*critical = FALSE;
9303089Swyllys 	}
9313089Swyllys 
9323089Swyllys 	/* Make sure there is an "=" sign */
9333089Swyllys 	p = strchr(arg, '=');
9343089Swyllys 	if (p == NULL)
9353089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9363089Swyllys 
9373089Swyllys 	p[0] = '\0';
9383089Swyllys 
9393089Swyllys 	if (strcmp(arg, "IP") == 0)
9403089Swyllys 		*type = GENNAME_IPADDRESS;
9413089Swyllys 	else if (strcmp(arg, "DNS") == 0)
9423089Swyllys 		*type = GENNAME_DNSNAME;
9433089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
9443089Swyllys 		*type = GENNAME_RFC822NAME;
9453089Swyllys 	else if (strcmp(arg, "URI") == 0)
9463089Swyllys 		*type = GENNAME_URI;
9473089Swyllys 	else if (strcmp(arg, "DN") == 0)
9483089Swyllys 		*type = GENNAME_DIRECTORYNAME;
9493089Swyllys 	else if (strcmp(arg, "RID") == 0)
9503089Swyllys 		*type = GENNAME_REGISTEREDID;
9513089Swyllys 	else
9523089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
9533089Swyllys 
9543089Swyllys 	p[0] = '=';
9553089Swyllys 
9563089Swyllys 	return (rv);
9573089Swyllys }
9583089Swyllys 
9593089Swyllys int
9603089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
9613089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
9623089Swyllys {
9633089Swyllys 	char	prompt[1024];
9643089Swyllys 	char	*p = NULL;
9653089Swyllys 
9663089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
9673089Swyllys 		p = strchr(token_spec, ':');
9683089Swyllys 		if (p != NULL)
9693089Swyllys 		*p = 0;
9703089Swyllys 	}
9713089Swyllys 	/*
9723089Swyllys 	 * Login to the token first.
9733089Swyllys 	 */
9743089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
975*5051Swyllys 	    gettext(DEFAULT_TOKEN_PROMPT), token_spec);
9763089Swyllys 
9773089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
978*5051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
9793089Swyllys 		cred->cred = NULL;
9803089Swyllys 		cred->credlen = 0;
9813089Swyllys 	}
9823089Swyllys 
9833089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
9843089Swyllys 		*p = ':';
9853089Swyllys 	return (KMF_OK);
9863089Swyllys }
9873089Swyllys 
9883089Swyllys KMF_RETURN
9893089Swyllys verify_file(char *filename)
9903089Swyllys {
9913089Swyllys 	KMF_RETURN ret = KMF_OK;
9923089Swyllys 	int fd;
9933089Swyllys 
9943089Swyllys 	/*
9953089Swyllys 	 * Attempt to open with  the EXCL flag so that if
9963089Swyllys 	 * it already exists, the open will fail.  It will
9973089Swyllys 	 * also fail if the file cannot be created due to
9983089Swyllys 	 * permissions on the parent directory, or if the
9993089Swyllys 	 * parent directory itself does not exist.
10003089Swyllys 	 */
10013089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
10023089Swyllys 	if (fd == -1)
10033089Swyllys 		return (KMF_ERR_OPEN_FILE);
10043089Swyllys 
10053089Swyllys 	/* If we were able to create it, delete it. */
10063089Swyllys 	(void) close(fd);
10073089Swyllys 	(void) unlink(filename);
10083089Swyllys 
10093089Swyllys 	return (ret);
10103089Swyllys }
10113089Swyllys 
10123089Swyllys void
10133089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
10143089Swyllys {
10153089Swyllys 	KMF_RETURN rv1, rv2;
10163089Swyllys 	char *plugin_errmsg = NULL;
10173089Swyllys 	char *kmf_errmsg = NULL;
10183089Swyllys 
1019*5051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
1020*5051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
10213089Swyllys 
10223089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
10233089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
1024*5051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
1025*5051Swyllys 		    plugin_errmsg);
1026*5051Swyllys 		kmf_free_str(plugin_errmsg);
10273089Swyllys 	}
10283089Swyllys 
10293089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
1030*5051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
1031*5051Swyllys 		    kmf_errmsg);
1032*5051Swyllys 		kmf_free_str(kmf_errmsg);
10333089Swyllys 	}
10343089Swyllys 
10353089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
10363089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
10373089Swyllys 
10383089Swyllys }
1039