xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 5221:98f4eb09776e)
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)
2565051Swyllys 			(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)
4045051Swyllys 			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") ||
5245051Swyllys 	    !strcasecmp(timetok, "hours")) {
5253089Swyllys 		*ltime = num * SECSPERHOUR;
5263089Swyllys 	} else if (!strcasecmp(timetok, "year") ||
5275051Swyllys 	    !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);
5635051Swyllys 		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);
6065051Swyllys 	if (!strcasecmp(formstr, "raw"))
6075051Swyllys 		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 {
6175051Swyllys 	KMF_ATTRIBUTE attlist[10];
6185051Swyllys 	int i = 0;
6195051Swyllys 	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 
6255051Swyllys 	kmf_set_attr_at_index(attlist, i,
6265051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6275051Swyllys 	    sizeof (kstype));
6285051Swyllys 	i++;
6293089Swyllys 
6305051Swyllys 	if (token) {
6315051Swyllys 		kmf_set_attr_at_index(attlist, i,
6325051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
6335051Swyllys 		    strlen(token));
6345051Swyllys 		i++;
6355051Swyllys 	}
6365051Swyllys 
6375051Swyllys 	kmf_set_attr_at_index(attlist, i,
6385051Swyllys 	    KMF_READONLY_ATTR, &readonly,
6395051Swyllys 	    sizeof (readonly));
6405051Swyllys 	i++;
6415051Swyllys 
6425051Swyllys 	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 {
6525051Swyllys 
6535051Swyllys 	KMF_ATTRIBUTE attlist[10];
6545051Swyllys 	int i = 0;
6555051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
6563089Swyllys 	KMF_RETURN rv = KMF_OK;
6575051Swyllys 
6585051Swyllys 	kmf_set_attr_at_index(attlist, i,
6595051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6605051Swyllys 	    sizeof (kstype));
6615051Swyllys 	i++;
6623089Swyllys 
6635051Swyllys 	if (dir) {
6645051Swyllys 		kmf_set_attr_at_index(attlist, i,
6655051Swyllys 		    KMF_DIRPATH_ATTR, dir,
6665051Swyllys 		    strlen(dir));
6675051Swyllys 		i++;
6685051Swyllys 	}
6693089Swyllys 
6705051Swyllys 	if (prefix) {
6715051Swyllys 		kmf_set_attr_at_index(attlist, i,
6725051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
6735051Swyllys 		    strlen(prefix));
6745051Swyllys 		i++;
6755051Swyllys 
6765051Swyllys 		kmf_set_attr_at_index(attlist, i,
6775051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
6785051Swyllys 		    strlen(prefix));
6795051Swyllys 		i++;
6805051Swyllys 	}
6815051Swyllys 
6825051Swyllys 	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,
7005051Swyllys 	    gettext("Enter password to use for "
7015051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
7023089Swyllys 
7033089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
7045051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
7053089Swyllys 		cred->cred = NULL;
7063089Swyllys 		cred->credlen = 0;
7073089Swyllys 	}
7083089Swyllys 
7093089Swyllys 	return (rv);
7103089Swyllys }
7113089Swyllys 
712*5221Swyllys #define	FILENAME_PROMPT gettext("Filename:")
713*5221Swyllys #define	FILENAME_MINLEN	1
714*5221Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
7153089Swyllys 
716*5221Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
717*5221Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
718*5221Swyllys 	"[Some-State]:")
719*5221Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
720*5221Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
721*5221Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
722*5221Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
723*5221Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
724*5221Swyllys 
725*5221Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
726*5221Swyllys 	"0x01020304):")
727*5221Swyllys #define	SERNO_MINLEN	3
728*5221Swyllys #define	SERNO_MAXLEN	42
729*5221Swyllys 
730*5221Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
731*5221Swyllys #define	LABEL_MINLEN	1
732*5221Swyllys #define	LABEL_MAXLEN	1024
7333089Swyllys 
7343089Swyllys #define	COUNTRY_DEFAULT "US"
735*5221Swyllys #define	STATE_DEFAULT	NULL
736*5221Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
7373089Swyllys 
7383089Swyllys #define	SUBNAMESIZ	1024
7393089Swyllys #define	RDN_MIN		1
7403089Swyllys #define	RDN_MAX		64
7413089Swyllys #define	COUNTRYNAME_MIN	2
7423089Swyllys #define	COUNTRYNAME_MAX	2
7433089Swyllys 
7443089Swyllys static char *
7453089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
7463089Swyllys {
7473089Swyllys 	char buf[1024];
7483089Swyllys 	char *response = NULL;
7493089Swyllys 	char *ret = NULL;
7503089Swyllys 	int len;
7513089Swyllys 
7523089Swyllys 	for (;;) {
7533089Swyllys 		(void) printf("\t%s", prompt);
7543089Swyllys 		(void) fflush(stdout);
7553089Swyllys 
7563089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
7573089Swyllys 		if (response == NULL) {
7583089Swyllys 			if (default_str != NULL) {
7593089Swyllys 				ret = strdup(default_str);
7603089Swyllys 			}
7613089Swyllys 			break;
7623089Swyllys 		}
7633089Swyllys 
7643089Swyllys 		/* Skip any leading white space. */
7653089Swyllys 		while (isspace(*response))
7663089Swyllys 			response++;
7673089Swyllys 		if (*response == '\0') {
7683089Swyllys 			if (default_str != NULL) {
7693089Swyllys 				ret = strdup(default_str);
7703089Swyllys 			}
7713089Swyllys 			break;
7723089Swyllys 		}
7733089Swyllys 
7743089Swyllys 		len = strlen(response);
7753089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
7763089Swyllys 		len--;
7773089Swyllys 		if (len >= min_len && len <= max_len) {
7783089Swyllys 			ret = strdup(response);
7793089Swyllys 			break;
7803089Swyllys 		}
7813089Swyllys 
7823089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
7833089Swyllys 
7843089Swyllys 	}
7853089Swyllys 
7863089Swyllys 	return (ret);
7873089Swyllys }
7883089Swyllys 
7893089Swyllys int
790*5221Swyllys get_filename(char *txt, char **result)
791*5221Swyllys {
792*5221Swyllys 	char prompt[1024];
793*5221Swyllys 	char *fname = NULL;
794*5221Swyllys 
795*5221Swyllys 	(void) snprintf(prompt, sizeof (prompt),
796*5221Swyllys 	    gettext("Enter filename for the %s: "),
797*5221Swyllys 	    txt);
798*5221Swyllys 	fname = get_input_string(prompt, NULL,
799*5221Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
800*5221Swyllys 	*result = fname;
801*5221Swyllys 	return (0);
802*5221Swyllys }
803*5221Swyllys 
804*5221Swyllys int
805*5221Swyllys get_certlabel(char **result)
806*5221Swyllys {
807*5221Swyllys 	char *label = NULL;
808*5221Swyllys 
809*5221Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
810*5221Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
811*5221Swyllys 	*result = label;
812*5221Swyllys 	return (0);
813*5221Swyllys }
814*5221Swyllys 
815*5221Swyllys int
816*5221Swyllys get_serial(char **result)
817*5221Swyllys {
818*5221Swyllys 	char *serial = NULL;
819*5221Swyllys 
820*5221Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
821*5221Swyllys 	    SERNO_MAXLEN);
822*5221Swyllys 
823*5221Swyllys 	*result = serial;
824*5221Swyllys 	return (0);
825*5221Swyllys }
826*5221Swyllys 
827*5221Swyllys int
8283089Swyllys get_subname(char **result)
8293089Swyllys {
8303089Swyllys 	char *country = NULL;
8313089Swyllys 	char *state = NULL;
8323089Swyllys 	char *locality = NULL;
8333089Swyllys 	char *org = NULL;
8343089Swyllys 	char *unit = NULL;
8353089Swyllys 	char *name = NULL;
8363089Swyllys 	char *email = NULL;
8373089Swyllys 	char *subname = NULL;
8383089Swyllys 
8393089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
8403089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
8413089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
8423089Swyllys 	if (country == NULL)
8433089Swyllys 		return (-1);
8443089Swyllys 
8453089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
8463089Swyllys 	    RDN_MIN, RDN_MAX);
8473089Swyllys 
8483089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
8493089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
8503089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
8513089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
8523089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
8533089Swyllys 
8543089Swyllys 	/* Now create a subject name from the input strings */
8553089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
8563089Swyllys 		goto out;
8573089Swyllys 
8583089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
8593089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
8603089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
861*5221Swyllys 	if (state != NULL) {
862*5221Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
863*5221Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
864*5221Swyllys 	}
8653089Swyllys 
866*5221Swyllys 	if (locality != NULL) {
867*5221Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
8683089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
8693089Swyllys 	}
8703089Swyllys 
871*5221Swyllys 	if (org != NULL) {
872*5221Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
8733089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
8743089Swyllys 	}
8753089Swyllys 
876*5221Swyllys 	if (unit != NULL) {
877*5221Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
8783089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
8793089Swyllys 	}
8803089Swyllys 
881*5221Swyllys 	if (name != NULL) {
882*5221Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
8833089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
8843089Swyllys 	}
8853089Swyllys 
886*5221Swyllys 	if (email != NULL) {
887*5221Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
8883089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
8893089Swyllys 	}
8903089Swyllys 
8913089Swyllys out:
8923089Swyllys 	if (country)
8933089Swyllys 		free(country);
8943089Swyllys 	if (state)
8953089Swyllys 		free(state);
8963089Swyllys 	if (locality)
8973089Swyllys 		free(locality);
8983089Swyllys 	if (org)
8993089Swyllys 		free(org);
9003089Swyllys 	if (unit)
9013089Swyllys 		free(unit);
9023089Swyllys 	if (name)
9033089Swyllys 		free(name);
9043089Swyllys 	if (email)
9053089Swyllys 		free(email);
9063089Swyllys 
9073089Swyllys 	if (subname == NULL)
9083089Swyllys 		return (-1);
9093089Swyllys 	else {
9103089Swyllys 		*result = subname;
9113089Swyllys 		return (0);
9123089Swyllys 	}
9133089Swyllys }
9143089Swyllys 
9153089Swyllys /*
9163089Swyllys  * Parse a string of KeyUsage values and convert
9173089Swyllys  * them to the correct KU Bits.
9183089Swyllys  * The field may be marked "critical" by prepending
9193089Swyllys  * "critical:" to the list.
9203089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
9213089Swyllys  */
9223089Swyllys KMF_RETURN
9233089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
9243089Swyllys {
9253089Swyllys 	KMF_RETURN ret = KMF_OK;
9263089Swyllys 	uint16_t kuval;
9273089Swyllys 	char *k;
9283089Swyllys 
9293089Swyllys 	*kubits = 0;
9303089Swyllys 	if (kustr == NULL || !strlen(kustr))
9313089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9323089Swyllys 
9333089Swyllys 	/* Check to see if this is critical */
9343089Swyllys 	if (!strncasecmp(kustr, "critical:", strlen("critical:"))) {
9353089Swyllys 		*critical = TRUE;
9363089Swyllys 		kustr += strlen("critical:");
9373089Swyllys 	} else {
9383089Swyllys 		*critical = FALSE;
9393089Swyllys 	}
9403089Swyllys 
9413089Swyllys 	k = strtok(kustr, ",");
9423089Swyllys 	while (k != NULL) {
9435051Swyllys 		kuval = kmf_string_to_ku(k);
9443089Swyllys 		if (kuval == 0) {
9453089Swyllys 			*kubits = 0;
9463089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
9473089Swyllys 		}
9483089Swyllys 		*kubits |= kuval;
9493089Swyllys 		k = strtok(NULL, ",");
9503089Swyllys 	}
9513089Swyllys 
9523089Swyllys 	return (ret);
9533089Swyllys }
9543089Swyllys 
9553089Swyllys /*
9563089Swyllys  * Verify the alternate subject label is real or invalid.
9573089Swyllys  *
9583089Swyllys  * The field may be marked "critical" by prepending
9593089Swyllys  * "critical:" to the list.
9603089Swyllys  * EX:  "critical:IP=1.2.3.4"
9613089Swyllys  */
9623089Swyllys KMF_RETURN
9633089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
9643089Swyllys {
9653089Swyllys 	char *p;
9663089Swyllys 	KMF_RETURN rv = KMF_OK;
9673089Swyllys 
9683089Swyllys 	/* Check to see if this is critical */
9693089Swyllys 	if (!strncasecmp(arg, "critical:", strlen("critical:"))) {
9703089Swyllys 		*critical = TRUE;
9713089Swyllys 		arg += strlen("critical:");
9723089Swyllys 	} else {
9733089Swyllys 		*critical = FALSE;
9743089Swyllys 	}
9753089Swyllys 
9763089Swyllys 	/* Make sure there is an "=" sign */
9773089Swyllys 	p = strchr(arg, '=');
9783089Swyllys 	if (p == NULL)
9793089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9803089Swyllys 
9813089Swyllys 	p[0] = '\0';
9823089Swyllys 
9833089Swyllys 	if (strcmp(arg, "IP") == 0)
9843089Swyllys 		*type = GENNAME_IPADDRESS;
9853089Swyllys 	else if (strcmp(arg, "DNS") == 0)
9863089Swyllys 		*type = GENNAME_DNSNAME;
9873089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
9883089Swyllys 		*type = GENNAME_RFC822NAME;
9893089Swyllys 	else if (strcmp(arg, "URI") == 0)
9903089Swyllys 		*type = GENNAME_URI;
9913089Swyllys 	else if (strcmp(arg, "DN") == 0)
9923089Swyllys 		*type = GENNAME_DIRECTORYNAME;
9933089Swyllys 	else if (strcmp(arg, "RID") == 0)
9943089Swyllys 		*type = GENNAME_REGISTEREDID;
9953089Swyllys 	else
9963089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
9973089Swyllys 
9983089Swyllys 	p[0] = '=';
9993089Swyllys 
10003089Swyllys 	return (rv);
10013089Swyllys }
10023089Swyllys 
10033089Swyllys int
10043089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
10053089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
10063089Swyllys {
10073089Swyllys 	char	prompt[1024];
10083089Swyllys 	char	*p = NULL;
10093089Swyllys 
10103089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
10113089Swyllys 		p = strchr(token_spec, ':');
10123089Swyllys 		if (p != NULL)
10133089Swyllys 		*p = 0;
10143089Swyllys 	}
10153089Swyllys 	/*
10163089Swyllys 	 * Login to the token first.
10173089Swyllys 	 */
10183089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
10195051Swyllys 	    gettext(DEFAULT_TOKEN_PROMPT), token_spec);
10203089Swyllys 
10213089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
10225051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
10233089Swyllys 		cred->cred = NULL;
10243089Swyllys 		cred->credlen = 0;
10253089Swyllys 	}
10263089Swyllys 
10273089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
10283089Swyllys 		*p = ':';
10293089Swyllys 	return (KMF_OK);
10303089Swyllys }
10313089Swyllys 
10323089Swyllys KMF_RETURN
10333089Swyllys verify_file(char *filename)
10343089Swyllys {
10353089Swyllys 	KMF_RETURN ret = KMF_OK;
10363089Swyllys 	int fd;
10373089Swyllys 
10383089Swyllys 	/*
10393089Swyllys 	 * Attempt to open with  the EXCL flag so that if
10403089Swyllys 	 * it already exists, the open will fail.  It will
10413089Swyllys 	 * also fail if the file cannot be created due to
10423089Swyllys 	 * permissions on the parent directory, or if the
10433089Swyllys 	 * parent directory itself does not exist.
10443089Swyllys 	 */
10453089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
10463089Swyllys 	if (fd == -1)
10473089Swyllys 		return (KMF_ERR_OPEN_FILE);
10483089Swyllys 
10493089Swyllys 	/* If we were able to create it, delete it. */
10503089Swyllys 	(void) close(fd);
10513089Swyllys 	(void) unlink(filename);
10523089Swyllys 
10533089Swyllys 	return (ret);
10543089Swyllys }
10553089Swyllys 
10563089Swyllys void
10573089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
10583089Swyllys {
10593089Swyllys 	KMF_RETURN rv1, rv2;
10603089Swyllys 	char *plugin_errmsg = NULL;
10613089Swyllys 	char *kmf_errmsg = NULL;
10623089Swyllys 
10635051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
10645051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
10653089Swyllys 
10663089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
10673089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
10685051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
10695051Swyllys 		    plugin_errmsg);
10705051Swyllys 		kmf_free_str(plugin_errmsg);
10713089Swyllys 	}
10723089Swyllys 
10733089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
10745051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
10755051Swyllys 		    kmf_errmsg);
10765051Swyllys 		kmf_free_str(kmf_errmsg);
10773089Swyllys 	}
10783089Swyllys 
10793089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
10803089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
10813089Swyllys 
10823089Swyllys }
1083