xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision 9126:6acea8ac53c8)
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*9126SWyllys.Ingersoll@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains the functions that are shared among
280Sstevel@tonic-gate  * the various services this tool will ultimately provide.
2917Sdinak  * The functions in this file return PKCS#11 CK_RV errors.
3017Sdinak  * Only one session and one login per token is supported
3117Sdinak  * at this time.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <ctype.h>
383089Swyllys #include <sys/types.h>
393089Swyllys #include <sys/stat.h>
403089Swyllys #include <fcntl.h>
413089Swyllys #include <tzfile.h>
420Sstevel@tonic-gate #include <cryptoutil.h>
430Sstevel@tonic-gate #include <security/cryptoki.h>
443089Swyllys #include <kmfapi.h>
450Sstevel@tonic-gate 
463089Swyllys #include "common.h"
4717Sdinak 
4817Sdinak /* Local status variables. */
4917Sdinak static boolean_t	initialized = B_FALSE;
5017Sdinak static boolean_t	session_opened = B_FALSE;
5117Sdinak static boolean_t	logged_in = B_FALSE;
5217Sdinak 
53864Sdinak /* Supporting structures and global variables for getopt_av(). */
54864Sdinak typedef struct	av_opts_s {
55864Sdinak 	int		shortnm;	/* short name character */
56864Sdinak 	char		*longnm;	/* long name string, NOT terminated */
57864Sdinak 	int		longnm_len;	/* length of long name string */
58864Sdinak 	boolean_t	has_arg;	/* takes optional argument */
59864Sdinak } av_opts;
60864Sdinak static av_opts		*opts_av = NULL;
61864Sdinak static const char	*_save_optstr = NULL;
62864Sdinak static int		_save_numopts = 0;
63864Sdinak 
64864Sdinak int			optind_av = 1;
65864Sdinak char			*optarg_av = NULL;
66864Sdinak 
673089Swyllys static void close_sess(CK_SESSION_HANDLE);
683089Swyllys static void logout_token(CK_SESSION_HANDLE);
693089Swyllys 
7017Sdinak /*
7117Sdinak  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
7217Sdinak  * along with setting/resetting state variables.
7317Sdinak  */
746669Swyllys static CK_RV
756669Swyllys init_pkcs11(void)
7617Sdinak {
7717Sdinak 	CK_RV		rv = CKR_OK;
7817Sdinak 
7917Sdinak 	/* If C_Initialize() already called, nothing to do here. */
8017Sdinak 	if (initialized == B_TRUE)
8117Sdinak 		return (CKR_OK);
8217Sdinak 
8317Sdinak 	/* Reset state variables because C_Initialize() not yet done. */
8417Sdinak 	session_opened = B_FALSE;
8517Sdinak 	logged_in = B_FALSE;
8617Sdinak 
8717Sdinak 	/* Initialize PKCS#11 library. */
8817Sdinak 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
8917Sdinak 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
9017Sdinak 		return (rv);
9117Sdinak 	}
9217Sdinak 
9317Sdinak 	initialized = B_TRUE;
9417Sdinak 	return (CKR_OK);
9517Sdinak }
9617Sdinak 
9717Sdinak /*
9817Sdinak  * Finalize PKCS#11 library and reset state variables.  Open sessions,
9917Sdinak  * if any, are closed, and thereby any logins are logged out also.
10017Sdinak  */
10117Sdinak void
10217Sdinak final_pk11(CK_SESSION_HANDLE sess)
10317Sdinak {
10417Sdinak 
10517Sdinak 	/* If the library wasn't initialized, nothing to do here. */
10617Sdinak 	if (!initialized)
10717Sdinak 		return;
10817Sdinak 
10917Sdinak 	/* Make sure the sesion is closed first. */
11017Sdinak 	close_sess(sess);
11117Sdinak 
11217Sdinak 	(void) C_Finalize(NULL);
11317Sdinak 	initialized = B_FALSE;
11417Sdinak }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
11717Sdinak  * Close PKCS#11 session and reset state variables.  Any logins are
11817Sdinak  * logged out.
11917Sdinak  */
1203089Swyllys static void
12117Sdinak close_sess(CK_SESSION_HANDLE sess)
12217Sdinak {
12317Sdinak 
12417Sdinak 	if (sess == NULL) {
12517Sdinak 		return;
12617Sdinak 	}
12717Sdinak 
12817Sdinak 	/* If session is already closed, nothing to do here. */
12917Sdinak 	if (!session_opened)
13017Sdinak 		return;
1310Sstevel@tonic-gate 
13217Sdinak 	/* Make sure user is logged out of token. */
13317Sdinak 	logout_token(sess);
13417Sdinak 
13517Sdinak 	(void) C_CloseSession(sess);
13617Sdinak 	session_opened = B_FALSE;
13717Sdinak }
13817Sdinak 
13917Sdinak /*
14017Sdinak  * Log user out of token and reset status variable.
14117Sdinak  */
1423089Swyllys static void
14317Sdinak logout_token(CK_SESSION_HANDLE sess)
14417Sdinak {
14517Sdinak 
14617Sdinak 	if (sess == NULL) {
14717Sdinak 		return;
14817Sdinak 	}
14917Sdinak 
15017Sdinak 	/* If already logged out, nothing to do here. */
15117Sdinak 	if (!logged_in)
15217Sdinak 		return;
15317Sdinak 
15417Sdinak 	(void) C_Logout(sess);
15517Sdinak 	logged_in = B_FALSE;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
15917Sdinak  * Gets PIN from user.  Caller needs to free the returned PIN when done.
16017Sdinak  * If two prompts are given, the PIN is confirmed with second prompt.
16117Sdinak  * Note that getphassphrase() may return data in static memory area.
16217Sdinak  */
16317Sdinak CK_RV
16417Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
16517Sdinak {
1666051Swyllys 	char *save_phrase, *phrase1, *phrase2;
1670Sstevel@tonic-gate 
16817Sdinak 	/* Prompt user for a PIN. */
16917Sdinak 	if (prompt1 == NULL) {
17017Sdinak 		return (CKR_ARGUMENTS_BAD);
17117Sdinak 	}
17217Sdinak 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
17317Sdinak 		return (CKR_FUNCTION_FAILED);
17417Sdinak 	}
17517Sdinak 
17617Sdinak 	/* Duplicate 1st PIN in separate chunk of memory. */
17717Sdinak 	if ((save_phrase = strdup(phrase1)) == NULL)
17817Sdinak 		return (CKR_HOST_MEMORY);
17917Sdinak 
18017Sdinak 	/* If second prompt given, PIN confirmation is requested. */
18117Sdinak 	if (prompt2 != NULL) {
18217Sdinak 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
18317Sdinak 			free(save_phrase);
18417Sdinak 			return (CKR_FUNCTION_FAILED);
18517Sdinak 		}
18617Sdinak 		if (strcmp(save_phrase, phrase2) != 0) {
18717Sdinak 			free(save_phrase);
18817Sdinak 			return (CKR_PIN_INCORRECT);
18917Sdinak 		}
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 
19217Sdinak 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
19317Sdinak 	*pinlen = strlen(save_phrase);
19417Sdinak 	return (CKR_OK);
19517Sdinak }
19617Sdinak 
1976051Swyllys int
1986051Swyllys yn_to_int(char *ynstr)
1996051Swyllys {
2006051Swyllys 	char *y = gettext("yes");
2016051Swyllys 	char *n = gettext("no");
2026051Swyllys 	if (ynstr == NULL)
2036051Swyllys 		return (-1);
2046051Swyllys 
2056051Swyllys 	if (strncasecmp(ynstr, y, 1) == 0)
2066051Swyllys 		return (1);
2076051Swyllys 	else if (strncasecmp(ynstr, n, 1) == 0)
2086051Swyllys 		return (0);
2096051Swyllys 	else
2106051Swyllys 		return (-1);
2116051Swyllys }
2126051Swyllys 
21317Sdinak /*
21417Sdinak  * Gets yes/no response from user.  If either no prompt is supplied, a
21517Sdinak  * default prompt is used.  If not message for invalid input is supplied,
21617Sdinak  * a default will not be provided.  If the user provides no response,
21717Sdinak  * the input default B_TRUE == yes, B_FALSE == no is returned.
21817Sdinak  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
21917Sdinak  */
22017Sdinak boolean_t
22117Sdinak yesno(char *prompt, char *invalid, boolean_t dflt)
22217Sdinak {
2236051Swyllys 	char	*response, buf[1024];
2246051Swyllys 	int	ans;
22517Sdinak 
22617Sdinak 	if (prompt == NULL)
22717Sdinak 		prompt = gettext("Enter (y)es or (n)o? ");
22817Sdinak 
22917Sdinak 	for (;;) {
23017Sdinak 		/* Prompt user. */
23117Sdinak 		(void) printf("%s", prompt);
23217Sdinak 		(void) fflush(stdout);
23317Sdinak 
23417Sdinak 		/* Get the response. */
23517Sdinak 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
23617Sdinak 			break;		/* go to default response */
23717Sdinak 
23817Sdinak 		/* Skip any leading white space. */
23917Sdinak 		while (isspace(*response))
24017Sdinak 			response++;
24117Sdinak 		if (*response == '\0')
24217Sdinak 			break;		/* go to default response */
24317Sdinak 
2446051Swyllys 		ans = yn_to_int(response);
2456051Swyllys 		if (ans == 1)
24617Sdinak 			return (B_TRUE);
2476051Swyllys 		else if (ans == 0)
24817Sdinak 			return (B_FALSE);
24917Sdinak 
25017Sdinak 		/* Indicate invalid input, and try again. */
25117Sdinak 		if (invalid != NULL)
2525051Swyllys 			(void) printf("%s", invalid);
25317Sdinak 	}
25417Sdinak 	return (dflt);
25517Sdinak }
25617Sdinak 
25717Sdinak /*
25817Sdinak  * Gets the list of slots which have tokens in them.  Keeps adjusting
25917Sdinak  * the size of the slot list buffer until the call is successful or an
26017Sdinak  * irrecoverable error occurs.
26117Sdinak  */
26217Sdinak CK_RV
26317Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
26417Sdinak {
26517Sdinak 	CK_ULONG	tmp_count = 0;
26617Sdinak 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
26717Sdinak 	int		rv = CKR_OK;
26817Sdinak 
26917Sdinak 	if (!initialized)
2706669Swyllys 		if ((rv = init_pkcs11()) != CKR_OK)
27117Sdinak 			return (rv);
27217Sdinak 
27317Sdinak 	/*
27417Sdinak 	 * Get the slot count first because we don't know how many
27517Sdinak 	 * slots there are and how many of those slots even have tokens.
27617Sdinak 	 * Don't specify an arbitrary buffer size for the slot list;
27717Sdinak 	 * it may be too small (see section 11.5 of PKCS#11 spec).
27817Sdinak 	 * Also select only those slots that have tokens in them,
27917Sdinak 	 * because this tool has no need to know about empty slots.
28017Sdinak 	 */
28117Sdinak 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
28217Sdinak 		return (rv);
28317Sdinak 
28417Sdinak 	if (tmp_count == 0) {
28517Sdinak 		*slot_list = NULL_PTR;
28617Sdinak 		*slot_count = 0;
28717Sdinak 		return (CKR_OK);
28817Sdinak 	}
28917Sdinak 
29017Sdinak 	/* Allocate initial space for the slot list. */
29117Sdinak 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
29217Sdinak 	    sizeof (CK_SLOT_ID))) == NULL)
29317Sdinak 		return (CKR_HOST_MEMORY);
29417Sdinak 
29517Sdinak 	/* Then get the slot list itself. */
29617Sdinak 	for (;;) {
29717Sdinak 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
29817Sdinak 			*slot_list = tmp_list;
29917Sdinak 			*slot_count = tmp_count;
30017Sdinak 			break;
30117Sdinak 		}
30217Sdinak 
30317Sdinak 		if (rv != CKR_BUFFER_TOO_SMALL) {
30417Sdinak 			free(tmp_list);
30517Sdinak 			break;
30617Sdinak 		}
30717Sdinak 
30817Sdinak 		/* If the number of slots grew, try again. */
30917Sdinak 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
31017Sdinak 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
31117Sdinak 			free(tmp_list);
31217Sdinak 			rv = CKR_HOST_MEMORY;
31317Sdinak 			break;
31417Sdinak 		}
31517Sdinak 		tmp_list = tmp2_list;
31617Sdinak 	}
31717Sdinak 
31817Sdinak 	return (rv);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate /*
322864Sdinak  * Breaks out the getopt-style option string into a structure that can be
323864Sdinak  * traversed later for calls to getopt_av().  Option string is NOT altered,
324864Sdinak  * but the struct fields point to locations within option string.
325864Sdinak  */
326864Sdinak static int
327864Sdinak populate_opts(char *optstring)
328864Sdinak {
329864Sdinak 	int		i;
330864Sdinak 	av_opts		*temp;
331864Sdinak 	char		*marker;
332864Sdinak 
333864Sdinak 	if (optstring == NULL || *optstring == '\0')
334864Sdinak 		return (0);
335864Sdinak 
336864Sdinak 	/*
337864Sdinak 	 * This tries to imitate getopt(3c) Each option must conform to:
338864Sdinak 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
339864Sdinak 	 * If long name is missing, the short name is used for long name.
340864Sdinak 	 */
341864Sdinak 	for (i = 0; *optstring != '\0'; i++) {
342864Sdinak 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
343864Sdinak 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
3443089Swyllys 			if (opts_av != NULL)
3453089Swyllys 				free(opts_av);
346864Sdinak 			opts_av = NULL;
347864Sdinak 			return (0);
3483089Swyllys 		} else {
349864Sdinak 			opts_av = (av_opts *)temp;
3503089Swyllys 		}
351864Sdinak 
3523089Swyllys 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
353864Sdinak 		marker = optstring;		/* may need optstring later */
354864Sdinak 
355864Sdinak 		opts_av[i].shortnm = *marker++;	/* set short name */
356864Sdinak 
357864Sdinak 		if (*marker == ':') {		/* check for opt arg */
358864Sdinak 			marker++;
359864Sdinak 			opts_av[i].has_arg = B_TRUE;
360864Sdinak 		}
361864Sdinak 
362864Sdinak 		if (*marker == '(') {		/* check and set long name */
363864Sdinak 			marker++;
364864Sdinak 			opts_av[i].longnm = marker;
365864Sdinak 			opts_av[i].longnm_len = strcspn(marker, ")");
366864Sdinak 			optstring = marker + opts_av[i].longnm_len + 1;
367864Sdinak 		} else {
368864Sdinak 			/* use short name option character */
369864Sdinak 			opts_av[i].longnm = optstring;
370864Sdinak 			opts_av[i].longnm_len = 1;
371864Sdinak 			optstring = marker;
372864Sdinak 		}
373864Sdinak 	}
374864Sdinak 
375864Sdinak 	return (i);
376864Sdinak }
377864Sdinak 
378864Sdinak /*
379864Sdinak  * getopt_av() is very similar to getopt(3c) in that the takes an option
380864Sdinak  * string, compares command line arguments for matches, and returns a single
381864Sdinak  * letter option when a match is found.  However, getopt_av() differs from
382864Sdinak  * getopt(3c) by requiring that only longname options and values be found
383864Sdinak  * on the command line and all leading dashes are omitted.  In other words,
384864Sdinak  * it tries to enforce only longname "option=value" arguments on the command
385864Sdinak  * line.  Boolean options are not allowed either.
386864Sdinak  */
387864Sdinak int
388864Sdinak getopt_av(int argc, char * const *argv, const char *optstring)
389864Sdinak {
390864Sdinak 	int	i;
391864Sdinak 	int	len;
3923089Swyllys 	char   *cur_option;
393864Sdinak 
394864Sdinak 	if (optind_av >= argc)
395864Sdinak 		return (EOF);
396864Sdinak 
397864Sdinak 	/* First time or when optstring changes from previous one */
398864Sdinak 	if (_save_optstr != optstring) {
399864Sdinak 		if (opts_av != NULL)
4005051Swyllys 			free(opts_av);
401864Sdinak 		opts_av = NULL;
402864Sdinak 		_save_optstr = optstring;
403864Sdinak 		_save_numopts = populate_opts((char *)optstring);
404864Sdinak 	}
405864Sdinak 
406864Sdinak 	for (i = 0; i < _save_numopts; i++) {
4073089Swyllys 		cur_option = argv[optind_av];
4083089Swyllys 
4093089Swyllys 		if (strcmp(cur_option, "--") == 0) {
410864Sdinak 			optind_av++;
411864Sdinak 			break;
412864Sdinak 		}
413864Sdinak 
4143089Swyllys 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
4153089Swyllys 			len = 1;
4163089Swyllys 			cur_option++; /* remove "-" */
4173089Swyllys 		} else {
4183089Swyllys 			len = strcspn(cur_option, "=");
4193089Swyllys 		}
420864Sdinak 
4213089Swyllys 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
422864Sdinak 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
423864Sdinak 			/* matched */
424864Sdinak 			if (!opts_av[i].has_arg) {
425864Sdinak 				optind_av++;
426864Sdinak 				return (opts_av[i].shortnm);
427864Sdinak 			}
428864Sdinak 
429864Sdinak 			/* needs optarg */
4303089Swyllys 			if (cur_option[len] == '=') {
4313089Swyllys 				optarg_av = &(cur_option[len+1]);
432864Sdinak 				optind_av++;
433864Sdinak 				return (opts_av[i].shortnm);
434864Sdinak 			}
435864Sdinak 
436864Sdinak 			optarg_av = NULL;
437864Sdinak 			optind_av++;
438864Sdinak 			return ((int)'?');
439864Sdinak 		}
440864Sdinak 	}
441864Sdinak 
442864Sdinak 	return (EOF);
443864Sdinak }
4443089Swyllys 
4453089Swyllys KMF_KEYSTORE_TYPE
4463089Swyllys KS2Int(char *keystore_str)
4473089Swyllys {
4483089Swyllys 	if (keystore_str == NULL)
4493089Swyllys 		return (0);
4506051Swyllys 	if (strcasecmp(keystore_str, "pkcs11") == 0)
4513089Swyllys 		return (KMF_KEYSTORE_PK11TOKEN);
4526051Swyllys 	else if (strcasecmp(keystore_str, "nss") == 0)
4533089Swyllys 		return (KMF_KEYSTORE_NSS);
4546051Swyllys 	else if (strcasecmp(keystore_str, "file") == 0)
4553089Swyllys 		return (KMF_KEYSTORE_OPENSSL);
4563089Swyllys 	else
4573089Swyllys 		return (0);
4583089Swyllys }
4593089Swyllys 
4603089Swyllys 
4613089Swyllys int
4623089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
4633089Swyllys {
4643089Swyllys 	if (algm == NULL) {
4653089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4663089Swyllys 		*ktype = KMF_RSA;
4673089Swyllys 	} else if (strcasecmp(algm, "DSA") == 0) {
4683089Swyllys 		*sigAlg = KMF_ALGID_SHA1WithDSA;
4693089Swyllys 		*ktype = KMF_DSA;
4703089Swyllys 	} else if (strcasecmp(algm, "RSA") == 0) {
4713089Swyllys 		*sigAlg = KMF_ALGID_MD5WithRSA;
4723089Swyllys 		*ktype = KMF_RSA;
4733089Swyllys 	} else {
4743089Swyllys 		return (-1);
4753089Swyllys 	}
4763089Swyllys 	return (0);
4773089Swyllys }
4783089Swyllys 
4793089Swyllys int
4803089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
4813089Swyllys {
4823089Swyllys 	if (algm == NULL)
4833089Swyllys 		*ktype = KMF_AES;
4843089Swyllys 	else if (strcasecmp(algm, "aes") == 0)
4853089Swyllys 		*ktype = KMF_AES;
4863089Swyllys 	else if (strcasecmp(algm, "arcfour") == 0)
4873089Swyllys 		*ktype = KMF_RC4;
4883089Swyllys 	else if (strcasecmp(algm, "des") == 0)
4893089Swyllys 		*ktype = KMF_DES;
4903089Swyllys 	else if (strcasecmp(algm, "3des") == 0)
4913089Swyllys 		*ktype = KMF_DES3;
4923812Shylee 	else if (strcasecmp(algm, "generic") == 0)
4933812Shylee 		*ktype = KMF_GENERIC_SECRET;
4943089Swyllys 	else
4953089Swyllys 		return (-1);
4963089Swyllys 
4973089Swyllys 	return (0);
4983089Swyllys }
4993089Swyllys 
5003089Swyllys int
5013089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
5023089Swyllys {
5033089Swyllys 	int num;
5043089Swyllys 	char timetok[6];
5053089Swyllys 
5066051Swyllys 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
5073089Swyllys 		/* default to 1 year lifetime */
5083089Swyllys 		*ltime = SECSPERDAY * DAYSPERNYEAR;
5093089Swyllys 		return (0);
5103089Swyllys 	}
5113089Swyllys 
5123089Swyllys 	(void) memset(timetok, 0, sizeof (timetok));
5133089Swyllys 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
5143089Swyllys 		return (-1);
5153089Swyllys 
5166051Swyllys 	if (strcasecmp(timetok, "day") == 0||
5176051Swyllys 	    strcasecmp(timetok, "days") == 0) {
5183089Swyllys 		*ltime = num * SECSPERDAY;
5196051Swyllys 	} else if (strcasecmp(timetok, "hour") == 0||
5206051Swyllys 	    strcasecmp(timetok, "hours") == 0) {
5213089Swyllys 		*ltime = num * SECSPERHOUR;
5226051Swyllys 	} else if (strcasecmp(timetok, "year") == 0 ||
5236051Swyllys 	    strcasecmp(timetok, "years") == 0) {
5243089Swyllys 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
5253089Swyllys 	} else {
5263089Swyllys 		*ltime = 0;
5273089Swyllys 		return (-1);
5283089Swyllys 	}
5293089Swyllys 
5303089Swyllys 	return (0);
5313089Swyllys }
5323089Swyllys 
5333089Swyllys int
5343089Swyllys OT2Int(char *objclass)
5353089Swyllys {
5363089Swyllys 	char *c = NULL;
5373089Swyllys 	int retval = 0;
5383089Swyllys 
5393089Swyllys 	if (objclass == NULL)
5403089Swyllys 		return (-1);
5413089Swyllys 
5423089Swyllys 	c = strchr(objclass, ':');
5433089Swyllys 	if (c != NULL) {
5446051Swyllys 		if (strcasecmp(c, ":private") == 0)
5453089Swyllys 			retval = PK_PRIVATE_OBJ;
5466051Swyllys 		else if (strcasecmp(c, ":public") == 0)
5473089Swyllys 			retval = PK_PUBLIC_OBJ;
5486051Swyllys 		else if (strcasecmp(c, ":both") == 0)
5493089Swyllys 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
5503089Swyllys 		else /* unrecognized option */
5513089Swyllys 			return (-1);
5523089Swyllys 
5533089Swyllys 		*c = '\0';
5543089Swyllys 	}
5553089Swyllys 
5566051Swyllys 	if (strcasecmp(objclass, "public") == 0) {
5573089Swyllys 		if (retval)
5583089Swyllys 			return (-1);
5595051Swyllys 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
5606051Swyllys 	} else if (strcasecmp(objclass, "private") == 0) {
5613089Swyllys 		if (retval)
5623089Swyllys 			return (-1);
5633089Swyllys 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
5646051Swyllys 	} else if (strcasecmp(objclass, "both") == 0) {
5653089Swyllys 		if (retval)
5663089Swyllys 			return (-1);
5673089Swyllys 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
5686051Swyllys 	} else if (strcasecmp(objclass, "cert") == 0) {
5693089Swyllys 		return (retval | PK_CERT_OBJ);
5706051Swyllys 	} else if (strcasecmp(objclass, "key") == 0) {
5713089Swyllys 		if (retval == 0) /* return all keys */
5723089Swyllys 			return (retval | PK_KEY_OBJ);
5733089Swyllys 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
5743089Swyllys 			/* return all keys */
5753089Swyllys 			return (retval | PK_KEY_OBJ);
5763089Swyllys 		else if (retval & PK_PUBLIC_OBJ)
5773089Swyllys 			/* Only return public keys */
5783089Swyllys 			return (retval | PK_PUBKEY_OBJ);
5793089Swyllys 		else if (retval & PK_PRIVATE_OBJ)
5803089Swyllys 			/* Only return private keys */
5813089Swyllys 			return (retval | PK_PRIKEY_OBJ);
5826051Swyllys 	} else if (strcasecmp(objclass, "crl") == 0) {
5833089Swyllys 		if (retval)
5843089Swyllys 			return (-1);
5853089Swyllys 		return (retval | PK_CRL_OBJ);
5863089Swyllys 	}
5873089Swyllys 
5883089Swyllys 	if (retval == 0) /* No matches found */
5893089Swyllys 		retval = -1;
5903089Swyllys 	return (retval);
5913089Swyllys }
5923089Swyllys 
5933089Swyllys KMF_ENCODE_FORMAT
5943089Swyllys Str2Format(char *formstr)
5953089Swyllys {
5966051Swyllys 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
5973089Swyllys 		return (KMF_FORMAT_ASN1);
5986051Swyllys 	if (strcasecmp(formstr, "pem") == 0)
5993089Swyllys 		return (KMF_FORMAT_PEM);
6006051Swyllys 	if (strcasecmp(formstr, "pkcs12") == 0)
6013089Swyllys 		return (KMF_FORMAT_PKCS12);
6026051Swyllys 	if (strcasecmp(formstr, "raw") == 0)
6035051Swyllys 		return (KMF_FORMAT_RAWKEY);
6043089Swyllys 
6053089Swyllys 	return (KMF_FORMAT_UNDEF);
6063089Swyllys }
6073089Swyllys 
6083089Swyllys KMF_RETURN
6096051Swyllys select_token(void *kmfhandle, char *token, int readonly)
6103089Swyllys {
6115051Swyllys 	KMF_ATTRIBUTE attlist[10];
6125051Swyllys 	int i = 0;
6135051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
6143089Swyllys 	KMF_RETURN rv = KMF_OK;
6153089Swyllys 
6163089Swyllys 	if (token == NULL)
6173089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
6183089Swyllys 
6195051Swyllys 	kmf_set_attr_at_index(attlist, i,
6205051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6215051Swyllys 	    sizeof (kstype));
6225051Swyllys 	i++;
6233089Swyllys 
6245051Swyllys 	if (token) {
6255051Swyllys 		kmf_set_attr_at_index(attlist, i,
6265051Swyllys 		    KMF_TOKEN_LABEL_ATTR, token,
6275051Swyllys 		    strlen(token));
6285051Swyllys 		i++;
6295051Swyllys 	}
6305051Swyllys 
6315051Swyllys 	kmf_set_attr_at_index(attlist, i,
6325051Swyllys 	    KMF_READONLY_ATTR, &readonly,
6335051Swyllys 	    sizeof (readonly));
6345051Swyllys 	i++;
6355051Swyllys 
6365051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6373089Swyllys 	if (rv == KMF_ERR_TOKEN_SELECTED)
6383089Swyllys 		rv = KMF_OK;
6393089Swyllys 	return (rv);
6403089Swyllys }
6413089Swyllys 
6423089Swyllys KMF_RETURN
6433089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
6443089Swyllys {
6455051Swyllys 	KMF_ATTRIBUTE attlist[10];
6465051Swyllys 	int i = 0;
6475051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
6483089Swyllys 	KMF_RETURN rv = KMF_OK;
6495051Swyllys 
6505051Swyllys 	kmf_set_attr_at_index(attlist, i,
6515051Swyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
6525051Swyllys 	    sizeof (kstype));
6535051Swyllys 	i++;
6543089Swyllys 
6555051Swyllys 	if (dir) {
6565051Swyllys 		kmf_set_attr_at_index(attlist, i,
6575051Swyllys 		    KMF_DIRPATH_ATTR, dir,
6585051Swyllys 		    strlen(dir));
6595051Swyllys 		i++;
6605051Swyllys 	}
6613089Swyllys 
6625051Swyllys 	if (prefix) {
6635051Swyllys 		kmf_set_attr_at_index(attlist, i,
6645051Swyllys 		    KMF_CERTPREFIX_ATTR, prefix,
6655051Swyllys 		    strlen(prefix));
6665051Swyllys 		i++;
6675051Swyllys 
6685051Swyllys 		kmf_set_attr_at_index(attlist, i,
6695051Swyllys 		    KMF_KEYPREFIX_ATTR, prefix,
6705051Swyllys 		    strlen(prefix));
6715051Swyllys 		i++;
6725051Swyllys 	}
6735051Swyllys 
6745051Swyllys 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
6753089Swyllys 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
6763089Swyllys 		rv = KMF_OK;
6773089Swyllys 
6783089Swyllys 	return (rv);
6793089Swyllys }
6803089Swyllys 
6813089Swyllys KMF_RETURN
6823089Swyllys get_pk12_password(KMF_CREDENTIAL *cred)
6833089Swyllys {
6843089Swyllys 	KMF_RETURN rv = KMF_OK;
6853089Swyllys 	char prompt[1024];
6863089Swyllys 
6873089Swyllys 	/*
6883089Swyllys 	 * Get the password to use for the PK12 encryption.
6893089Swyllys 	 */
6903089Swyllys 	(void) strlcpy(prompt,
6915051Swyllys 	    gettext("Enter password to use for "
6925051Swyllys 	    "accessing the PKCS12 file: "), sizeof (prompt));
6933089Swyllys 
6943089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
6955051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
6963089Swyllys 		cred->cred = NULL;
6973089Swyllys 		cred->credlen = 0;
6983089Swyllys 	}
6993089Swyllys 
7003089Swyllys 	return (rv);
7013089Swyllys }
7023089Swyllys 
7035221Swyllys #define	FILENAME_PROMPT gettext("Filename:")
7045221Swyllys #define	FILENAME_MINLEN	1
7055221Swyllys #define	FILENAME_MAXLEN MAXPATHLEN
7063089Swyllys 
7075221Swyllys #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
7085221Swyllys #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
7095221Swyllys 	"[Some-State]:")
7105221Swyllys #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
7115221Swyllys #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
7125221Swyllys #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
7135221Swyllys #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
7145221Swyllys #define	EMAIL_PROMPT	gettext("Email Address []:")
7155221Swyllys 
7165221Swyllys #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
7175221Swyllys 	"0x01020304):")
7185221Swyllys #define	SERNO_MINLEN	3
7195221Swyllys #define	SERNO_MAXLEN	42
7205221Swyllys 
7215221Swyllys #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
7225221Swyllys #define	LABEL_MINLEN	1
7235221Swyllys #define	LABEL_MAXLEN	1024
7243089Swyllys 
7253089Swyllys #define	COUNTRY_DEFAULT "US"
7265221Swyllys #define	STATE_DEFAULT	NULL
7275221Swyllys #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
7283089Swyllys 
7293089Swyllys #define	SUBNAMESIZ	1024
7303089Swyllys #define	RDN_MIN		1
7313089Swyllys #define	RDN_MAX		64
7323089Swyllys #define	COUNTRYNAME_MIN	2
7333089Swyllys #define	COUNTRYNAME_MAX	2
7343089Swyllys 
7353089Swyllys static char *
7363089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
7373089Swyllys {
7383089Swyllys 	char buf[1024];
7393089Swyllys 	char *response = NULL;
7403089Swyllys 	char *ret = NULL;
7413089Swyllys 	int len;
7423089Swyllys 
7433089Swyllys 	for (;;) {
7443089Swyllys 		(void) printf("\t%s", prompt);
7453089Swyllys 		(void) fflush(stdout);
7463089Swyllys 
7473089Swyllys 		response = fgets(buf, sizeof (buf), stdin);
7483089Swyllys 		if (response == NULL) {
7493089Swyllys 			if (default_str != NULL) {
7503089Swyllys 				ret = strdup(default_str);
7513089Swyllys 			}
7523089Swyllys 			break;
7533089Swyllys 		}
7543089Swyllys 
7553089Swyllys 		/* Skip any leading white space. */
7563089Swyllys 		while (isspace(*response))
7573089Swyllys 			response++;
7583089Swyllys 		if (*response == '\0') {
7593089Swyllys 			if (default_str != NULL) {
7603089Swyllys 				ret = strdup(default_str);
7613089Swyllys 			}
7623089Swyllys 			break;
7633089Swyllys 		}
7643089Swyllys 
7653089Swyllys 		len = strlen(response);
7663089Swyllys 		response[len-1] = '\0'; /* get rid of "LF" */
7673089Swyllys 		len--;
7683089Swyllys 		if (len >= min_len && len <= max_len) {
7693089Swyllys 			ret = strdup(response);
7703089Swyllys 			break;
7713089Swyllys 		}
7723089Swyllys 
7733089Swyllys 		(void) printf("%s\n", INVALID_INPUT);
7743089Swyllys 
7753089Swyllys 	}
7763089Swyllys 
7773089Swyllys 	return (ret);
7783089Swyllys }
7793089Swyllys 
7803089Swyllys int
7815221Swyllys get_filename(char *txt, char **result)
7825221Swyllys {
7835221Swyllys 	char prompt[1024];
7845221Swyllys 	char *fname = NULL;
7855221Swyllys 
7865221Swyllys 	(void) snprintf(prompt, sizeof (prompt),
7875221Swyllys 	    gettext("Enter filename for the %s: "),
7885221Swyllys 	    txt);
7895221Swyllys 	fname = get_input_string(prompt, NULL,
7905221Swyllys 	    FILENAME_MINLEN, FILENAME_MAXLEN);
7915221Swyllys 	*result = fname;
7925221Swyllys 	return (0);
7935221Swyllys }
7945221Swyllys 
7955221Swyllys int
7965221Swyllys get_certlabel(char **result)
7975221Swyllys {
7985221Swyllys 	char *label = NULL;
7995221Swyllys 
8005221Swyllys 	label = get_input_string(LABEL_PROMPT, NULL,
8015221Swyllys 	    LABEL_MINLEN, LABEL_MAXLEN);
8025221Swyllys 	*result = label;
8035221Swyllys 	return (0);
8045221Swyllys }
8055221Swyllys 
8065221Swyllys int
8075221Swyllys get_serial(char **result)
8085221Swyllys {
8095221Swyllys 	char *serial = NULL;
8105221Swyllys 
8115221Swyllys 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
8125221Swyllys 	    SERNO_MAXLEN);
8135221Swyllys 
8145221Swyllys 	*result = serial;
8155221Swyllys 	return (0);
8165221Swyllys }
8175221Swyllys 
8185221Swyllys int
8193089Swyllys get_subname(char **result)
8203089Swyllys {
8213089Swyllys 	char *country = NULL;
8223089Swyllys 	char *state = NULL;
8233089Swyllys 	char *locality = NULL;
8243089Swyllys 	char *org = NULL;
8253089Swyllys 	char *unit = NULL;
8263089Swyllys 	char *name = NULL;
8273089Swyllys 	char *email = NULL;
8283089Swyllys 	char *subname = NULL;
8293089Swyllys 
8303089Swyllys 	(void) printf("Entering following fields for subject (a DN) ...\n");
8313089Swyllys 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
8323089Swyllys 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
8333089Swyllys 	if (country == NULL)
8343089Swyllys 		return (-1);
8353089Swyllys 
8363089Swyllys 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
8373089Swyllys 	    RDN_MIN, RDN_MAX);
8383089Swyllys 
8393089Swyllys 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
8403089Swyllys 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
8413089Swyllys 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
8423089Swyllys 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
8433089Swyllys 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
8443089Swyllys 
8453089Swyllys 	/* Now create a subject name from the input strings */
8463089Swyllys 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
8473089Swyllys 		goto out;
8483089Swyllys 
8493089Swyllys 	(void) memset(subname, 0, SUBNAMESIZ);
8503089Swyllys 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
8513089Swyllys 	(void) strlcat(subname, country, SUBNAMESIZ);
8525221Swyllys 	if (state != NULL) {
8535221Swyllys 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
8545221Swyllys 		(void) strlcat(subname, state, SUBNAMESIZ);
8555221Swyllys 	}
8563089Swyllys 
8575221Swyllys 	if (locality != NULL) {
8585221Swyllys 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
8593089Swyllys 		(void) strlcat(subname, locality, SUBNAMESIZ);
8603089Swyllys 	}
8613089Swyllys 
8625221Swyllys 	if (org != NULL) {
8635221Swyllys 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
8643089Swyllys 		(void) strlcat(subname, org, SUBNAMESIZ);
8653089Swyllys 	}
8663089Swyllys 
8675221Swyllys 	if (unit != NULL) {
8685221Swyllys 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
8693089Swyllys 		(void) strlcat(subname, unit, SUBNAMESIZ);
8703089Swyllys 	}
8713089Swyllys 
8725221Swyllys 	if (name != NULL) {
8735221Swyllys 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
8743089Swyllys 		(void) strlcat(subname, name, SUBNAMESIZ);
8753089Swyllys 	}
8763089Swyllys 
8775221Swyllys 	if (email != NULL) {
8785221Swyllys 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
8793089Swyllys 		(void) strlcat(subname, email, SUBNAMESIZ);
8803089Swyllys 	}
8813089Swyllys 
8823089Swyllys out:
8833089Swyllys 	if (country)
8843089Swyllys 		free(country);
8853089Swyllys 	if (state)
8863089Swyllys 		free(state);
8873089Swyllys 	if (locality)
8883089Swyllys 		free(locality);
8893089Swyllys 	if (org)
8903089Swyllys 		free(org);
8913089Swyllys 	if (unit)
8923089Swyllys 		free(unit);
8933089Swyllys 	if (name)
8943089Swyllys 		free(name);
8953089Swyllys 	if (email)
8963089Swyllys 		free(email);
8973089Swyllys 
8983089Swyllys 	if (subname == NULL)
8993089Swyllys 		return (-1);
9003089Swyllys 	else {
9013089Swyllys 		*result = subname;
9023089Swyllys 		return (0);
9033089Swyllys 	}
9043089Swyllys }
9053089Swyllys 
9063089Swyllys /*
9073089Swyllys  * Parse a string of KeyUsage values and convert
9083089Swyllys  * them to the correct KU Bits.
9093089Swyllys  * The field may be marked "critical" by prepending
9103089Swyllys  * "critical:" to the list.
9113089Swyllys  * EX:  critical:digitialSignature,keyEncipherment
9123089Swyllys  */
9133089Swyllys KMF_RETURN
9143089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
9153089Swyllys {
9163089Swyllys 	KMF_RETURN ret = KMF_OK;
9173089Swyllys 	uint16_t kuval;
9183089Swyllys 	char *k;
9193089Swyllys 
9203089Swyllys 	*kubits = 0;
9216051Swyllys 	if (kustr == NULL || strlen(kustr) == 0)
9223089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9233089Swyllys 
9243089Swyllys 	/* Check to see if this is critical */
9256051Swyllys 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
9263089Swyllys 		*critical = TRUE;
9273089Swyllys 		kustr += strlen("critical:");
9283089Swyllys 	} else {
9293089Swyllys 		*critical = FALSE;
9303089Swyllys 	}
9313089Swyllys 
9323089Swyllys 	k = strtok(kustr, ",");
9333089Swyllys 	while (k != NULL) {
9345051Swyllys 		kuval = kmf_string_to_ku(k);
9353089Swyllys 		if (kuval == 0) {
9363089Swyllys 			*kubits = 0;
9373089Swyllys 			return (KMF_ERR_BAD_PARAMETER);
9383089Swyllys 		}
9393089Swyllys 		*kubits |= kuval;
9403089Swyllys 		k = strtok(NULL, ",");
9413089Swyllys 	}
9423089Swyllys 
9433089Swyllys 	return (ret);
9443089Swyllys }
9453089Swyllys 
9463089Swyllys /*
9473089Swyllys  * Verify the alternate subject label is real or invalid.
9483089Swyllys  *
9493089Swyllys  * The field may be marked "critical" by prepending
9503089Swyllys  * "critical:" to the list.
9513089Swyllys  * EX:  "critical:IP=1.2.3.4"
9523089Swyllys  */
9533089Swyllys KMF_RETURN
9543089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
9553089Swyllys {
9563089Swyllys 	char *p;
9573089Swyllys 	KMF_RETURN rv = KMF_OK;
9583089Swyllys 
9593089Swyllys 	/* Check to see if this is critical */
9606051Swyllys 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
9613089Swyllys 		*critical = TRUE;
9623089Swyllys 		arg += strlen("critical:");
9633089Swyllys 	} else {
9643089Swyllys 		*critical = FALSE;
9653089Swyllys 	}
9663089Swyllys 
9673089Swyllys 	/* Make sure there is an "=" sign */
9683089Swyllys 	p = strchr(arg, '=');
9693089Swyllys 	if (p == NULL)
9703089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
9713089Swyllys 
9723089Swyllys 	p[0] = '\0';
9733089Swyllys 
9743089Swyllys 	if (strcmp(arg, "IP") == 0)
9753089Swyllys 		*type = GENNAME_IPADDRESS;
9763089Swyllys 	else if (strcmp(arg, "DNS") == 0)
9773089Swyllys 		*type = GENNAME_DNSNAME;
9783089Swyllys 	else if (strcmp(arg, "EMAIL") == 0)
9793089Swyllys 		*type = GENNAME_RFC822NAME;
9803089Swyllys 	else if (strcmp(arg, "URI") == 0)
9813089Swyllys 		*type = GENNAME_URI;
9823089Swyllys 	else if (strcmp(arg, "DN") == 0)
9833089Swyllys 		*type = GENNAME_DIRECTORYNAME;
9843089Swyllys 	else if (strcmp(arg, "RID") == 0)
9853089Swyllys 		*type = GENNAME_REGISTEREDID;
9866051Swyllys 	else if (strcmp(arg, "KRB") == 0)
9876051Swyllys 		*type = GENNAME_KRB5PRINC;
9886051Swyllys 	else if (strcmp(arg, "UPN") == 0)
9896051Swyllys 		*type = GENNAME_SCLOGON_UPN;
9903089Swyllys 	else
9913089Swyllys 		rv = KMF_ERR_BAD_PARAMETER;
9923089Swyllys 
9933089Swyllys 	p[0] = '=';
9943089Swyllys 
9953089Swyllys 	return (rv);
9963089Swyllys }
9973089Swyllys 
9983089Swyllys int
9993089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
10003089Swyllys 	char *token_spec, KMF_CREDENTIAL *cred)
10013089Swyllys {
10023089Swyllys 	char	prompt[1024];
10038132SWyllys.Ingersoll@Sun.COM 	char	temptoken[32];
10043089Swyllys 	char	*p = NULL;
10058132SWyllys.Ingersoll@Sun.COM 	char	*t = NULL;
1006*9126SWyllys.Ingersoll@Sun.COM 	int	len;
10073089Swyllys 
1008*9126SWyllys.Ingersoll@Sun.COM 	(void) memset(temptoken, 0, sizeof (temptoken));
10093089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
10103089Swyllys 		p = strchr(token_spec, ':');
10113089Swyllys 		if (p != NULL)
10128132SWyllys.Ingersoll@Sun.COM 			*p = 0;
10133089Swyllys 	}
1014*9126SWyllys.Ingersoll@Sun.COM 	len = strlen(token_spec);
1015*9126SWyllys.Ingersoll@Sun.COM 	if (len > sizeof (temptoken))
1016*9126SWyllys.Ingersoll@Sun.COM 		len = sizeof (temptoken);
1017*9126SWyllys.Ingersoll@Sun.COM 
1018*9126SWyllys.Ingersoll@Sun.COM 	(void) strncpy(temptoken, token_spec, len);
10198132SWyllys.Ingersoll@Sun.COM 
10208132SWyllys.Ingersoll@Sun.COM 	/*
10218132SWyllys.Ingersoll@Sun.COM 	 * Strip trailing whitespace
10228132SWyllys.Ingersoll@Sun.COM 	 */
1023*9126SWyllys.Ingersoll@Sun.COM 	t = temptoken + (len - 1);
10248132SWyllys.Ingersoll@Sun.COM 	while (isspace(*t) && t >= temptoken) {
10258132SWyllys.Ingersoll@Sun.COM 		*t = 0x00;
10268132SWyllys.Ingersoll@Sun.COM 		t--;
10278132SWyllys.Ingersoll@Sun.COM 	}
10288132SWyllys.Ingersoll@Sun.COM 
10293089Swyllys 	/*
10303089Swyllys 	 * Login to the token first.
10313089Swyllys 	 */
10323089Swyllys 	(void) snprintf(prompt, sizeof (prompt),
10338132SWyllys.Ingersoll@Sun.COM 	    gettext(DEFAULT_TOKEN_PROMPT), temptoken);
10343089Swyllys 
10353089Swyllys 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
10365051Swyllys 	    (ulong_t *)&cred->credlen) != CKR_OK) {
10373089Swyllys 		cred->cred = NULL;
10383089Swyllys 		cred->credlen = 0;
10393089Swyllys 	}
10403089Swyllys 
10413089Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
10423089Swyllys 		*p = ':';
10433089Swyllys 	return (KMF_OK);
10443089Swyllys }
10453089Swyllys 
10463089Swyllys KMF_RETURN
10473089Swyllys verify_file(char *filename)
10483089Swyllys {
10493089Swyllys 	KMF_RETURN ret = KMF_OK;
10503089Swyllys 	int fd;
10513089Swyllys 
10523089Swyllys 	/*
10533089Swyllys 	 * Attempt to open with  the EXCL flag so that if
10543089Swyllys 	 * it already exists, the open will fail.  It will
10553089Swyllys 	 * also fail if the file cannot be created due to
10563089Swyllys 	 * permissions on the parent directory, or if the
10573089Swyllys 	 * parent directory itself does not exist.
10583089Swyllys 	 */
10593089Swyllys 	fd = open(filename, O_CREAT | O_EXCL, 0600);
10603089Swyllys 	if (fd == -1)
10613089Swyllys 		return (KMF_ERR_OPEN_FILE);
10623089Swyllys 
10633089Swyllys 	/* If we were able to create it, delete it. */
10643089Swyllys 	(void) close(fd);
10653089Swyllys 	(void) unlink(filename);
10663089Swyllys 
10673089Swyllys 	return (ret);
10683089Swyllys }
10693089Swyllys 
10703089Swyllys void
10713089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
10723089Swyllys {
10733089Swyllys 	KMF_RETURN rv1, rv2;
10743089Swyllys 	char *plugin_errmsg = NULL;
10753089Swyllys 	char *kmf_errmsg = NULL;
10763089Swyllys 
10775051Swyllys 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
10785051Swyllys 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
10793089Swyllys 
10803089Swyllys 	cryptoerror(LOG_STDERR, "%s:", prefix);
10813089Swyllys 	if (rv1 == KMF_OK && plugin_errmsg) {
10825051Swyllys 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
10835051Swyllys 		    plugin_errmsg);
10845051Swyllys 		kmf_free_str(plugin_errmsg);
10853089Swyllys 	}
10863089Swyllys 
10873089Swyllys 	if (rv2 == KMF_OK && kmf_errmsg) {
10885051Swyllys 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
10895051Swyllys 		    kmf_errmsg);
10905051Swyllys 		kmf_free_str(kmf_errmsg);
10913089Swyllys 	}
10923089Swyllys 
10933089Swyllys 	if (rv1 != KMF_OK && rv2 != KMF_OK)
10943089Swyllys 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
10953089Swyllys 
10963089Swyllys }
10976051Swyllys 
10986051Swyllys static KMF_RETURN
10996051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
11006051Swyllys {
11016051Swyllys 	if (newoid != NULL && ekus != NULL) {
11026051Swyllys 		ekus->eku_count++;
11036051Swyllys 
11046051Swyllys 		ekus->critlist = realloc(ekus->critlist,
11056051Swyllys 		    ekus->eku_count * sizeof (int));
11066051Swyllys 		if (ekus->critlist != NULL)
11076051Swyllys 			ekus->critlist[ekus->eku_count-1] = critical;
11086051Swyllys 		else
11096051Swyllys 			return (KMF_ERR_MEMORY);
11106051Swyllys 
11116051Swyllys 		ekus->ekulist = realloc(
11126051Swyllys 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
11136051Swyllys 		if (ekus->ekulist != NULL)
11146051Swyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
11156051Swyllys 		else
11166051Swyllys 			return (KMF_ERR_MEMORY);
11176051Swyllys 	}
11186051Swyllys 	return (KMF_OK);
11196051Swyllys }
11206051Swyllys 
11216051Swyllys void
11226051Swyllys free_eku_list(EKU_LIST *ekus)
11236051Swyllys {
11246051Swyllys 	if (ekus != NULL && ekus->eku_count > 0) {
11256051Swyllys 		int i;
11266051Swyllys 		for (i = 0; i < ekus->eku_count; i++) {
11276051Swyllys 			kmf_free_data(&ekus->ekulist[i]);
11286051Swyllys 		}
11296051Swyllys 		free(ekus->ekulist);
11306051Swyllys 		free(ekus->critlist);
11316051Swyllys 	}
11326051Swyllys }
11336051Swyllys 
11346051Swyllys static KMF_RETURN
11356051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
11366051Swyllys {
11376051Swyllys 	KMF_RETURN rv = KMF_OK;
11386051Swyllys 	KMF_OID *newoid;
11396051Swyllys 	int critical;
11406051Swyllys 
11416051Swyllys 	if (strncasecmp(ekustr, "critical:",
11426051Swyllys 	    strlen("critical:")) == 0) {
11436051Swyllys 		critical = TRUE;
11446051Swyllys 		ekustr += strlen("critical:");
11456051Swyllys 	} else {
11466051Swyllys 		critical = FALSE;
11476051Swyllys 	}
11486051Swyllys 	newoid = kmf_ekuname_to_oid(ekustr);
11496051Swyllys 	if (newoid != NULL) {
11506051Swyllys 		rv = addToEKUList(ekus, critical, newoid);
11516051Swyllys 		free(newoid);
11526051Swyllys 	} else {
11536051Swyllys 		rv = PK_ERR_USAGE;
11546051Swyllys 	}
11556051Swyllys 
11566051Swyllys 	return (rv);
11576051Swyllys }
11586051Swyllys 
11596051Swyllys KMF_RETURN
11606051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
11616051Swyllys {
11626051Swyllys 	KMF_RETURN rv = KMF_OK;
11636051Swyllys 	char *p;
11646051Swyllys 	EKU_LIST *ekus = NULL;
11656051Swyllys 
11666051Swyllys 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
11676051Swyllys 		return (0);
11686051Swyllys 
11696051Swyllys 	/*
11706051Swyllys 	 * The list should be comma separated list of EKU Names.
11716051Swyllys 	 */
11726051Swyllys 	p = strtok(ekuliststr, ",");
11736051Swyllys 
11746051Swyllys 	/* If no tokens found, then maybe it's just a single EKU value */
11756051Swyllys 	if (p == NULL) {
11766051Swyllys 		rv = parse_ekus(ekuliststr, ekus);
11776051Swyllys 	}
11786051Swyllys 
11796051Swyllys 	while (p != NULL) {
11806051Swyllys 		rv = parse_ekus(p, ekus);
11816051Swyllys 
11826051Swyllys 		if (rv != KMF_OK)
11836051Swyllys 			break;
11846051Swyllys 		p = strtok(NULL, ",");
11856051Swyllys 	}
11866051Swyllys 
11876051Swyllys 	if (rv != KMF_OK)
11886051Swyllys 		free_eku_list(ekus);
11896051Swyllys 	else
11906051Swyllys 		*ekulist = ekus;
11916051Swyllys 
11926051Swyllys 	return (rv);
11936051Swyllys }
11946354Swyllys 
11956354Swyllys KMF_RETURN
11966354Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
11976354Swyllys {
11986354Swyllys 	CK_TOKEN_INFO info;
11996354Swyllys 	CK_SLOT_ID slot;
12006354Swyllys 	CK_RV ckrv;
12016354Swyllys 	KMF_RETURN rv;
12026354Swyllys 
12036354Swyllys 	*auth = 0;
12046354Swyllys 	rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
12056354Swyllys 	if (rv != KMF_OK)
12066354Swyllys 		return (rv);
12076354Swyllys 
12086354Swyllys 	ckrv = C_GetTokenInfo(slot, &info);
12096354Swyllys 	if (ckrv != KMF_OK)
12106354Swyllys 		return (KMF_ERR_INTERNAL);
12116354Swyllys 
12126354Swyllys 	*auth = (info.flags & CKF_LOGIN_REQUIRED);
12136354Swyllys 
12146354Swyllys 	return (KMF_OK);
12156354Swyllys }
1216