xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 3089:8ddeb2ace8aa)
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
5*3089Swyllys  * Common Development and Distribution License (the "License").
6*3089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3089Swyllys  * Copyright 2006 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>
40*3089Swyllys #include <sys/types.h>
41*3089Swyllys #include <sys/stat.h>
42*3089Swyllys #include <fcntl.h>
43*3089Swyllys #include <tzfile.h>
440Sstevel@tonic-gate #include <cryptoutil.h>
450Sstevel@tonic-gate #include <security/cryptoki.h>
46*3089Swyllys #include <kmfapi.h>
470Sstevel@tonic-gate 
48*3089Swyllys #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 
69*3089Swyllys static void close_sess(CK_SESSION_HANDLE);
70*3089Swyllys static void logout_token(CK_SESSION_HANDLE);
71*3089Swyllys 
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  */
122*3089Swyllys 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  */
144*3089Swyllys 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 
170*3089Swyllys 
171*3089Swyllys #ifdef DEBUG
172*3089Swyllys 	if (getenv("TOKENPIN") != NULL) {
173*3089Swyllys 		*pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN"));
174*3089Swyllys 		*pinlen = strlen((char *)(*pin));
175*3089Swyllys 		return (CKR_OK);
176*3089Swyllys 	}
177*3089Swyllys #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 
222*3089Swyllys 
223*3089Swyllys #ifdef DEBUG
224*3089Swyllys 	/* If debugging or testing, return TRUE and avoid prompting */
225*3089Swyllys 	if (getenv("TOKENPIN") != NULL) {
226*3089Swyllys 		return (B_TRUE);
227*3089Swyllys 	}
228*3089Swyllys #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)
25617Sdinak 		    (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) {
348*3089Swyllys 			if (opts_av != NULL)
349*3089Swyllys 				free(opts_av);
350864Sdinak 			opts_av = NULL;
351864Sdinak 			return (0);
352*3089Swyllys 		} else {
353864Sdinak 			opts_av = (av_opts *)temp;
354*3089Swyllys 		}
355864Sdinak 
356*3089Swyllys 		(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;
396*3089Swyllys 	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)
404864Sdinak 		    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++) {
411*3089Swyllys 		cur_option = argv[optind_av];
412*3089Swyllys 
413*3089Swyllys 		if (strcmp(cur_option, "--") == 0) {
414864Sdinak 			optind_av++;
415864Sdinak 			break;
416864Sdinak 		}
417864Sdinak 
418*3089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
419*3089Swyllys 			len = 1;
420*3089Swyllys 			cur_option++; /* remove "-" */
421*3089Swyllys 		} else {
422*3089Swyllys 			len = strcspn(cur_option, "=");
423*3089Swyllys 		}
424864Sdinak 
425*3089Swyllys 		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 */
434*3089Swyllys 			if (cur_option[len] == '=') {
435*3089Swyllys 				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 }
448*3089Swyllys 
449*3089Swyllys KMF_KEYSTORE_TYPE
450*3089Swyllys KS2Int(char *keystore_str)
451*3089Swyllys {
452*3089Swyllys 	if (keystore_str == NULL)
453*3089Swyllys 		return (0);
454*3089Swyllys 	if (!strcasecmp(keystore_str, "pkcs11"))
455*3089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
456*3089Swyllys 	else if (!strcasecmp(keystore_str, "nss"))
457*3089Swyllys 		return (KMF_KEYSTORE_NSS);
458*3089Swyllys 	else if (!strcasecmp(keystore_str, "file"))
459*3089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
460*3089Swyllys 	else
461*3089Swyllys 		return (0);
462*3089Swyllys }
463*3089Swyllys 
464*3089Swyllys 
465*3089Swyllys int
466*3089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
467*3089Swyllys {
468*3089Swyllys 	if (algm == NULL) {
469*3089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
470*3089Swyllys 		*ktype = KMF_RSA;
471*3089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
472*3089Swyllys 		*sigAlg = KMF_ALGID_SHA1WithDSA;
473*3089Swyllys 		*ktype = KMF_DSA;
474*3089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
475*3089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
476*3089Swyllys 		*ktype = KMF_RSA;
477*3089Swyllys 	} else {
478*3089Swyllys 		return (-1);
479*3089Swyllys 	}
480*3089Swyllys 	return (0);
481*3089Swyllys }
482*3089Swyllys 
483*3089Swyllys int
484*3089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
485*3089Swyllys {
486*3089Swyllys 	if (algm == NULL)
487*3089Swyllys 		*ktype = KMF_AES;
488*3089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
489*3089Swyllys 		*ktype = KMF_AES;
490*3089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
491*3089Swyllys 		*ktype = KMF_RC4;
492*3089Swyllys 	else if (strcasecmp(algm, "des") == 0)
493*3089Swyllys 		*ktype = KMF_DES;
494*3089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
495*3089Swyllys 		*ktype = KMF_DES3;
496*3089Swyllys 	else
497*3089Swyllys 		return (-1);
498*3089Swyllys 
499*3089Swyllys 	return (0);
500*3089Swyllys }
501*3089Swyllys 
502*3089Swyllys int
503*3089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
504*3089Swyllys {
505*3089Swyllys 	int num;
506*3089Swyllys 	char timetok[6];
507*3089Swyllys 
508*3089Swyllys 	if (ltimestr == NULL || !strlen(ltimestr)) {
509*3089Swyllys 		/* default to 1 year lifetime */
510*3089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
511*3089Swyllys 		return (0);
512*3089Swyllys 	}
513*3089Swyllys 
514*3089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
515*3089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
516*3089Swyllys 		return (-1);
517*3089Swyllys 
518*3089Swyllys 	if (!strcasecmp(timetok, "day") ||
519*3089Swyllys 	    !strcasecmp(timetok, "days")) {
520*3089Swyllys 		*ltime = num * SECSPERDAY;
521*3089Swyllys 	} else if (!strcasecmp(timetok, "hour") ||
522*3089Swyllys 		!strcasecmp(timetok, "hours")) {
523*3089Swyllys 		*ltime = num * SECSPERHOUR;
524*3089Swyllys 	} else if (!strcasecmp(timetok, "year") ||
525*3089Swyllys 		!strcasecmp(timetok, "years")) {
526*3089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
527*3089Swyllys 	} else {
528*3089Swyllys 		*ltime = 0;
529*3089Swyllys 		return (-1);
530*3089Swyllys 	}
531*3089Swyllys 
532*3089Swyllys 	return (0);
533*3089Swyllys }
534*3089Swyllys 
535*3089Swyllys int
536*3089Swyllys OT2Int(char *objclass)
537*3089Swyllys {
538*3089Swyllys 	char *c = NULL;
539*3089Swyllys 	int retval = 0;
540*3089Swyllys 
541*3089Swyllys 	if (objclass == NULL)
542*3089Swyllys 		return (-1);
543*3089Swyllys 
544*3089Swyllys 	c = strchr(objclass, ':');
545*3089Swyllys 	if (c != NULL) {
546*3089Swyllys 		if (!strcasecmp(c, ":private"))
547*3089Swyllys 			retval = PK_PRIVATE_OBJ;
548*3089Swyllys 		else if (!strcasecmp(c, ":public"))
549*3089Swyllys 			retval = PK_PUBLIC_OBJ;
550*3089Swyllys 		else if (!strcasecmp(c, ":both"))
551*3089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
552*3089Swyllys 		else /* unrecognized option */
553*3089Swyllys 			return (-1);
554*3089Swyllys 
555*3089Swyllys 		*c = '\0';
556*3089Swyllys 	}
557*3089Swyllys 
558*3089Swyllys 	if (!strcasecmp(objclass, "public")) {
559*3089Swyllys 		if (retval)
560*3089Swyllys 			return (-1);
561*3089Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ |
562*3089Swyllys 			PK_PUBKEY_OBJ);
563*3089Swyllys 	} else if (!strcasecmp(objclass, "private")) {
564*3089Swyllys 		if (retval)
565*3089Swyllys 			return (-1);
566*3089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
567*3089Swyllys 	} else if (!strcasecmp(objclass, "both")) {
568*3089Swyllys 		if (retval)
569*3089Swyllys 			return (-1);
570*3089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
571*3089Swyllys 	} else if (!strcasecmp(objclass, "cert")) {
572*3089Swyllys 		return (retval | PK_CERT_OBJ);
573*3089Swyllys 	} else if (!strcasecmp(objclass, "key")) {
574*3089Swyllys 		if (retval == 0) /* return all keys */
575*3089Swyllys 			return (retval | PK_KEY_OBJ);
576*3089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
577*3089Swyllys 			/* return all keys */
578*3089Swyllys 			return (retval | PK_KEY_OBJ);
579*3089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
580*3089Swyllys 			/* Only return public keys */
581*3089Swyllys 			return (retval | PK_PUBKEY_OBJ);
582*3089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
583*3089Swyllys 			/* Only return private keys */
584*3089Swyllys 			return (retval | PK_PRIKEY_OBJ);
585*3089Swyllys 	} else if (!strcasecmp(objclass, "crl")) {
586*3089Swyllys 		if (retval)
587*3089Swyllys 			return (-1);
588*3089Swyllys 		return (retval | PK_CRL_OBJ);
589*3089Swyllys 	}
590*3089Swyllys 
591*3089Swyllys 	if (retval == 0) /* No matches found */
592*3089Swyllys 		retval = -1;
593*3089Swyllys 	return (retval);
594*3089Swyllys }
595*3089Swyllys 
596*3089Swyllys KMF_ENCODE_FORMAT
597*3089Swyllys Str2Format(char *formstr)
598*3089Swyllys {
599*3089Swyllys 	if (formstr == NULL || !strcasecmp(formstr, "der"))
600*3089Swyllys 		return (KMF_FORMAT_ASN1);
601*3089Swyllys 	if (!strcasecmp(formstr, "pem"))
602*3089Swyllys 		return (KMF_FORMAT_PEM);
603*3089Swyllys 	if (!strcasecmp(formstr, "pkcs12"))
604*3089Swyllys 		return (KMF_FORMAT_PKCS12);
605*3089Swyllys 
606*3089Swyllys 	return (KMF_FORMAT_UNDEF);
607*3089Swyllys }
608*3089Swyllys 
609*3089Swyllys 
610*3089Swyllys KMF_RETURN
611*3089Swyllys select_token(void *kmfhandle, char *token,
612*3089Swyllys 	int readonly)
613*3089Swyllys {
614*3089Swyllys 	KMF_RETURN rv = KMF_OK;
615*3089Swyllys 	KMF_CONFIG_PARAMS  config;
616*3089Swyllys 
617*3089Swyllys 	if (token == NULL)
618*3089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
619*3089Swyllys 
620*3089Swyllys 	(void) memset(&config, 0, sizeof (config));
621*3089Swyllys 	config.kstype = KMF_KEYSTORE_PK11TOKEN;
622*3089Swyllys 	config.pkcs11config.label = token;
623*3089Swyllys 	config.pkcs11config.readonly = readonly;
624*3089Swyllys 
625*3089Swyllys 	rv = KMF_ConfigureKeystore(kmfhandle, &config);
626*3089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
627*3089Swyllys 		rv = KMF_OK;
628*3089Swyllys 	return (rv);
629*3089Swyllys }
630*3089Swyllys 
631*3089Swyllys 
632*3089Swyllys KMF_RETURN
633*3089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
634*3089Swyllys {
635*3089Swyllys 	KMF_RETURN rv = KMF_OK;
636*3089Swyllys 	KMF_CONFIG_PARAMS  config;
637*3089Swyllys 
638*3089Swyllys 	(void) memset(&config, 0, sizeof (config));
639*3089Swyllys 	config.kstype = KMF_KEYSTORE_NSS;
640*3089Swyllys 	config.nssconfig.configdir = dir;
641*3089Swyllys 	config.nssconfig.certPrefix = prefix;
642*3089Swyllys 	config.nssconfig.keyPrefix = prefix;
643*3089Swyllys 	config.nssconfig.secModName = NULL;
644*3089Swyllys 
645*3089Swyllys 	rv = KMF_ConfigureKeystore(kmfhandle, &config);
646*3089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
647*3089Swyllys 		rv = KMF_OK;
648*3089Swyllys 
649*3089Swyllys 	return (rv);
650*3089Swyllys }
651*3089Swyllys 
652*3089Swyllys 
653*3089Swyllys KMF_RETURN
654*3089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
655*3089Swyllys {
656*3089Swyllys 	KMF_RETURN rv = KMF_OK;
657*3089Swyllys 	char prompt[1024];
658*3089Swyllys 
659*3089Swyllys 	/*
660*3089Swyllys 	 * Get the password to use for the PK12 encryption.
661*3089Swyllys 	 */
662*3089Swyllys 	(void) strlcpy(prompt,
663*3089Swyllys 		gettext("Enter password to use for "
664*3089Swyllys 			"accessing the PKCS12 file: "),
665*3089Swyllys 		sizeof (prompt));
666*3089Swyllys 
667*3089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
668*3089Swyllys 		(ulong_t *)&cred->credlen) != CKR_OK) {
669*3089Swyllys 		cred->cred = NULL;
670*3089Swyllys 		cred->credlen = 0;
671*3089Swyllys 	}
672*3089Swyllys 
673*3089Swyllys 	return (rv);
674*3089Swyllys }
675*3089Swyllys 
676*3089Swyllys 
677*3089Swyllys #define	COUNTRY_PROMPT	"Country Name (2 letter code) [US]:"
678*3089Swyllys #define	STATE_PROMPT	"State or Province Name (full name) [Some-State]:"
679*3089Swyllys #define	LOCALITY_PROMPT	"Locality Name (eg, city) []:"
680*3089Swyllys #define	ORG_PROMPT	"Organization Name (eg, company) []:"
681*3089Swyllys #define	UNIT_PROMPT	"Organizational Unit Name (eg, section) []:"
682*3089Swyllys #define	NAME_PROMPT	"Common Name (eg, YOUR name) []:"
683*3089Swyllys #define	EMAIL_PROMPT	"Email Address []:"
684*3089Swyllys 
685*3089Swyllys #define	COUNTRY_DEFAULT "US"
686*3089Swyllys #define	STATE_DEFAULT	"Some-State"
687*3089Swyllys #define	INVALID_INPUT 	"Invalid input; please re-enter ..."
688*3089Swyllys 
689*3089Swyllys #define	SUBNAMESIZ	1024
690*3089Swyllys #define	RDN_MIN		1
691*3089Swyllys #define	RDN_MAX		64
692*3089Swyllys #define	COUNTRYNAME_MIN	2
693*3089Swyllys #define	COUNTRYNAME_MAX	2
694*3089Swyllys 
695*3089Swyllys static char *
696*3089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
697*3089Swyllys {
698*3089Swyllys 	char buf[1024];
699*3089Swyllys 	char *response = NULL;
700*3089Swyllys 	char *ret = NULL;
701*3089Swyllys 	int len;
702*3089Swyllys 
703*3089Swyllys 	for (;;) {
704*3089Swyllys 		(void) printf("\t%s", prompt);
705*3089Swyllys 		(void) fflush(stdout);
706*3089Swyllys 
707*3089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
708*3089Swyllys 		if (response == NULL) {
709*3089Swyllys 			if (default_str != NULL) {
710*3089Swyllys 				ret = strdup(default_str);
711*3089Swyllys 			}
712*3089Swyllys 			break;
713*3089Swyllys 		}
714*3089Swyllys 
715*3089Swyllys 		/* Skip any leading white space. */
716*3089Swyllys 		while (isspace(*response))
717*3089Swyllys 			response++;
718*3089Swyllys 		if (*response == '\0') {
719*3089Swyllys 			if (default_str != NULL) {
720*3089Swyllys 				ret = strdup(default_str);
721*3089Swyllys 			}
722*3089Swyllys 			break;
723*3089Swyllys 		}
724*3089Swyllys 
725*3089Swyllys 		len = strlen(response);
726*3089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
727*3089Swyllys 		len--;
728*3089Swyllys 		if (len >= min_len && len <= max_len) {
729*3089Swyllys 			ret = strdup(response);
730*3089Swyllys 			break;
731*3089Swyllys 		}
732*3089Swyllys 
733*3089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
734*3089Swyllys 
735*3089Swyllys 	}
736*3089Swyllys 
737*3089Swyllys 	return (ret);
738*3089Swyllys }
739*3089Swyllys 
740*3089Swyllys int
741*3089Swyllys get_subname(char **result)
742*3089Swyllys {
743*3089Swyllys 	char *country = NULL;
744*3089Swyllys 	char *state = NULL;
745*3089Swyllys 	char *locality = NULL;
746*3089Swyllys 	char *org = NULL;
747*3089Swyllys 	char *unit = NULL;
748*3089Swyllys 	char *name = NULL;
749*3089Swyllys 	char *email = NULL;
750*3089Swyllys 	char *subname = NULL;
751*3089Swyllys 
752*3089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
753*3089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
754*3089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
755*3089Swyllys 	if (country == NULL)
756*3089Swyllys 		return (-1);
757*3089Swyllys 
758*3089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
759*3089Swyllys 	    RDN_MIN, RDN_MAX);
760*3089Swyllys 	if (state == NULL) {
761*3089Swyllys 		goto out;
762*3089Swyllys 	}
763*3089Swyllys 
764*3089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
765*3089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
766*3089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
767*3089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
768*3089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
769*3089Swyllys 
770*3089Swyllys 	/* Now create a subject name from the input strings */
771*3089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
772*3089Swyllys 		goto out;
773*3089Swyllys 
774*3089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
775*3089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
776*3089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
777*3089Swyllys 	(void) strlcat(subname, ", ", SUBNAMESIZ);
778*3089Swyllys 	(void) strlcat(subname, "ST=", SUBNAMESIZ);
779*3089Swyllys 	(void) strlcat(subname, state, SUBNAMESIZ);
780*3089Swyllys 
781*3089Swyllys 	if (locality) {
782*3089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
783*3089Swyllys 		(void) strlcat(subname, "L=", SUBNAMESIZ);
784*3089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
785*3089Swyllys 	}
786*3089Swyllys 
787*3089Swyllys 	if (org) {
788*3089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
789*3089Swyllys 		(void) strlcat(subname, "O=", SUBNAMESIZ);
790*3089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
791*3089Swyllys 	}
792*3089Swyllys 
793*3089Swyllys 	if (unit) {
794*3089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
795*3089Swyllys 		(void) strlcat(subname, "OU=", SUBNAMESIZ);
796*3089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
797*3089Swyllys 	}
798*3089Swyllys 
799*3089Swyllys 	if (name) {
800*3089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
801*3089Swyllys 		(void) strlcat(subname, "CN=", SUBNAMESIZ);
802*3089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
803*3089Swyllys 	}
804*3089Swyllys 
805*3089Swyllys 	if (email) {
806*3089Swyllys 		(void) strlcat(subname, ", ", SUBNAMESIZ);
807*3089Swyllys 		(void) strlcat(subname, "E=", SUBNAMESIZ);
808*3089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
809*3089Swyllys 	}
810*3089Swyllys 
811*3089Swyllys out:
812*3089Swyllys 	if (country)
813*3089Swyllys 		free(country);
814*3089Swyllys 	if (state)
815*3089Swyllys 		free(state);
816*3089Swyllys 	if (locality)
817*3089Swyllys 		free(locality);
818*3089Swyllys 	if (org)
819*3089Swyllys 		free(org);
820*3089Swyllys 	if (unit)
821*3089Swyllys 		free(unit);
822*3089Swyllys 	if (name)
823*3089Swyllys 		free(name);
824*3089Swyllys 	if (email)
825*3089Swyllys 		free(email);
826*3089Swyllys 
827*3089Swyllys 	if (subname == NULL)
828*3089Swyllys 		return (-1);
829*3089Swyllys 	else {
830*3089Swyllys 		*result = subname;
831*3089Swyllys 		return (0);
832*3089Swyllys 	}
833*3089Swyllys }
834*3089Swyllys 
835*3089Swyllys /*
836*3089Swyllys  * Parse a string of KeyUsage values and convert
837*3089Swyllys  * them to the correct KU Bits.
838*3089Swyllys  * The field may be marked "critical" by prepending
839*3089Swyllys  * "critical:" to the list.
840*3089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
841*3089Swyllys  */
842*3089Swyllys KMF_RETURN
843*3089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
844*3089Swyllys {
845*3089Swyllys 	KMF_RETURN ret = KMF_OK;
846*3089Swyllys 	uint16_t kuval;
847*3089Swyllys 	char *k;
848*3089Swyllys 
849*3089Swyllys 	*kubits = 0;
850*3089Swyllys 	if (kustr == NULL || !strlen(kustr))
851*3089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
852*3089Swyllys 
853*3089Swyllys 	/* Check to see if this is critical */
854*3089Swyllys 	if (!strncasecmp(kustr, "critical:", strlen("critical:"))) {
855*3089Swyllys 		*critical = TRUE;
856*3089Swyllys 		kustr += strlen("critical:");
857*3089Swyllys 	} else {
858*3089Swyllys 		*critical = FALSE;
859*3089Swyllys 	}
860*3089Swyllys 
861*3089Swyllys 	k = strtok(kustr, ",");
862*3089Swyllys 	while (k != NULL) {
863*3089Swyllys 		kuval = KMF_StringToKeyUsage(k);
864*3089Swyllys 		if (kuval == 0) {
865*3089Swyllys 			*kubits = 0;
866*3089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
867*3089Swyllys 		}
868*3089Swyllys 		*kubits |= kuval;
869*3089Swyllys 		k = strtok(NULL, ",");
870*3089Swyllys 	}
871*3089Swyllys 
872*3089Swyllys 	return (ret);
873*3089Swyllys }
874*3089Swyllys 
875*3089Swyllys /*
876*3089Swyllys  * Verify the alternate subject label is real or invalid.
877*3089Swyllys  *
878*3089Swyllys  * The field may be marked "critical" by prepending
879*3089Swyllys  * "critical:" to the list.
880*3089Swyllys  * EX:  "critical:IP=1.2.3.4"
881*3089Swyllys  */
882*3089Swyllys KMF_RETURN
883*3089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
884*3089Swyllys {
885*3089Swyllys 	char *p;
886*3089Swyllys 	KMF_RETURN rv = KMF_OK;
887*3089Swyllys 
888*3089Swyllys 	/* Check to see if this is critical */
889*3089Swyllys 	if (!strncasecmp(arg, "critical:", strlen("critical:"))) {
890*3089Swyllys 		*critical = TRUE;
891*3089Swyllys 		arg += strlen("critical:");
892*3089Swyllys 	} else {
893*3089Swyllys 		*critical = FALSE;
894*3089Swyllys 	}
895*3089Swyllys 
896*3089Swyllys 	/* Make sure there is an "=" sign */
897*3089Swyllys 	p = strchr(arg, '=');
898*3089Swyllys 	if (p == NULL)
899*3089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
900*3089Swyllys 
901*3089Swyllys 	p[0] = '\0';
902*3089Swyllys 
903*3089Swyllys 	if (strcmp(arg, "IP") == 0)
904*3089Swyllys 		*type = GENNAME_IPADDRESS;
905*3089Swyllys 	else if (strcmp(arg, "DNS") == 0)
906*3089Swyllys 		*type = GENNAME_DNSNAME;
907*3089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
908*3089Swyllys 		*type = GENNAME_RFC822NAME;
909*3089Swyllys 	else if (strcmp(arg, "URI") == 0)
910*3089Swyllys 		*type = GENNAME_URI;
911*3089Swyllys 	else if (strcmp(arg, "DN") == 0)
912*3089Swyllys 		*type = GENNAME_DIRECTORYNAME;
913*3089Swyllys 	else if (strcmp(arg, "RID") == 0)
914*3089Swyllys 		*type = GENNAME_REGISTEREDID;
915*3089Swyllys 	else
916*3089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
917*3089Swyllys 
918*3089Swyllys 	p[0] = '=';
919*3089Swyllys 
920*3089Swyllys 	return (rv);
921*3089Swyllys }
922*3089Swyllys 
923*3089Swyllys int
924*3089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
925*3089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
926*3089Swyllys {
927*3089Swyllys 	char	prompt[1024];
928*3089Swyllys 	char	*p = NULL;
929*3089Swyllys 
930*3089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
931*3089Swyllys 		p = strchr(token_spec, ':');
932*3089Swyllys 		if (p != NULL)
933*3089Swyllys 		*p = 0;
934*3089Swyllys 	}
935*3089Swyllys 	/*
936*3089Swyllys 	 * Login to the token first.
937*3089Swyllys 	 */
938*3089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
939*3089Swyllys 		gettext(DEFAULT_TOKEN_PROMPT),
940*3089Swyllys 		token_spec);
941*3089Swyllys 
942*3089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
943*3089Swyllys 		(ulong_t *)&cred->credlen) != CKR_OK) {
944*3089Swyllys 		cred->cred = NULL;
945*3089Swyllys 		cred->credlen = 0;
946*3089Swyllys 	}
947*3089Swyllys 
948*3089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
949*3089Swyllys 		*p = ':';
950*3089Swyllys 	return (KMF_OK);
951*3089Swyllys }
952*3089Swyllys 
953*3089Swyllys KMF_RETURN
954*3089Swyllys verify_file(char *filename)
955*3089Swyllys {
956*3089Swyllys 	KMF_RETURN ret = KMF_OK;
957*3089Swyllys 	int fd;
958*3089Swyllys 
959*3089Swyllys 	/*
960*3089Swyllys 	 * Attempt to open with  the EXCL flag so that if
961*3089Swyllys 	 * it already exists, the open will fail.  It will
962*3089Swyllys 	 * also fail if the file cannot be created due to
963*3089Swyllys 	 * permissions on the parent directory, or if the
964*3089Swyllys 	 * parent directory itself does not exist.
965*3089Swyllys 	 */
966*3089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
967*3089Swyllys 	if (fd == -1)
968*3089Swyllys 		return (KMF_ERR_OPEN_FILE);
969*3089Swyllys 
970*3089Swyllys 	/* If we were able to create it, delete it. */
971*3089Swyllys 	(void) close(fd);
972*3089Swyllys 	(void) unlink(filename);
973*3089Swyllys 
974*3089Swyllys 	return (ret);
975*3089Swyllys }
976*3089Swyllys 
977*3089Swyllys void
978*3089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
979*3089Swyllys {
980*3089Swyllys 	KMF_RETURN rv1, rv2;
981*3089Swyllys 	char *plugin_errmsg = NULL;
982*3089Swyllys 	char *kmf_errmsg = NULL;
983*3089Swyllys 
984*3089Swyllys 	rv1 = KMF_GetPluginErrorString(handle, &plugin_errmsg);
985*3089Swyllys 	rv2 = KMF_GetKMFErrorString(errcode, &kmf_errmsg);
986*3089Swyllys 
987*3089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
988*3089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
989*3089Swyllys 		cryptoerror(LOG_STDERR,
990*3089Swyllys 			gettext("keystore error: %s"),
991*3089Swyllys 			plugin_errmsg);
992*3089Swyllys 		KMF_FreeString(plugin_errmsg);
993*3089Swyllys 	}
994*3089Swyllys 
995*3089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
996*3089Swyllys 		cryptoerror(LOG_STDERR,
997*3089Swyllys 			gettext("libkmf error: %s"),
998*3089Swyllys 			kmf_errmsg);
999*3089Swyllys 		KMF_FreeString(kmf_errmsg);
1000*3089Swyllys 	}
1001*3089Swyllys 
1002*3089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
1003*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
1004*3089Swyllys 
1005*3089Swyllys }
1006