xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 6051:7b29d160facb)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*6051Swyllys  * Copyright 2008 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 {
168*6051Swyllys 	char *save_phrase, *phrase1, *phrase2;
1690Sstevel@tonic-gate 
17017Sdinak 	/* Prompt user for a PIN. */
17117Sdinak 	if (prompt1 == NULL) {
17217Sdinak 		return (CKR_ARGUMENTS_BAD);
17317Sdinak 	}
17417Sdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
17517Sdinak 		return (CKR_FUNCTION_FAILED);
17617Sdinak 	}
17717Sdinak 
17817Sdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
17917Sdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
18017Sdinak 		return (CKR_HOST_MEMORY);
18117Sdinak 
18217Sdinak 	/* If second prompt given, PIN confirmation is requested. */
18317Sdinak 	if (prompt2 != NULL) {
18417Sdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
18517Sdinak 			free(save_phrase);
18617Sdinak 			return (CKR_FUNCTION_FAILED);
18717Sdinak 		}
18817Sdinak 		if (strcmp(save_phrase, phrase2) != 0) {
18917Sdinak 			free(save_phrase);
19017Sdinak 			return (CKR_PIN_INCORRECT);
19117Sdinak 		}
1920Sstevel@tonic-gate 	}
1930Sstevel@tonic-gate 
19417Sdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
19517Sdinak 	*pinlen = strlen(save_phrase);
19617Sdinak 	return (CKR_OK);
19717Sdinak }
19817Sdinak 
199*6051Swyllys int
200*6051Swyllys yn_to_int(char *ynstr)
201*6051Swyllys {
202*6051Swyllys 	char *y = gettext("yes");
203*6051Swyllys 	char *n = gettext("no");
204*6051Swyllys 	if (ynstr == NULL)
205*6051Swyllys 		return (-1);
206*6051Swyllys 
207*6051Swyllys 	if (strncasecmp(ynstr, y, 1) == 0)
208*6051Swyllys 		return (1);
209*6051Swyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
210*6051Swyllys 		return (0);
211*6051Swyllys 	else
212*6051Swyllys 		return (-1);
213*6051Swyllys }
214*6051Swyllys 
21517Sdinak /*
21617Sdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
21717Sdinak  * default prompt is used.  If not message for invalid input is supplied,
21817Sdinak  * a default will not be provided.  If the user provides no response,
21917Sdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
22017Sdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
22117Sdinak  */
22217Sdinak boolean_t
22317Sdinak yesno(char *prompt, char *invalid, boolean_t dflt)
22417Sdinak {
225*6051Swyllys 	char	*response, buf[1024];
226*6051Swyllys 	int	ans;
22717Sdinak 
22817Sdinak 	if (prompt == NULL)
22917Sdinak 		prompt = gettext("Enter (y)es or (n)o? ");
23017Sdinak 
23117Sdinak 	for (;;) {
23217Sdinak 		/* Prompt user. */
23317Sdinak 		(void) printf("%s", prompt);
23417Sdinak 		(void) fflush(stdout);
23517Sdinak 
23617Sdinak 		/* Get the response. */
23717Sdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
23817Sdinak 			break;		/* go to default response */
23917Sdinak 
24017Sdinak 		/* Skip any leading white space. */
24117Sdinak 		while (isspace(*response))
24217Sdinak 			response++;
24317Sdinak 		if (*response == '\0')
24417Sdinak 			break;		/* go to default response */
24517Sdinak 
246*6051Swyllys 		ans = yn_to_int(response);
247*6051Swyllys 		if (ans == 1)
24817Sdinak 			return (B_TRUE);
249*6051Swyllys 		else if (ans == 0)
25017Sdinak 			return (B_FALSE);
25117Sdinak 
25217Sdinak 		/* Indicate invalid input, and try again. */
25317Sdinak 		if (invalid != NULL)
2545051Swyllys 			(void) printf("%s", invalid);
25517Sdinak 	}
25617Sdinak 	return (dflt);
25717Sdinak }
25817Sdinak 
25917Sdinak /*
26017Sdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
26117Sdinak  * the size of the slot list buffer until the call is successful or an
26217Sdinak  * irrecoverable error occurs.
26317Sdinak  */
26417Sdinak CK_RV
26517Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
26617Sdinak {
26717Sdinak 	CK_ULONG	tmp_count = 0;
26817Sdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
26917Sdinak 	int		rv = CKR_OK;
27017Sdinak 
27117Sdinak 	if (!initialized)
27217Sdinak 		if ((rv = init_pk11()) != CKR_OK)
27317Sdinak 			return (rv);
27417Sdinak 
27517Sdinak 	/*
27617Sdinak 	 * Get the slot count first because we don't know how many
27717Sdinak 	 * slots there are and how many of those slots even have tokens.
27817Sdinak 	 * Don't specify an arbitrary buffer size for the slot list;
27917Sdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
28017Sdinak 	 * Also select only those slots that have tokens in them,
28117Sdinak 	 * because this tool has no need to know about empty slots.
28217Sdinak 	 */
28317Sdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
28417Sdinak 		return (rv);
28517Sdinak 
28617Sdinak 	if (tmp_count == 0) {
28717Sdinak 		*slot_list = NULL_PTR;
28817Sdinak 		*slot_count = 0;
28917Sdinak 		return (CKR_OK);
29017Sdinak 	}
29117Sdinak 
29217Sdinak 	/* Allocate initial space for the slot list. */
29317Sdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
29417Sdinak 	    sizeof (CK_SLOT_ID))) == NULL)
29517Sdinak 		return (CKR_HOST_MEMORY);
29617Sdinak 
29717Sdinak 	/* Then get the slot list itself. */
29817Sdinak 	for (;;) {
29917Sdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
30017Sdinak 			*slot_list = tmp_list;
30117Sdinak 			*slot_count = tmp_count;
30217Sdinak 			break;
30317Sdinak 		}
30417Sdinak 
30517Sdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
30617Sdinak 			free(tmp_list);
30717Sdinak 			break;
30817Sdinak 		}
30917Sdinak 
31017Sdinak 		/* If the number of slots grew, try again. */
31117Sdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
31217Sdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
31317Sdinak 			free(tmp_list);
31417Sdinak 			rv = CKR_HOST_MEMORY;
31517Sdinak 			break;
31617Sdinak 		}
31717Sdinak 		tmp_list = tmp2_list;
31817Sdinak 	}
31917Sdinak 
32017Sdinak 	return (rv);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate /*
324864Sdinak  * Breaks out the getopt-style option string into a structure that can be
325864Sdinak  * traversed later for calls to getopt_av().  Option string is NOT altered,
326864Sdinak  * but the struct fields point to locations within option string.
327864Sdinak  */
328864Sdinak static int
329864Sdinak populate_opts(char *optstring)
330864Sdinak {
331864Sdinak 	int		i;
332864Sdinak 	av_opts		*temp;
333864Sdinak 	char		*marker;
334864Sdinak 
335864Sdinak 	if (optstring == NULL || *optstring == '\0')
336864Sdinak 		return (0);
337864Sdinak 
338864Sdinak 	/*
339864Sdinak 	 * This tries to imitate getopt(3c) Each option must conform to:
340864Sdinak 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
341864Sdinak 	 * If long name is missing, the short name is used for long name.
342864Sdinak 	 */
343864Sdinak 	for (i = 0; *optstring != '\0'; i++) {
344864Sdinak 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
345864Sdinak 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
3463089Swyllys 			if (opts_av != NULL)
3473089Swyllys 				free(opts_av);
348864Sdinak 			opts_av = NULL;
349864Sdinak 			return (0);
3503089Swyllys 		} else {
351864Sdinak 			opts_av = (av_opts *)temp;
3523089Swyllys 		}
353864Sdinak 
3543089Swyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
355864Sdinak 		marker = optstring;		/* may need optstring later */
356864Sdinak 
357864Sdinak 		opts_av[i].shortnm = *marker++;	/* set short name */
358864Sdinak 
359864Sdinak 		if (*marker == ':') {		/* check for opt arg */
360864Sdinak 			marker++;
361864Sdinak 			opts_av[i].has_arg = B_TRUE;
362864Sdinak 		}
363864Sdinak 
364864Sdinak 		if (*marker == '(') {		/* check and set long name */
365864Sdinak 			marker++;
366864Sdinak 			opts_av[i].longnm = marker;
367864Sdinak 			opts_av[i].longnm_len = strcspn(marker, ")");
368864Sdinak 			optstring = marker + opts_av[i].longnm_len + 1;
369864Sdinak 		} else {
370864Sdinak 			/* use short name option character */
371864Sdinak 			opts_av[i].longnm = optstring;
372864Sdinak 			opts_av[i].longnm_len = 1;
373864Sdinak 			optstring = marker;
374864Sdinak 		}
375864Sdinak 	}
376864Sdinak 
377864Sdinak 	return (i);
378864Sdinak }
379864Sdinak 
380864Sdinak /*
381864Sdinak  * getopt_av() is very similar to getopt(3c) in that the takes an option
382864Sdinak  * string, compares command line arguments for matches, and returns a single
383864Sdinak  * letter option when a match is found.  However, getopt_av() differs from
384864Sdinak  * getopt(3c) by requiring that only longname options and values be found
385864Sdinak  * on the command line and all leading dashes are omitted.  In other words,
386864Sdinak  * it tries to enforce only longname "option=value" arguments on the command
387864Sdinak  * line.  Boolean options are not allowed either.
388864Sdinak  */
389864Sdinak int
390864Sdinak getopt_av(int argc, char * const *argv, const char *optstring)
391864Sdinak {
392864Sdinak 	int	i;
393864Sdinak 	int	len;
3943089Swyllys 	char   *cur_option;
395864Sdinak 
396864Sdinak 	if (optind_av >= argc)
397864Sdinak 		return (EOF);
398864Sdinak 
399864Sdinak 	/* First time or when optstring changes from previous one */
400864Sdinak 	if (_save_optstr != optstring) {
401864Sdinak 		if (opts_av != NULL)
4025051Swyllys 			free(opts_av);
403864Sdinak 		opts_av = NULL;
404864Sdinak 		_save_optstr = optstring;
405864Sdinak 		_save_numopts = populate_opts((char *)optstring);
406864Sdinak 	}
407864Sdinak 
408864Sdinak 	for (i = 0; i < _save_numopts; i++) {
4093089Swyllys 		cur_option = argv[optind_av];
4103089Swyllys 
4113089Swyllys 		if (strcmp(cur_option, "--") == 0) {
412864Sdinak 			optind_av++;
413864Sdinak 			break;
414864Sdinak 		}
415864Sdinak 
4163089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
4173089Swyllys 			len = 1;
4183089Swyllys 			cur_option++; /* remove "-" */
4193089Swyllys 		} else {
4203089Swyllys 			len = strcspn(cur_option, "=");
4213089Swyllys 		}
422864Sdinak 
4233089Swyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
424864Sdinak 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
425864Sdinak 			/* matched */
426864Sdinak 			if (!opts_av[i].has_arg) {
427864Sdinak 				optind_av++;
428864Sdinak 				return (opts_av[i].shortnm);
429864Sdinak 			}
430864Sdinak 
431864Sdinak 			/* needs optarg */
4323089Swyllys 			if (cur_option[len] == '=') {
4333089Swyllys 				optarg_av = &(cur_option[len+1]);
434864Sdinak 				optind_av++;
435864Sdinak 				return (opts_av[i].shortnm);
436864Sdinak 			}
437864Sdinak 
438864Sdinak 			optarg_av = NULL;
439864Sdinak 			optind_av++;
440864Sdinak 			return ((int)'?');
441864Sdinak 		}
442864Sdinak 	}
443864Sdinak 
444864Sdinak 	return (EOF);
445864Sdinak }
4463089Swyllys 
4473089Swyllys KMF_KEYSTORE_TYPE
4483089Swyllys KS2Int(char *keystore_str)
4493089Swyllys {
4503089Swyllys 	if (keystore_str == NULL)
4513089Swyllys 		return (0);
452*6051Swyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
4533089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
454*6051Swyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
4553089Swyllys 		return (KMF_KEYSTORE_NSS);
456*6051Swyllys 	else if (strcasecmp(keystore_str, "file") == 0)
4573089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
4583089Swyllys 	else
4593089Swyllys 		return (0);
4603089Swyllys }
4613089Swyllys 
4623089Swyllys 
4633089Swyllys int
4643089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
4653089Swyllys {
4663089Swyllys 	if (algm == NULL) {
4673089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4683089Swyllys 		*ktype = KMF_RSA;
4693089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
4703089Swyllys 		*sigAlg = KMF_ALGID_SHA1WithDSA;
4713089Swyllys 		*ktype = KMF_DSA;
4723089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
4733089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4743089Swyllys 		*ktype = KMF_RSA;
4753089Swyllys 	} else {
4763089Swyllys 		return (-1);
4773089Swyllys 	}
4783089Swyllys 	return (0);
4793089Swyllys }
4803089Swyllys 
4813089Swyllys int
4823089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
4833089Swyllys {
4843089Swyllys 	if (algm == NULL)
4853089Swyllys 		*ktype = KMF_AES;
4863089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
4873089Swyllys 		*ktype = KMF_AES;
4883089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
4893089Swyllys 		*ktype = KMF_RC4;
4903089Swyllys 	else if (strcasecmp(algm, "des") == 0)
4913089Swyllys 		*ktype = KMF_DES;
4923089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
4933089Swyllys 		*ktype = KMF_DES3;
4943812Shylee 	else if (strcasecmp(algm, "generic") == 0)
4953812Shylee 		*ktype = KMF_GENERIC_SECRET;
4963089Swyllys 	else
4973089Swyllys 		return (-1);
4983089Swyllys 
4993089Swyllys 	return (0);
5003089Swyllys }
5013089Swyllys 
5023089Swyllys int
5033089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
5043089Swyllys {
5053089Swyllys 	int num;
5063089Swyllys 	char timetok[6];
5073089Swyllys 
508*6051Swyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
5093089Swyllys 		/* default to 1 year lifetime */
5103089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
5113089Swyllys 		return (0);
5123089Swyllys 	}
5133089Swyllys 
5143089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
5153089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
5163089Swyllys 		return (-1);
5173089Swyllys 
518*6051Swyllys 	if (strcasecmp(timetok, "day") == 0||
519*6051Swyllys 	    strcasecmp(timetok, "days") == 0) {
5203089Swyllys 		*ltime = num * SECSPERDAY;
521*6051Swyllys 	} else if (strcasecmp(timetok, "hour") == 0||
522*6051Swyllys 	    strcasecmp(timetok, "hours") == 0) {
5233089Swyllys 		*ltime = num * SECSPERHOUR;
524*6051Swyllys 	} else if (strcasecmp(timetok, "year") == 0 ||
525*6051Swyllys 	    strcasecmp(timetok, "years") == 0) {
5263089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
5273089Swyllys 	} else {
5283089Swyllys 		*ltime = 0;
5293089Swyllys 		return (-1);
5303089Swyllys 	}
5313089Swyllys 
5323089Swyllys 	return (0);
5333089Swyllys }
5343089Swyllys 
5353089Swyllys int
5363089Swyllys OT2Int(char *objclass)
5373089Swyllys {
5383089Swyllys 	char *c = NULL;
5393089Swyllys 	int retval = 0;
5403089Swyllys 
5413089Swyllys 	if (objclass == NULL)
5423089Swyllys 		return (-1);
5433089Swyllys 
5443089Swyllys 	c = strchr(objclass, ':');
5453089Swyllys 	if (c != NULL) {
546*6051Swyllys 		if (strcasecmp(c, ":private") == 0)
5473089Swyllys 			retval = PK_PRIVATE_OBJ;
548*6051Swyllys 		else if (strcasecmp(c, ":public") == 0)
5493089Swyllys 			retval = PK_PUBLIC_OBJ;
550*6051Swyllys 		else if (strcasecmp(c, ":both") == 0)
5513089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
5523089Swyllys 		else /* unrecognized option */
5533089Swyllys 			return (-1);
5543089Swyllys 
5553089Swyllys 		*c = '\0';
5563089Swyllys 	}
5573089Swyllys 
558*6051Swyllys 	if (strcasecmp(objclass, "public") == 0) {
5593089Swyllys 		if (retval)
5603089Swyllys 			return (-1);
5615051Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
562*6051Swyllys 	} else if (strcasecmp(objclass, "private") == 0) {
5633089Swyllys 		if (retval)
5643089Swyllys 			return (-1);
5653089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
566*6051Swyllys 	} else if (strcasecmp(objclass, "both") == 0) {
5673089Swyllys 		if (retval)
5683089Swyllys 			return (-1);
5693089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
570*6051Swyllys 	} else if (strcasecmp(objclass, "cert") == 0) {
5713089Swyllys 		return (retval | PK_CERT_OBJ);
572*6051Swyllys 	} else if (strcasecmp(objclass, "key") == 0) {
5733089Swyllys 		if (retval == 0) /* return all keys */
5743089Swyllys 			return (retval | PK_KEY_OBJ);
5753089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
5763089Swyllys 			/* return all keys */
5773089Swyllys 			return (retval | PK_KEY_OBJ);
5783089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
5793089Swyllys 			/* Only return public keys */
5803089Swyllys 			return (retval | PK_PUBKEY_OBJ);
5813089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
5823089Swyllys 			/* Only return private keys */
5833089Swyllys 			return (retval | PK_PRIKEY_OBJ);
584*6051Swyllys 	} else if (strcasecmp(objclass, "crl") == 0) {
5853089Swyllys 		if (retval)
5863089Swyllys 			return (-1);
5873089Swyllys 		return (retval | PK_CRL_OBJ);
5883089Swyllys 	}
5893089Swyllys 
5903089Swyllys 	if (retval == 0) /* No matches found */
5913089Swyllys 		retval = -1;
5923089Swyllys 	return (retval);
5933089Swyllys }
5943089Swyllys 
5953089Swyllys KMF_ENCODE_FORMAT
5963089Swyllys Str2Format(char *formstr)
5973089Swyllys {
598*6051Swyllys 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
5993089Swyllys 		return (KMF_FORMAT_ASN1);
600*6051Swyllys 	if (strcasecmp(formstr, "pem") == 0)
6013089Swyllys 		return (KMF_FORMAT_PEM);
602*6051Swyllys 	if (strcasecmp(formstr, "pkcs12") == 0)
6033089Swyllys 		return (KMF_FORMAT_PKCS12);
604*6051Swyllys 	if (strcasecmp(formstr, "raw") == 0)
6055051Swyllys 		return (KMF_FORMAT_RAWKEY);
6063089Swyllys 
6073089Swyllys 	return (KMF_FORMAT_UNDEF);
6083089Swyllys }
6093089Swyllys 
6103089Swyllys KMF_RETURN
611*6051Swyllys select_token(void *kmfhandle, char *token, int readonly)
6123089Swyllys {
6135051Swyllys 	KMF_ATTRIBUTE attlist[10];
6145051Swyllys 	int i = 0;
6155051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
6163089Swyllys 	KMF_RETURN rv = KMF_OK;
6173089Swyllys 
6183089Swyllys 	if (token == NULL)
6193089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
6203089Swyllys 
6215051Swyllys 	kmf_set_attr_at_index(attlist, i,
6225051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6235051Swyllys 	    sizeof (kstype));
6245051Swyllys 	i++;
6253089Swyllys 
6265051Swyllys 	if (token) {
6275051Swyllys 		kmf_set_attr_at_index(attlist, i,
6285051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
6295051Swyllys 		    strlen(token));
6305051Swyllys 		i++;
6315051Swyllys 	}
6325051Swyllys 
6335051Swyllys 	kmf_set_attr_at_index(attlist, i,
6345051Swyllys 	    KMF_READONLY_ATTR, &readonly,
6355051Swyllys 	    sizeof (readonly));
6365051Swyllys 	i++;
6375051Swyllys 
6385051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6393089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
6403089Swyllys 		rv = KMF_OK;
6413089Swyllys 	return (rv);
6423089Swyllys }
6433089Swyllys 
6443089Swyllys KMF_RETURN
6453089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
6463089Swyllys {
6475051Swyllys 	KMF_ATTRIBUTE attlist[10];
6485051Swyllys 	int i = 0;
6495051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
6503089Swyllys 	KMF_RETURN rv = KMF_OK;
6515051Swyllys 
6525051Swyllys 	kmf_set_attr_at_index(attlist, i,
6535051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6545051Swyllys 	    sizeof (kstype));
6555051Swyllys 	i++;
6563089Swyllys 
6575051Swyllys 	if (dir) {
6585051Swyllys 		kmf_set_attr_at_index(attlist, i,
6595051Swyllys 		    KMF_DIRPATH_ATTR, dir,
6605051Swyllys 		    strlen(dir));
6615051Swyllys 		i++;
6625051Swyllys 	}
6633089Swyllys 
6645051Swyllys 	if (prefix) {
6655051Swyllys 		kmf_set_attr_at_index(attlist, i,
6665051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
6675051Swyllys 		    strlen(prefix));
6685051Swyllys 		i++;
6695051Swyllys 
6705051Swyllys 		kmf_set_attr_at_index(attlist, i,
6715051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
6725051Swyllys 		    strlen(prefix));
6735051Swyllys 		i++;
6745051Swyllys 	}
6755051Swyllys 
6765051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6773089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
6783089Swyllys 		rv = KMF_OK;
6793089Swyllys 
6803089Swyllys 	return (rv);
6813089Swyllys }
6823089Swyllys 
6833089Swyllys KMF_RETURN
6843089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
6853089Swyllys {
6863089Swyllys 	KMF_RETURN rv = KMF_OK;
6873089Swyllys 	char prompt[1024];
6883089Swyllys 
6893089Swyllys 	/*
6903089Swyllys 	 * Get the password to use for the PK12 encryption.
6913089Swyllys 	 */
6923089Swyllys 	(void) strlcpy(prompt,
6935051Swyllys 	    gettext("Enter password to use for "
6945051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
6953089Swyllys 
6963089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
6975051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
6983089Swyllys 		cred->cred = NULL;
6993089Swyllys 		cred->credlen = 0;
7003089Swyllys 	}
7013089Swyllys 
7023089Swyllys 	return (rv);
7033089Swyllys }
7043089Swyllys 
7055221Swyllys #define	FILENAME_PROMPT gettext("Filename:")
7065221Swyllys #define	FILENAME_MINLEN	1
7075221Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
7083089Swyllys 
7095221Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
7105221Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
7115221Swyllys 	"[Some-State]:")
7125221Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
7135221Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
7145221Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
7155221Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
7165221Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
7175221Swyllys 
7185221Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
7195221Swyllys 	"0x01020304):")
7205221Swyllys #define	SERNO_MINLEN	3
7215221Swyllys #define	SERNO_MAXLEN	42
7225221Swyllys 
7235221Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
7245221Swyllys #define	LABEL_MINLEN	1
7255221Swyllys #define	LABEL_MAXLEN	1024
7263089Swyllys 
7273089Swyllys #define	COUNTRY_DEFAULT "US"
7285221Swyllys #define	STATE_DEFAULT	NULL
7295221Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
7303089Swyllys 
7313089Swyllys #define	SUBNAMESIZ	1024
7323089Swyllys #define	RDN_MIN		1
7333089Swyllys #define	RDN_MAX		64
7343089Swyllys #define	COUNTRYNAME_MIN	2
7353089Swyllys #define	COUNTRYNAME_MAX	2
7363089Swyllys 
7373089Swyllys static char *
7383089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
7393089Swyllys {
7403089Swyllys 	char buf[1024];
7413089Swyllys 	char *response = NULL;
7423089Swyllys 	char *ret = NULL;
7433089Swyllys 	int len;
7443089Swyllys 
7453089Swyllys 	for (;;) {
7463089Swyllys 		(void) printf("\t%s", prompt);
7473089Swyllys 		(void) fflush(stdout);
7483089Swyllys 
7493089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
7503089Swyllys 		if (response == NULL) {
7513089Swyllys 			if (default_str != NULL) {
7523089Swyllys 				ret = strdup(default_str);
7533089Swyllys 			}
7543089Swyllys 			break;
7553089Swyllys 		}
7563089Swyllys 
7573089Swyllys 		/* Skip any leading white space. */
7583089Swyllys 		while (isspace(*response))
7593089Swyllys 			response++;
7603089Swyllys 		if (*response == '\0') {
7613089Swyllys 			if (default_str != NULL) {
7623089Swyllys 				ret = strdup(default_str);
7633089Swyllys 			}
7643089Swyllys 			break;
7653089Swyllys 		}
7663089Swyllys 
7673089Swyllys 		len = strlen(response);
7683089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
7693089Swyllys 		len--;
7703089Swyllys 		if (len >= min_len && len <= max_len) {
7713089Swyllys 			ret = strdup(response);
7723089Swyllys 			break;
7733089Swyllys 		}
7743089Swyllys 
7753089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
7763089Swyllys 
7773089Swyllys 	}
7783089Swyllys 
7793089Swyllys 	return (ret);
7803089Swyllys }
7813089Swyllys 
7823089Swyllys int
7835221Swyllys get_filename(char *txt, char **result)
7845221Swyllys {
7855221Swyllys 	char prompt[1024];
7865221Swyllys 	char *fname = NULL;
7875221Swyllys 
7885221Swyllys 	(void) snprintf(prompt, sizeof (prompt),
7895221Swyllys 	    gettext("Enter filename for the %s: "),
7905221Swyllys 	    txt);
7915221Swyllys 	fname = get_input_string(prompt, NULL,
7925221Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
7935221Swyllys 	*result = fname;
7945221Swyllys 	return (0);
7955221Swyllys }
7965221Swyllys 
7975221Swyllys int
7985221Swyllys get_certlabel(char **result)
7995221Swyllys {
8005221Swyllys 	char *label = NULL;
8015221Swyllys 
8025221Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
8035221Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
8045221Swyllys 	*result = label;
8055221Swyllys 	return (0);
8065221Swyllys }
8075221Swyllys 
8085221Swyllys int
8095221Swyllys get_serial(char **result)
8105221Swyllys {
8115221Swyllys 	char *serial = NULL;
8125221Swyllys 
8135221Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
8145221Swyllys 	    SERNO_MAXLEN);
8155221Swyllys 
8165221Swyllys 	*result = serial;
8175221Swyllys 	return (0);
8185221Swyllys }
8195221Swyllys 
8205221Swyllys int
8213089Swyllys get_subname(char **result)
8223089Swyllys {
8233089Swyllys 	char *country = NULL;
8243089Swyllys 	char *state = NULL;
8253089Swyllys 	char *locality = NULL;
8263089Swyllys 	char *org = NULL;
8273089Swyllys 	char *unit = NULL;
8283089Swyllys 	char *name = NULL;
8293089Swyllys 	char *email = NULL;
8303089Swyllys 	char *subname = NULL;
8313089Swyllys 
8323089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
8333089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
8343089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
8353089Swyllys 	if (country == NULL)
8363089Swyllys 		return (-1);
8373089Swyllys 
8383089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
8393089Swyllys 	    RDN_MIN, RDN_MAX);
8403089Swyllys 
8413089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
8423089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
8433089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
8443089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
8453089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
8463089Swyllys 
8473089Swyllys 	/* Now create a subject name from the input strings */
8483089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
8493089Swyllys 		goto out;
8503089Swyllys 
8513089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
8523089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
8533089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
8545221Swyllys 	if (state != NULL) {
8555221Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
8565221Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
8575221Swyllys 	}
8583089Swyllys 
8595221Swyllys 	if (locality != NULL) {
8605221Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
8613089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
8623089Swyllys 	}
8633089Swyllys 
8645221Swyllys 	if (org != NULL) {
8655221Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
8663089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
8673089Swyllys 	}
8683089Swyllys 
8695221Swyllys 	if (unit != NULL) {
8705221Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
8713089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
8723089Swyllys 	}
8733089Swyllys 
8745221Swyllys 	if (name != NULL) {
8755221Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
8763089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
8773089Swyllys 	}
8783089Swyllys 
8795221Swyllys 	if (email != NULL) {
8805221Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
8813089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
8823089Swyllys 	}
8833089Swyllys 
8843089Swyllys out:
8853089Swyllys 	if (country)
8863089Swyllys 		free(country);
8873089Swyllys 	if (state)
8883089Swyllys 		free(state);
8893089Swyllys 	if (locality)
8903089Swyllys 		free(locality);
8913089Swyllys 	if (org)
8923089Swyllys 		free(org);
8933089Swyllys 	if (unit)
8943089Swyllys 		free(unit);
8953089Swyllys 	if (name)
8963089Swyllys 		free(name);
8973089Swyllys 	if (email)
8983089Swyllys 		free(email);
8993089Swyllys 
9003089Swyllys 	if (subname == NULL)
9013089Swyllys 		return (-1);
9023089Swyllys 	else {
9033089Swyllys 		*result = subname;
9043089Swyllys 		return (0);
9053089Swyllys 	}
9063089Swyllys }
9073089Swyllys 
9083089Swyllys /*
9093089Swyllys  * Parse a string of KeyUsage values and convert
9103089Swyllys  * them to the correct KU Bits.
9113089Swyllys  * The field may be marked "critical" by prepending
9123089Swyllys  * "critical:" to the list.
9133089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
9143089Swyllys  */
9153089Swyllys KMF_RETURN
9163089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
9173089Swyllys {
9183089Swyllys 	KMF_RETURN ret = KMF_OK;
9193089Swyllys 	uint16_t kuval;
9203089Swyllys 	char *k;
9213089Swyllys 
9223089Swyllys 	*kubits = 0;
923*6051Swyllys 	if (kustr == NULL || strlen(kustr) == 0)
9243089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9253089Swyllys 
9263089Swyllys 	/* Check to see if this is critical */
927*6051Swyllys 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
9283089Swyllys 		*critical = TRUE;
9293089Swyllys 		kustr += strlen("critical:");
9303089Swyllys 	} else {
9313089Swyllys 		*critical = FALSE;
9323089Swyllys 	}
9333089Swyllys 
9343089Swyllys 	k = strtok(kustr, ",");
9353089Swyllys 	while (k != NULL) {
9365051Swyllys 		kuval = kmf_string_to_ku(k);
9373089Swyllys 		if (kuval == 0) {
9383089Swyllys 			*kubits = 0;
9393089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
9403089Swyllys 		}
9413089Swyllys 		*kubits |= kuval;
9423089Swyllys 		k = strtok(NULL, ",");
9433089Swyllys 	}
9443089Swyllys 
9453089Swyllys 	return (ret);
9463089Swyllys }
9473089Swyllys 
9483089Swyllys /*
9493089Swyllys  * Verify the alternate subject label is real or invalid.
9503089Swyllys  *
9513089Swyllys  * The field may be marked "critical" by prepending
9523089Swyllys  * "critical:" to the list.
9533089Swyllys  * EX:  "critical:IP=1.2.3.4"
9543089Swyllys  */
9553089Swyllys KMF_RETURN
9563089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
9573089Swyllys {
9583089Swyllys 	char *p;
9593089Swyllys 	KMF_RETURN rv = KMF_OK;
9603089Swyllys 
9613089Swyllys 	/* Check to see if this is critical */
962*6051Swyllys 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
9633089Swyllys 		*critical = TRUE;
9643089Swyllys 		arg += strlen("critical:");
9653089Swyllys 	} else {
9663089Swyllys 		*critical = FALSE;
9673089Swyllys 	}
9683089Swyllys 
9693089Swyllys 	/* Make sure there is an "=" sign */
9703089Swyllys 	p = strchr(arg, '=');
9713089Swyllys 	if (p == NULL)
9723089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9733089Swyllys 
9743089Swyllys 	p[0] = '\0';
9753089Swyllys 
9763089Swyllys 	if (strcmp(arg, "IP") == 0)
9773089Swyllys 		*type = GENNAME_IPADDRESS;
9783089Swyllys 	else if (strcmp(arg, "DNS") == 0)
9793089Swyllys 		*type = GENNAME_DNSNAME;
9803089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
9813089Swyllys 		*type = GENNAME_RFC822NAME;
9823089Swyllys 	else if (strcmp(arg, "URI") == 0)
9833089Swyllys 		*type = GENNAME_URI;
9843089Swyllys 	else if (strcmp(arg, "DN") == 0)
9853089Swyllys 		*type = GENNAME_DIRECTORYNAME;
9863089Swyllys 	else if (strcmp(arg, "RID") == 0)
9873089Swyllys 		*type = GENNAME_REGISTEREDID;
988*6051Swyllys 	else if (strcmp(arg, "KRB") == 0)
989*6051Swyllys 		*type = GENNAME_KRB5PRINC;
990*6051Swyllys 	else if (strcmp(arg, "UPN") == 0)
991*6051Swyllys 		*type = GENNAME_SCLOGON_UPN;
9923089Swyllys 	else
9933089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
9943089Swyllys 
9953089Swyllys 	p[0] = '=';
9963089Swyllys 
9973089Swyllys 	return (rv);
9983089Swyllys }
9993089Swyllys 
10003089Swyllys int
10013089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
10023089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
10033089Swyllys {
10043089Swyllys 	char	prompt[1024];
10053089Swyllys 	char	*p = NULL;
10063089Swyllys 
10073089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
10083089Swyllys 		p = strchr(token_spec, ':');
10093089Swyllys 		if (p != NULL)
10103089Swyllys 		*p = 0;
10113089Swyllys 	}
10123089Swyllys 	/*
10133089Swyllys 	 * Login to the token first.
10143089Swyllys 	 */
10153089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
10165051Swyllys 	    gettext(DEFAULT_TOKEN_PROMPT), token_spec);
10173089Swyllys 
10183089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
10195051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
10203089Swyllys 		cred->cred = NULL;
10213089Swyllys 		cred->credlen = 0;
10223089Swyllys 	}
10233089Swyllys 
10243089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
10253089Swyllys 		*p = ':';
10263089Swyllys 	return (KMF_OK);
10273089Swyllys }
10283089Swyllys 
10293089Swyllys KMF_RETURN
10303089Swyllys verify_file(char *filename)
10313089Swyllys {
10323089Swyllys 	KMF_RETURN ret = KMF_OK;
10333089Swyllys 	int fd;
10343089Swyllys 
10353089Swyllys 	/*
10363089Swyllys 	 * Attempt to open with  the EXCL flag so that if
10373089Swyllys 	 * it already exists, the open will fail.  It will
10383089Swyllys 	 * also fail if the file cannot be created due to
10393089Swyllys 	 * permissions on the parent directory, or if the
10403089Swyllys 	 * parent directory itself does not exist.
10413089Swyllys 	 */
10423089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
10433089Swyllys 	if (fd == -1)
10443089Swyllys 		return (KMF_ERR_OPEN_FILE);
10453089Swyllys 
10463089Swyllys 	/* If we were able to create it, delete it. */
10473089Swyllys 	(void) close(fd);
10483089Swyllys 	(void) unlink(filename);
10493089Swyllys 
10503089Swyllys 	return (ret);
10513089Swyllys }
10523089Swyllys 
10533089Swyllys void
10543089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
10553089Swyllys {
10563089Swyllys 	KMF_RETURN rv1, rv2;
10573089Swyllys 	char *plugin_errmsg = NULL;
10583089Swyllys 	char *kmf_errmsg = NULL;
10593089Swyllys 
10605051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
10615051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
10623089Swyllys 
10633089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
10643089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
10655051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
10665051Swyllys 		    plugin_errmsg);
10675051Swyllys 		kmf_free_str(plugin_errmsg);
10683089Swyllys 	}
10693089Swyllys 
10703089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
10715051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
10725051Swyllys 		    kmf_errmsg);
10735051Swyllys 		kmf_free_str(kmf_errmsg);
10743089Swyllys 	}
10753089Swyllys 
10763089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
10773089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
10783089Swyllys 
10793089Swyllys }
1080*6051Swyllys 
1081*6051Swyllys static KMF_RETURN
1082*6051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
1083*6051Swyllys {
1084*6051Swyllys 	if (newoid != NULL && ekus != NULL) {
1085*6051Swyllys 		ekus->eku_count++;
1086*6051Swyllys 
1087*6051Swyllys 		ekus->critlist = realloc(ekus->critlist,
1088*6051Swyllys 		    ekus->eku_count * sizeof (int));
1089*6051Swyllys 		if (ekus->critlist != NULL)
1090*6051Swyllys 			ekus->critlist[ekus->eku_count-1] = critical;
1091*6051Swyllys 		else
1092*6051Swyllys 			return (KMF_ERR_MEMORY);
1093*6051Swyllys 
1094*6051Swyllys 		ekus->ekulist = realloc(
1095*6051Swyllys 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
1096*6051Swyllys 		if (ekus->ekulist != NULL)
1097*6051Swyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
1098*6051Swyllys 		else
1099*6051Swyllys 			return (KMF_ERR_MEMORY);
1100*6051Swyllys 	}
1101*6051Swyllys 	return (KMF_OK);
1102*6051Swyllys }
1103*6051Swyllys 
1104*6051Swyllys void
1105*6051Swyllys free_eku_list(EKU_LIST *ekus)
1106*6051Swyllys {
1107*6051Swyllys 	if (ekus != NULL && ekus->eku_count > 0) {
1108*6051Swyllys 		int i;
1109*6051Swyllys 		for (i = 0; i < ekus->eku_count; i++) {
1110*6051Swyllys 			kmf_free_data(&ekus->ekulist[i]);
1111*6051Swyllys 		}
1112*6051Swyllys 		free(ekus->ekulist);
1113*6051Swyllys 		free(ekus->critlist);
1114*6051Swyllys 	}
1115*6051Swyllys }
1116*6051Swyllys 
1117*6051Swyllys static KMF_RETURN
1118*6051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
1119*6051Swyllys {
1120*6051Swyllys 	KMF_RETURN rv = KMF_OK;
1121*6051Swyllys 	KMF_OID *newoid;
1122*6051Swyllys 	int critical;
1123*6051Swyllys 
1124*6051Swyllys 	if (strncasecmp(ekustr, "critical:",
1125*6051Swyllys 	    strlen("critical:")) == 0) {
1126*6051Swyllys 		critical = TRUE;
1127*6051Swyllys 		ekustr += strlen("critical:");
1128*6051Swyllys 	} else {
1129*6051Swyllys 		critical = FALSE;
1130*6051Swyllys 	}
1131*6051Swyllys 	newoid = kmf_ekuname_to_oid(ekustr);
1132*6051Swyllys 	if (newoid != NULL) {
1133*6051Swyllys 		rv = addToEKUList(ekus, critical, newoid);
1134*6051Swyllys 		free(newoid);
1135*6051Swyllys 	} else {
1136*6051Swyllys 		rv = PK_ERR_USAGE;
1137*6051Swyllys 	}
1138*6051Swyllys 
1139*6051Swyllys 	return (rv);
1140*6051Swyllys }
1141*6051Swyllys 
1142*6051Swyllys KMF_RETURN
1143*6051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
1144*6051Swyllys {
1145*6051Swyllys 	KMF_RETURN rv = KMF_OK;
1146*6051Swyllys 	char *p;
1147*6051Swyllys 	EKU_LIST *ekus = NULL;
1148*6051Swyllys 
1149*6051Swyllys 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
1150*6051Swyllys 		return (0);
1151*6051Swyllys 
1152*6051Swyllys 	/*
1153*6051Swyllys 	 * The list should be comma separated list of EKU Names.
1154*6051Swyllys 	 */
1155*6051Swyllys 	p = strtok(ekuliststr, ",");
1156*6051Swyllys 
1157*6051Swyllys 	/* If no tokens found, then maybe it's just a single EKU value */
1158*6051Swyllys 	if (p == NULL) {
1159*6051Swyllys 		rv = parse_ekus(ekuliststr, ekus);
1160*6051Swyllys 	}
1161*6051Swyllys 
1162*6051Swyllys 	while (p != NULL) {
1163*6051Swyllys 		rv = parse_ekus(p, ekus);
1164*6051Swyllys 
1165*6051Swyllys 		if (rv != KMF_OK)
1166*6051Swyllys 			break;
1167*6051Swyllys 		p = strtok(NULL, ",");
1168*6051Swyllys 	}
1169*6051Swyllys 
1170*6051Swyllys 	if (rv != KMF_OK)
1171*6051Swyllys 		free_eku_list(ekus);
1172*6051Swyllys 	else
1173*6051Swyllys 		*ekulist = ekus;
1174*6051Swyllys 
1175*6051Swyllys 	return (rv);
1176*6051Swyllys }
1177