xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/common.c (revision e65e5c2d2f32a99e8c5f740cabae9075dab03ce7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file contains the functions that are shared among
28  * the various services this tool will ultimately provide.
29  * The functions in this file return PKCS#11 CK_RV errors.
30  * Only one session and one login per token is supported
31  * at this time.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <tzfile.h>
42 #include <cryptoutil.h>
43 #include <security/cryptoki.h>
44 #include <kmfapi.h>
45 
46 #include "common.h"
47 
48 /* Local status variables. */
49 static boolean_t	initialized = B_FALSE;
50 static boolean_t	session_opened = B_FALSE;
51 static boolean_t	logged_in = B_FALSE;
52 
53 /* Supporting structures and global variables for getopt_av(). */
54 typedef struct	av_opts_s {
55 	int		shortnm;	/* short name character */
56 	char		*longnm;	/* long name string, NOT terminated */
57 	int		longnm_len;	/* length of long name string */
58 	boolean_t	has_arg;	/* takes optional argument */
59 } av_opts;
60 static av_opts		*opts_av = NULL;
61 static const char	*_save_optstr = NULL;
62 static int		_save_numopts = 0;
63 
64 int			optind_av = 1;
65 char			*optarg_av = NULL;
66 
67 static void close_sess(CK_SESSION_HANDLE);
68 static void logout_token(CK_SESSION_HANDLE);
69 
70 struct oid_table_entry {
71 	const KMF_OID *oid;
72 	char *name;
73 };
74 
75 struct oid_table_entry oid_table[] = {
76 	{ &KMFOID_ECC_secp112r1, "secp112r1"},
77 	{ &KMFOID_ECC_secp112r2, "secp112r2"},
78 	{ &KMFOID_ECC_secp128r1, "secp128r1"},
79 	{ &KMFOID_ECC_secp128r2, "secp128r2"},
80 	{ &KMFOID_ECC_secp160k1, "secp160k1"},
81 	{ &KMFOID_ECC_secp160r1, "secp160r1"},
82 	{ &KMFOID_ECC_secp160r2, "secp160r2"},
83 	{ &KMFOID_ECC_secp192k1, "secp192k1"},
84 	{ &KMFOID_ECC_secp192r1, "secp192r1"},
85 	{ &KMFOID_ECC_secp224k1, "secp224k1"},
86 	{ &KMFOID_ECC_secp224r1, "secp224r1"},
87 	{ &KMFOID_ECC_secp256k1, "secp256k1"},
88 	{ &KMFOID_ECC_secp256r1, "secp256r1"},
89 	{ &KMFOID_ECC_secp384r1, "secp384r1"},
90 	{ &KMFOID_ECC_secp521r1, "secp521r1"},
91 	{ &KMFOID_ECC_sect113r1, "sect113r1"},
92 	{ &KMFOID_ECC_sect113r2, "sect113r2"},
93 	{ &KMFOID_ECC_sect131r1, "sect131r1"},
94 	{ &KMFOID_ECC_sect131r2, "sect131r2"},
95 	{ &KMFOID_ECC_sect163k1, "sect163k1"},
96 	{ &KMFOID_ECC_sect163r1, "sect163r1"},
97 	{ &KMFOID_ECC_sect163r2, "sect163r2"},
98 	{ &KMFOID_ECC_sect193r1, "sect193r1"},
99 	{ &KMFOID_ECC_sect193r2, "sect193r2"},
100 	{ &KMFOID_ECC_sect233k1, "sect233k1"},
101 	{ &KMFOID_ECC_sect233r1, "sect233r1"},
102 	{ &KMFOID_ECC_sect239k1, "sect239k1"},
103 	{ &KMFOID_ECC_sect283k1, "sect283k1"},
104 	{ &KMFOID_ECC_sect283r1, "sect283r1"},
105 	{ &KMFOID_ECC_sect409k1, "sect409k1"},
106 	{ &KMFOID_ECC_sect409r1, "sect409r1"},
107 	{ &KMFOID_ECC_sect571k1, "sect571k1"},
108 	{ &KMFOID_ECC_sect571r1, "sect571r1"},
109 	{ &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
110 	{ &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
111 	{ &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
112 	{ &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
113 	{ &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
114 	{ &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
115 	{ &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
116 	{ &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
117 	{ &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
118 	{ &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
119 	{ &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
120 	{ &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
121 	{ &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
122 	{ &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
123 	{ &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
124 	{ &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
125 	{ &KMFOID_ECC_prime192v2, "prime192v2"},
126 	{ &KMFOID_ECC_prime192v3, "prime192v3"},
127 	{ &KMFOID_MD5, "md5"},
128 	{ &KMFOID_SHA1, "sha1"},
129 	{ &KMFOID_SHA256, "sha256"},
130 	{ &KMFOID_SHA384, "sha384"},
131 	{ &KMFOID_SHA512, "sha512"}
132 };
133 int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
134 #define	number_of_curves (number_of_oids - 5)
135 
136 /*
137  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
138  * along with setting/resetting state variables.
139  */
140 static CK_RV
141 init_pkcs11(void)
142 {
143 	CK_RV		rv = CKR_OK;
144 
145 	/* If C_Initialize() already called, nothing to do here. */
146 	if (initialized == B_TRUE)
147 		return (CKR_OK);
148 
149 	/* Reset state variables because C_Initialize() not yet done. */
150 	session_opened = B_FALSE;
151 	logged_in = B_FALSE;
152 
153 	/* Initialize PKCS#11 library. */
154 	if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
155 	    rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
156 		return (rv);
157 	}
158 
159 	initialized = B_TRUE;
160 	return (CKR_OK);
161 }
162 
163 /*
164  * Finalize PKCS#11 library and reset state variables.  Open sessions,
165  * if any, are closed, and thereby any logins are logged out also.
166  */
167 void
168 final_pk11(CK_SESSION_HANDLE sess)
169 {
170 
171 	/* If the library wasn't initialized, nothing to do here. */
172 	if (!initialized)
173 		return;
174 
175 	/* Make sure the sesion is closed first. */
176 	close_sess(sess);
177 
178 	(void) C_Finalize(NULL);
179 	initialized = B_FALSE;
180 }
181 
182 /*
183  * Close PKCS#11 session and reset state variables.  Any logins are
184  * logged out.
185  */
186 static void
187 close_sess(CK_SESSION_HANDLE sess)
188 {
189 
190 	if (sess == NULL) {
191 		return;
192 	}
193 
194 	/* If session is already closed, nothing to do here. */
195 	if (!session_opened)
196 		return;
197 
198 	/* Make sure user is logged out of token. */
199 	logout_token(sess);
200 
201 	(void) C_CloseSession(sess);
202 	session_opened = B_FALSE;
203 }
204 
205 /*
206  * Log user out of token and reset status variable.
207  */
208 static void
209 logout_token(CK_SESSION_HANDLE sess)
210 {
211 
212 	if (sess == NULL) {
213 		return;
214 	}
215 
216 	/* If already logged out, nothing to do here. */
217 	if (!logged_in)
218 		return;
219 
220 	(void) C_Logout(sess);
221 	logged_in = B_FALSE;
222 }
223 
224 /*
225  * Gets PIN from user.  Caller needs to free the returned PIN when done.
226  * If two prompts are given, the PIN is confirmed with second prompt.
227  * Note that getphassphrase() may return data in static memory area.
228  */
229 CK_RV
230 get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
231 {
232 	char *save_phrase, *phrase1, *phrase2;
233 
234 	/* Prompt user for a PIN. */
235 	if (prompt1 == NULL) {
236 		return (CKR_ARGUMENTS_BAD);
237 	}
238 	if ((phrase1 = getpassphrase(prompt1)) == NULL) {
239 		return (CKR_FUNCTION_FAILED);
240 	}
241 
242 	/* Duplicate 1st PIN in separate chunk of memory. */
243 	if ((save_phrase = strdup(phrase1)) == NULL)
244 		return (CKR_HOST_MEMORY);
245 
246 	/* If second prompt given, PIN confirmation is requested. */
247 	if (prompt2 != NULL) {
248 		if ((phrase2 = getpassphrase(prompt2)) == NULL) {
249 			free(save_phrase);
250 			return (CKR_FUNCTION_FAILED);
251 		}
252 		if (strcmp(save_phrase, phrase2) != 0) {
253 			free(save_phrase);
254 			return (CKR_PIN_INCORRECT);
255 		}
256 	}
257 
258 	*pin = (CK_UTF8CHAR_PTR)save_phrase;
259 	*pinlen = strlen(save_phrase);
260 	return (CKR_OK);
261 }
262 
263 int
264 yn_to_int(char *ynstr)
265 {
266 	char *y = gettext("yes");
267 	char *n = gettext("no");
268 	if (ynstr == NULL)
269 		return (-1);
270 
271 	if (strncasecmp(ynstr, y, 1) == 0)
272 		return (1);
273 	else if (strncasecmp(ynstr, n, 1) == 0)
274 		return (0);
275 	else
276 		return (-1);
277 }
278 
279 /*
280  * Gets yes/no response from user.  If either no prompt is supplied, a
281  * default prompt is used.  If not message for invalid input is supplied,
282  * a default will not be provided.  If the user provides no response,
283  * the input default B_TRUE == yes, B_FALSE == no is returned.
284  * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
285  */
286 boolean_t
287 yesno(char *prompt, char *invalid, boolean_t dflt)
288 {
289 	char	*response, buf[1024];
290 	int	ans;
291 
292 	if (prompt == NULL)
293 		prompt = gettext("Enter (y)es or (n)o? ");
294 
295 	for (;;) {
296 		/* Prompt user. */
297 		(void) printf("%s", prompt);
298 		(void) fflush(stdout);
299 
300 		/* Get the response. */
301 		if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
302 			break;		/* go to default response */
303 
304 		/* Skip any leading white space. */
305 		while (isspace(*response))
306 			response++;
307 		if (*response == '\0')
308 			break;		/* go to default response */
309 
310 		ans = yn_to_int(response);
311 		if (ans == 1)
312 			return (B_TRUE);
313 		else if (ans == 0)
314 			return (B_FALSE);
315 
316 		/* Indicate invalid input, and try again. */
317 		if (invalid != NULL)
318 			(void) printf("%s", invalid);
319 	}
320 	return (dflt);
321 }
322 
323 /*
324  * Gets the list of slots which have tokens in them.  Keeps adjusting
325  * the size of the slot list buffer until the call is successful or an
326  * irrecoverable error occurs.
327  */
328 CK_RV
329 get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
330 {
331 	CK_ULONG	tmp_count = 0;
332 	CK_SLOT_ID_PTR	tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
333 	int		rv = CKR_OK;
334 
335 	if (!initialized)
336 		if ((rv = init_pkcs11()) != CKR_OK)
337 			return (rv);
338 
339 	/*
340 	 * Get the slot count first because we don't know how many
341 	 * slots there are and how many of those slots even have tokens.
342 	 * Don't specify an arbitrary buffer size for the slot list;
343 	 * it may be too small (see section 11.5 of PKCS#11 spec).
344 	 * Also select only those slots that have tokens in them,
345 	 * because this tool has no need to know about empty slots.
346 	 */
347 	if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
348 		return (rv);
349 
350 	if (tmp_count == 0) {
351 		*slot_list = NULL_PTR;
352 		*slot_count = 0;
353 		return (CKR_OK);
354 	}
355 
356 	/* Allocate initial space for the slot list. */
357 	if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
358 	    sizeof (CK_SLOT_ID))) == NULL)
359 		return (CKR_HOST_MEMORY);
360 
361 	/* Then get the slot list itself. */
362 	for (;;) {
363 		if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
364 			*slot_list = tmp_list;
365 			*slot_count = tmp_count;
366 			break;
367 		}
368 
369 		if (rv != CKR_BUFFER_TOO_SMALL) {
370 			free(tmp_list);
371 			break;
372 		}
373 
374 		/* If the number of slots grew, try again. */
375 		if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
376 		    tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
377 			free(tmp_list);
378 			rv = CKR_HOST_MEMORY;
379 			break;
380 		}
381 		tmp_list = tmp2_list;
382 	}
383 
384 	return (rv);
385 }
386 
387 /*
388  * Breaks out the getopt-style option string into a structure that can be
389  * traversed later for calls to getopt_av().  Option string is NOT altered,
390  * but the struct fields point to locations within option string.
391  */
392 static int
393 populate_opts(char *optstring)
394 {
395 	int		i;
396 	av_opts		*temp;
397 	char		*marker;
398 
399 	if (optstring == NULL || *optstring == '\0')
400 		return (0);
401 
402 	/*
403 	 * This tries to imitate getopt(3c) Each option must conform to:
404 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
405 	 * If long name is missing, the short name is used for long name.
406 	 */
407 	for (i = 0; *optstring != '\0'; i++) {
408 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
409 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
410 			if (opts_av != NULL)
411 				free(opts_av);
412 			opts_av = NULL;
413 			return (0);
414 		} else {
415 			opts_av = (av_opts *)temp;
416 		}
417 
418 		(void) memset(&opts_av[i], 0, sizeof (av_opts));
419 		marker = optstring;		/* may need optstring later */
420 
421 		opts_av[i].shortnm = *marker++;	/* set short name */
422 
423 		if (*marker == ':') {		/* check for opt arg */
424 			marker++;
425 			opts_av[i].has_arg = B_TRUE;
426 		}
427 
428 		if (*marker == '(') {		/* check and set long name */
429 			marker++;
430 			opts_av[i].longnm = marker;
431 			opts_av[i].longnm_len = strcspn(marker, ")");
432 			optstring = marker + opts_av[i].longnm_len + 1;
433 		} else {
434 			/* use short name option character */
435 			opts_av[i].longnm = optstring;
436 			opts_av[i].longnm_len = 1;
437 			optstring = marker;
438 		}
439 	}
440 
441 	return (i);
442 }
443 
444 /*
445  * getopt_av() is very similar to getopt(3c) in that the takes an option
446  * string, compares command line arguments for matches, and returns a single
447  * letter option when a match is found.  However, getopt_av() differs from
448  * getopt(3c) by requiring that only longname options and values be found
449  * on the command line and all leading dashes are omitted.  In other words,
450  * it tries to enforce only longname "option=value" arguments on the command
451  * line.  Boolean options are not allowed either.
452  */
453 int
454 getopt_av(int argc, char * const *argv, const char *optstring)
455 {
456 	int	i;
457 	int	len;
458 	char   *cur_option;
459 
460 	if (optind_av >= argc)
461 		return (EOF);
462 
463 	/* First time or when optstring changes from previous one */
464 	if (_save_optstr != optstring) {
465 		if (opts_av != NULL)
466 			free(opts_av);
467 		opts_av = NULL;
468 		_save_optstr = optstring;
469 		_save_numopts = populate_opts((char *)optstring);
470 	}
471 
472 	for (i = 0; i < _save_numopts; i++) {
473 		cur_option = argv[optind_av];
474 
475 		if (strcmp(cur_option, "--") == 0) {
476 			optind_av++;
477 			break;
478 		}
479 
480 		if (cur_option[0] == '-' && strlen(cur_option) == 2) {
481 			len = 1;
482 			cur_option++; /* remove "-" */
483 		} else {
484 			len = strcspn(cur_option, "=");
485 		}
486 
487 		if (len == opts_av[i].longnm_len && strncmp(cur_option,
488 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
489 			/* matched */
490 			if (!opts_av[i].has_arg) {
491 				optind_av++;
492 				return (opts_av[i].shortnm);
493 			}
494 
495 			/* needs optarg */
496 			if (cur_option[len] == '=') {
497 				optarg_av = &(cur_option[len+1]);
498 				optind_av++;
499 				return (opts_av[i].shortnm);
500 			}
501 
502 			optarg_av = NULL;
503 			optind_av++;
504 			return ((int)'?');
505 		}
506 	}
507 
508 	return (EOF);
509 }
510 
511 KMF_KEYSTORE_TYPE
512 KS2Int(char *keystore_str)
513 {
514 	if (keystore_str == NULL)
515 		return (0);
516 	if (strcasecmp(keystore_str, "pkcs11") == 0)
517 		return (KMF_KEYSTORE_PK11TOKEN);
518 	else if (strcasecmp(keystore_str, "nss") == 0)
519 		return (KMF_KEYSTORE_NSS);
520 	else if (strcasecmp(keystore_str, "file") == 0)
521 		return (KMF_KEYSTORE_OPENSSL);
522 	else
523 		return (0);
524 }
525 
526 /*
527  * compare_oids
528  * return 1 if equal
529  */
530 boolean_t
531 compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
532 {
533 	return ((oid1->Length == oid2->Length) &&
534 	    !memcmp(oid1->Data, oid2->Data, oid1->Length));
535 }
536 
537 int
538 Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
539     KMF_ALGORITHM_INDEX *sigAlg)
540 {
541 	if (algm == NULL) {
542 		/* Default to SHA1+RSA */
543 		*sigAlg = KMF_ALGID_SHA1WithRSA;
544 		*ktype = KMF_RSA;
545 	} else if (strcasecmp(algm, "DSA") == 0) {
546 		if (hashoid == NULL ||
547 		    compare_oids(hashoid, &KMFOID_SHA1))
548 			*sigAlg = KMF_ALGID_SHA1WithDSA;
549 		else if (compare_oids(hashoid, &KMFOID_SHA256))
550 			*sigAlg = KMF_ALGID_SHA256WithDSA;
551 		else
552 			return (-1); /* unsupported hash/key combo */
553 		*ktype = KMF_DSA;
554 	} else if (strcasecmp(algm, "RSA") == 0) {
555 		if (hashoid == NULL ||
556 		    compare_oids(hashoid, &KMFOID_SHA1))
557 			*sigAlg = KMF_ALGID_SHA1WithRSA;
558 		else if (compare_oids(hashoid, &KMFOID_SHA256))
559 			*sigAlg = KMF_ALGID_SHA256WithRSA;
560 		else if (compare_oids(hashoid, &KMFOID_SHA384))
561 			*sigAlg = KMF_ALGID_SHA384WithRSA;
562 		else if (compare_oids(hashoid, &KMFOID_SHA512))
563 			*sigAlg = KMF_ALGID_SHA512WithRSA;
564 		else if (compare_oids(hashoid, &KMFOID_MD5))
565 			*sigAlg = KMF_ALGID_MD5WithRSA;
566 		else
567 			return (-1); /* unsupported hash/key combo */
568 		*ktype = KMF_RSA;
569 	} else if (strcasecmp(algm, "EC") == 0) {
570 		/* EC keys may be used with some SHA2 hashes */
571 		if (hashoid == NULL ||
572 		    compare_oids(hashoid, &KMFOID_SHA1))
573 			*sigAlg = KMF_ALGID_SHA1WithECDSA;
574 		else if (compare_oids(hashoid, &KMFOID_SHA256))
575 			*sigAlg = KMF_ALGID_SHA256WithECDSA;
576 		else if (compare_oids(hashoid, &KMFOID_SHA384))
577 			*sigAlg = KMF_ALGID_SHA384WithECDSA;
578 		else if (compare_oids(hashoid, &KMFOID_SHA512))
579 			*sigAlg = KMF_ALGID_SHA512WithECDSA;
580 		else
581 			return (-1); /* unsupported hash/key combo */
582 
583 		*ktype = KMF_ECDSA;
584 	} else {
585 		return (-1);
586 	}
587 	return (0);
588 }
589 
590 int
591 Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
592 {
593 	if (algm == NULL)
594 		*ktype = KMF_AES;
595 	else if (strcasecmp(algm, "aes") == 0)
596 		*ktype = KMF_AES;
597 	else if (strcasecmp(algm, "arcfour") == 0)
598 		*ktype = KMF_RC4;
599 	else if (strcasecmp(algm, "des") == 0)
600 		*ktype = KMF_DES;
601 	else if (strcasecmp(algm, "3des") == 0)
602 		*ktype = KMF_DES3;
603 	else if (strcasecmp(algm, "generic") == 0)
604 		*ktype = KMF_GENERIC_SECRET;
605 	else
606 		return (-1);
607 
608 	return (0);
609 }
610 
611 int
612 Str2Lifetime(char *ltimestr, uint32_t *ltime)
613 {
614 	int num;
615 	char timetok[6];
616 
617 	if (ltimestr == NULL || strlen(ltimestr) == 0) {
618 		/* default to 1 year lifetime */
619 		*ltime = SECSPERDAY * DAYSPERNYEAR;
620 		return (0);
621 	}
622 
623 	(void) memset(timetok, 0, sizeof (timetok));
624 	if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
625 		return (-1);
626 
627 	if (strcasecmp(timetok, "day") == 0||
628 	    strcasecmp(timetok, "days") == 0) {
629 		*ltime = num * SECSPERDAY;
630 	} else if (strcasecmp(timetok, "hour") == 0||
631 	    strcasecmp(timetok, "hours") == 0) {
632 		*ltime = num * SECSPERHOUR;
633 	} else if (strcasecmp(timetok, "year") == 0 ||
634 	    strcasecmp(timetok, "years") == 0) {
635 		*ltime = num * SECSPERDAY * DAYSPERNYEAR;
636 	} else {
637 		*ltime = 0;
638 		return (-1);
639 	}
640 
641 	return (0);
642 }
643 
644 int
645 OT2Int(char *objclass)
646 {
647 	char *c = NULL;
648 	int retval = 0;
649 
650 	if (objclass == NULL)
651 		return (-1);
652 
653 	c = strchr(objclass, ':');
654 	if (c != NULL) {
655 		if (strcasecmp(c, ":private") == 0)
656 			retval = PK_PRIVATE_OBJ;
657 		else if (strcasecmp(c, ":public") == 0)
658 			retval = PK_PUBLIC_OBJ;
659 		else if (strcasecmp(c, ":both") == 0)
660 			retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
661 		else /* unrecognized option */
662 			return (-1);
663 
664 		*c = '\0';
665 	}
666 
667 	if (strcasecmp(objclass, "public") == 0) {
668 		if (retval)
669 			return (-1);
670 		return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
671 	} else if (strcasecmp(objclass, "private") == 0) {
672 		if (retval)
673 			return (-1);
674 		return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
675 	} else if (strcasecmp(objclass, "both") == 0) {
676 		if (retval)
677 			return (-1);
678 		return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
679 	} else if (strcasecmp(objclass, "cert") == 0) {
680 		return (retval | PK_CERT_OBJ);
681 	} else if (strcasecmp(objclass, "key") == 0) {
682 		if (retval == 0) /* return all keys */
683 			return (retval | PK_KEY_OBJ);
684 		else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
685 			/* return all keys */
686 			return (retval | PK_KEY_OBJ);
687 		else if (retval & PK_PUBLIC_OBJ)
688 			/* Only return public keys */
689 			return (retval | PK_PUBKEY_OBJ);
690 		else if (retval & PK_PRIVATE_OBJ)
691 			/* Only return private keys */
692 			return (retval | PK_PRIKEY_OBJ);
693 	} else if (strcasecmp(objclass, "crl") == 0) {
694 		if (retval)
695 			return (-1);
696 		return (retval | PK_CRL_OBJ);
697 	}
698 
699 	if (retval == 0) /* No matches found */
700 		retval = -1;
701 	return (retval);
702 }
703 
704 KMF_ENCODE_FORMAT
705 Str2Format(char *formstr)
706 {
707 	if (formstr == NULL || strcasecmp(formstr, "der") == 0)
708 		return (KMF_FORMAT_ASN1);
709 	if (strcasecmp(formstr, "pem") == 0)
710 		return (KMF_FORMAT_PEM);
711 	if (strcasecmp(formstr, "pkcs12") == 0)
712 		return (KMF_FORMAT_PKCS12);
713 	if (strcasecmp(formstr, "raw") == 0)
714 		return (KMF_FORMAT_RAWKEY);
715 
716 	return (KMF_FORMAT_UNDEF);
717 }
718 
719 KMF_RETURN
720 select_token(void *kmfhandle, char *token, int readonly)
721 {
722 	KMF_ATTRIBUTE attlist[10];
723 	int i = 0;
724 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
725 	KMF_RETURN rv = KMF_OK;
726 
727 	if (token == NULL)
728 		return (KMF_ERR_BAD_PARAMETER);
729 
730 	kmf_set_attr_at_index(attlist, i,
731 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
732 	    sizeof (kstype));
733 	i++;
734 
735 	if (token) {
736 		kmf_set_attr_at_index(attlist, i,
737 		    KMF_TOKEN_LABEL_ATTR, token,
738 		    strlen(token));
739 		i++;
740 	}
741 
742 	kmf_set_attr_at_index(attlist, i,
743 	    KMF_READONLY_ATTR, &readonly,
744 	    sizeof (readonly));
745 	i++;
746 
747 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
748 	if (rv == KMF_ERR_TOKEN_SELECTED)
749 		rv = KMF_OK;
750 	return (rv);
751 }
752 
753 KMF_RETURN
754 configure_nss(void *kmfhandle, char *dir, char *prefix)
755 {
756 	KMF_ATTRIBUTE attlist[10];
757 	int i = 0;
758 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
759 	KMF_RETURN rv = KMF_OK;
760 
761 	kmf_set_attr_at_index(attlist, i,
762 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
763 	    sizeof (kstype));
764 	i++;
765 
766 	if (dir) {
767 		kmf_set_attr_at_index(attlist, i,
768 		    KMF_DIRPATH_ATTR, dir,
769 		    strlen(dir));
770 		i++;
771 	}
772 
773 	if (prefix) {
774 		kmf_set_attr_at_index(attlist, i,
775 		    KMF_CERTPREFIX_ATTR, prefix,
776 		    strlen(prefix));
777 		i++;
778 
779 		kmf_set_attr_at_index(attlist, i,
780 		    KMF_KEYPREFIX_ATTR, prefix,
781 		    strlen(prefix));
782 		i++;
783 	}
784 
785 	rv = kmf_configure_keystore(kmfhandle, i, attlist);
786 	if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
787 		rv = KMF_OK;
788 
789 	return (rv);
790 }
791 
792 KMF_RETURN
793 get_pk12_password(KMF_CREDENTIAL *cred)
794 {
795 	KMF_RETURN rv = KMF_OK;
796 	char prompt[1024];
797 
798 	/*
799 	 * Get the password to use for the PK12 encryption.
800 	 */
801 	(void) strlcpy(prompt,
802 	    gettext("Enter password to use for "
803 	    "accessing the PKCS12 file: "), sizeof (prompt));
804 
805 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
806 	    (ulong_t *)&cred->credlen) != CKR_OK) {
807 		cred->cred = NULL;
808 		cred->credlen = 0;
809 	}
810 
811 	return (rv);
812 }
813 
814 #define	FILENAME_PROMPT gettext("Filename:")
815 #define	FILENAME_MINLEN	1
816 #define	FILENAME_MAXLEN MAXPATHLEN
817 
818 #define	COUNTRY_PROMPT	gettext("Country Name (2 letter code) [US]:")
819 #define	STATE_PROMPT	gettext("State or Province Name (full name) " \
820 	"[Some-State]:")
821 #define	LOCALITY_PROMPT	gettext("Locality Name (eg, city) []:")
822 #define	ORG_PROMPT	gettext("Organization Name (eg, company) []:")
823 #define	UNIT_PROMPT	gettext("Organizational Unit Name (eg, section) []:")
824 #define	NAME_PROMPT	gettext("Common Name (eg, YOUR name) []:")
825 #define	EMAIL_PROMPT	gettext("Email Address []:")
826 
827 #define	SERNO_PROMPT	gettext("Serial Number (hex value, example: " \
828 	"0x01020304):")
829 #define	SERNO_MINLEN	3
830 #define	SERNO_MAXLEN	42
831 
832 #define	LABEL_PROMPT	gettext("Enter a label for the certificate:")
833 #define	LABEL_MINLEN	1
834 #define	LABEL_MAXLEN	1024
835 
836 #define	COUNTRY_DEFAULT "US"
837 #define	STATE_DEFAULT	NULL
838 #define	INVALID_INPUT 	gettext("Invalid input; please re-enter ...")
839 
840 #define	SUBNAMESIZ	1024
841 #define	RDN_MIN		1
842 #define	RDN_MAX		64
843 #define	COUNTRYNAME_MIN	2
844 #define	COUNTRYNAME_MAX	2
845 
846 static char *
847 get_input_string(char *prompt, char *default_str, int min_len, int max_len)
848 {
849 	char buf[1024];
850 	char *response = NULL;
851 	char *ret = NULL;
852 	int len;
853 
854 	for (;;) {
855 		(void) printf("\t%s", prompt);
856 		(void) fflush(stdout);
857 
858 		response = fgets(buf, sizeof (buf), stdin);
859 		if (response == NULL) {
860 			if (default_str != NULL) {
861 				ret = strdup(default_str);
862 			}
863 			break;
864 		}
865 
866 		/* Skip any leading white space. */
867 		while (isspace(*response))
868 			response++;
869 		if (*response == '\0') {
870 			if (default_str != NULL) {
871 				ret = strdup(default_str);
872 			}
873 			break;
874 		}
875 
876 		len = strlen(response);
877 		response[len-1] = '\0'; /* get rid of "LF" */
878 		len--;
879 		if (len >= min_len && len <= max_len) {
880 			ret = strdup(response);
881 			break;
882 		}
883 
884 		(void) printf("%s\n", INVALID_INPUT);
885 
886 	}
887 
888 	return (ret);
889 }
890 
891 int
892 get_filename(char *txt, char **result)
893 {
894 	char prompt[1024];
895 	char *fname = NULL;
896 
897 	(void) snprintf(prompt, sizeof (prompt),
898 	    gettext("Enter filename for the %s: "),
899 	    txt);
900 	fname = get_input_string(prompt, NULL,
901 	    FILENAME_MINLEN, FILENAME_MAXLEN);
902 	*result = fname;
903 	return (0);
904 }
905 
906 int
907 get_certlabel(char **result)
908 {
909 	char *label = NULL;
910 
911 	label = get_input_string(LABEL_PROMPT, NULL,
912 	    LABEL_MINLEN, LABEL_MAXLEN);
913 	*result = label;
914 	return (0);
915 }
916 
917 int
918 get_serial(char **result)
919 {
920 	char *serial = NULL;
921 
922 	serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
923 	    SERNO_MAXLEN);
924 
925 	*result = serial;
926 	return (0);
927 }
928 
929 int
930 get_subname(char **result)
931 {
932 	char *country = NULL;
933 	char *state = NULL;
934 	char *locality = NULL;
935 	char *org = NULL;
936 	char *unit = NULL;
937 	char *name = NULL;
938 	char *email = NULL;
939 	char *subname = NULL;
940 
941 	(void) printf("Entering following fields for subject (a DN) ...\n");
942 	country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
943 	    COUNTRYNAME_MIN, COUNTRYNAME_MAX);
944 	if (country == NULL)
945 		return (-1);
946 
947 	state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
948 	    RDN_MIN, RDN_MAX);
949 
950 	locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
951 	org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
952 	unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
953 	name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
954 	email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
955 
956 	/* Now create a subject name from the input strings */
957 	if ((subname = malloc(SUBNAMESIZ)) == NULL)
958 		goto out;
959 
960 	(void) memset(subname, 0, SUBNAMESIZ);
961 	(void) strlcpy(subname, "C=", SUBNAMESIZ);
962 	(void) strlcat(subname, country, SUBNAMESIZ);
963 	if (state != NULL) {
964 		(void) strlcat(subname, ", ST=", SUBNAMESIZ);
965 		(void) strlcat(subname, state, SUBNAMESIZ);
966 	}
967 
968 	if (locality != NULL) {
969 		(void) strlcat(subname, ", L=", SUBNAMESIZ);
970 		(void) strlcat(subname, locality, SUBNAMESIZ);
971 	}
972 
973 	if (org != NULL) {
974 		(void) strlcat(subname, ", O=", SUBNAMESIZ);
975 		(void) strlcat(subname, org, SUBNAMESIZ);
976 	}
977 
978 	if (unit != NULL) {
979 		(void) strlcat(subname, ", OU=", SUBNAMESIZ);
980 		(void) strlcat(subname, unit, SUBNAMESIZ);
981 	}
982 
983 	if (name != NULL) {
984 		(void) strlcat(subname, ", CN=", SUBNAMESIZ);
985 		(void) strlcat(subname, name, SUBNAMESIZ);
986 	}
987 
988 	if (email != NULL) {
989 		(void) strlcat(subname, ", E=", SUBNAMESIZ);
990 		(void) strlcat(subname, email, SUBNAMESIZ);
991 	}
992 
993 out:
994 	if (country)
995 		free(country);
996 	if (state)
997 		free(state);
998 	if (locality)
999 		free(locality);
1000 	if (org)
1001 		free(org);
1002 	if (unit)
1003 		free(unit);
1004 	if (name)
1005 		free(name);
1006 	if (email)
1007 		free(email);
1008 
1009 	if (subname == NULL)
1010 		return (-1);
1011 	else {
1012 		*result = subname;
1013 		return (0);
1014 	}
1015 }
1016 
1017 /*
1018  * Parse a string of KeyUsage values and convert
1019  * them to the correct KU Bits.
1020  * The field may be marked "critical" by prepending
1021  * "critical:" to the list.
1022  * EX:  critical:digitialSignature,keyEncipherment
1023  */
1024 KMF_RETURN
1025 verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
1026 {
1027 	KMF_RETURN ret = KMF_OK;
1028 	uint16_t kuval;
1029 	char *k;
1030 
1031 	*kubits = 0;
1032 	if (kustr == NULL || strlen(kustr) == 0)
1033 		return (KMF_ERR_BAD_PARAMETER);
1034 
1035 	/* Check to see if this is critical */
1036 	if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
1037 		*critical = TRUE;
1038 		kustr += strlen("critical:");
1039 	} else {
1040 		*critical = FALSE;
1041 	}
1042 
1043 	k = strtok(kustr, ",");
1044 	while (k != NULL) {
1045 		kuval = kmf_string_to_ku(k);
1046 		if (kuval == 0) {
1047 			*kubits = 0;
1048 			return (KMF_ERR_BAD_PARAMETER);
1049 		}
1050 		*kubits |= kuval;
1051 		k = strtok(NULL, ",");
1052 	}
1053 
1054 	return (ret);
1055 }
1056 
1057 /*
1058  * Verify the alternate subject label is real or invalid.
1059  *
1060  * The field may be marked "critical" by prepending
1061  * "critical:" to the list.
1062  * EX:  "critical:IP=1.2.3.4"
1063  */
1064 KMF_RETURN
1065 verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
1066 {
1067 	char *p;
1068 	KMF_RETURN rv = KMF_OK;
1069 
1070 	/* Check to see if this is critical */
1071 	if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
1072 		*critical = TRUE;
1073 		arg += strlen("critical:");
1074 	} else {
1075 		*critical = FALSE;
1076 	}
1077 
1078 	/* Make sure there is an "=" sign */
1079 	p = strchr(arg, '=');
1080 	if (p == NULL)
1081 		return (KMF_ERR_BAD_PARAMETER);
1082 
1083 	p[0] = '\0';
1084 
1085 	if (strcmp(arg, "IP") == 0)
1086 		*type = GENNAME_IPADDRESS;
1087 	else if (strcmp(arg, "DNS") == 0)
1088 		*type = GENNAME_DNSNAME;
1089 	else if (strcmp(arg, "EMAIL") == 0)
1090 		*type = GENNAME_RFC822NAME;
1091 	else if (strcmp(arg, "URI") == 0)
1092 		*type = GENNAME_URI;
1093 	else if (strcmp(arg, "DN") == 0)
1094 		*type = GENNAME_DIRECTORYNAME;
1095 	else if (strcmp(arg, "RID") == 0)
1096 		*type = GENNAME_REGISTEREDID;
1097 	else if (strcmp(arg, "KRB") == 0)
1098 		*type = GENNAME_KRB5PRINC;
1099 	else if (strcmp(arg, "UPN") == 0)
1100 		*type = GENNAME_SCLOGON_UPN;
1101 	else
1102 		rv = KMF_ERR_BAD_PARAMETER;
1103 
1104 	p[0] = '=';
1105 
1106 	return (rv);
1107 }
1108 
1109 int
1110 get_token_password(KMF_KEYSTORE_TYPE kstype,
1111 	char *token_spec, KMF_CREDENTIAL *cred)
1112 {
1113 	char	prompt[1024];
1114 	char	temptoken[32];
1115 	char	*p = NULL;
1116 	char	*t = NULL;
1117 	int	len;
1118 
1119 	(void) memset(temptoken, 0, sizeof (temptoken));
1120 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
1121 		p = strchr(token_spec, ':');
1122 		if (p != NULL)
1123 			*p = 0;
1124 	}
1125 	len = strlen(token_spec);
1126 	if (len > sizeof (temptoken))
1127 		len = sizeof (temptoken);
1128 
1129 	(void) strncpy(temptoken, token_spec, len);
1130 
1131 	/*
1132 	 * Strip trailing whitespace
1133 	 */
1134 	t = temptoken + (len - 1);
1135 	while (isspace(*t) && t >= temptoken) {
1136 		*t = 0x00;
1137 		t--;
1138 	}
1139 
1140 	/*
1141 	 * Login to the token first.
1142 	 */
1143 	(void) snprintf(prompt, sizeof (prompt),
1144 	    gettext(DEFAULT_TOKEN_PROMPT), temptoken);
1145 
1146 	if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
1147 	    (ulong_t *)&cred->credlen) != CKR_OK) {
1148 		cred->cred = NULL;
1149 		cred->credlen = 0;
1150 	}
1151 
1152 	if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
1153 		*p = ':';
1154 	return (KMF_OK);
1155 }
1156 
1157 KMF_RETURN
1158 verify_file(char *filename)
1159 {
1160 	KMF_RETURN ret = KMF_OK;
1161 	int fd;
1162 
1163 	/*
1164 	 * Attempt to open with  the EXCL flag so that if
1165 	 * it already exists, the open will fail.  It will
1166 	 * also fail if the file cannot be created due to
1167 	 * permissions on the parent directory, or if the
1168 	 * parent directory itself does not exist.
1169 	 */
1170 	fd = open(filename, O_CREAT | O_EXCL, 0600);
1171 	if (fd == -1)
1172 		return (KMF_ERR_OPEN_FILE);
1173 
1174 	/* If we were able to create it, delete it. */
1175 	(void) close(fd);
1176 	(void) unlink(filename);
1177 
1178 	return (ret);
1179 }
1180 
1181 void
1182 display_error(void *handle, KMF_RETURN errcode, char *prefix)
1183 {
1184 	KMF_RETURN rv1, rv2;
1185 	char *plugin_errmsg = NULL;
1186 	char *kmf_errmsg = NULL;
1187 
1188 	rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
1189 	rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
1190 
1191 	cryptoerror(LOG_STDERR, "%s:", prefix);
1192 	if (rv1 == KMF_OK && plugin_errmsg) {
1193 		cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
1194 		    plugin_errmsg);
1195 		kmf_free_str(plugin_errmsg);
1196 	}
1197 
1198 	if (rv2 == KMF_OK && kmf_errmsg) {
1199 		cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
1200 		    kmf_errmsg);
1201 		kmf_free_str(kmf_errmsg);
1202 	}
1203 
1204 	if (rv1 != KMF_OK && rv2 != KMF_OK)
1205 		cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
1206 
1207 }
1208 
1209 static KMF_RETURN
1210 addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
1211 {
1212 	if (newoid != NULL && ekus != NULL) {
1213 		ekus->eku_count++;
1214 
1215 		ekus->critlist = realloc(ekus->critlist,
1216 		    ekus->eku_count * sizeof (int));
1217 		if (ekus->critlist != NULL)
1218 			ekus->critlist[ekus->eku_count-1] = critical;
1219 		else
1220 			return (KMF_ERR_MEMORY);
1221 
1222 		ekus->ekulist = realloc(
1223 		    ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
1224 		if (ekus->ekulist != NULL)
1225 			ekus->ekulist[ekus->eku_count-1] = *newoid;
1226 		else
1227 			return (KMF_ERR_MEMORY);
1228 	}
1229 	return (KMF_OK);
1230 }
1231 
1232 void
1233 free_eku_list(EKU_LIST *ekus)
1234 {
1235 	if (ekus != NULL && ekus->eku_count > 0) {
1236 		int i;
1237 		for (i = 0; i < ekus->eku_count; i++) {
1238 			kmf_free_data(&ekus->ekulist[i]);
1239 		}
1240 		free(ekus->ekulist);
1241 		free(ekus->critlist);
1242 		free(ekus);
1243 	}
1244 }
1245 
1246 static KMF_RETURN
1247 parse_ekus(char *ekustr, EKU_LIST *ekus)
1248 {
1249 	KMF_RETURN rv = KMF_OK;
1250 	KMF_OID *newoid;
1251 	int critical;
1252 
1253 	if (strncasecmp(ekustr, "critical:",
1254 	    strlen("critical:")) == 0) {
1255 		critical = TRUE;
1256 		ekustr += strlen("critical:");
1257 	} else {
1258 		critical = FALSE;
1259 	}
1260 	newoid = kmf_ekuname_to_oid(ekustr);
1261 	if (newoid != NULL) {
1262 		rv = addToEKUList(ekus, critical, newoid);
1263 		free(newoid);
1264 	} else {
1265 		rv = PK_ERR_USAGE;
1266 	}
1267 
1268 	return (rv);
1269 }
1270 
1271 KMF_RETURN
1272 verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
1273 {
1274 	KMF_RETURN rv = KMF_OK;
1275 	char *p;
1276 	EKU_LIST *ekus = NULL;
1277 
1278 	if (ekuliststr == NULL || strlen(ekuliststr) == 0)
1279 		return (0);
1280 
1281 	ekus = calloc(sizeof (EKU_LIST), 1);
1282 	if (ekus == NULL)
1283 		return (KMF_ERR_MEMORY);
1284 
1285 	/*
1286 	 * The list should be comma separated list of EKU Names.
1287 	 */
1288 	p = strtok(ekuliststr, ",");
1289 
1290 	/* If no tokens found, then maybe it's just a single EKU value */
1291 	if (p == NULL) {
1292 		rv = parse_ekus(ekuliststr, ekus);
1293 	}
1294 
1295 	while (p != NULL) {
1296 		rv = parse_ekus(p, ekus);
1297 
1298 		if (rv != KMF_OK)
1299 			break;
1300 		p = strtok(NULL, ",");
1301 	}
1302 
1303 	if (rv != KMF_OK)
1304 		free_eku_list(ekus);
1305 	else
1306 		*ekulist = ekus;
1307 
1308 	return (rv);
1309 }
1310 
1311 KMF_RETURN
1312 token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
1313 {
1314 	CK_TOKEN_INFO info;
1315 	CK_SLOT_ID slot;
1316 	CK_RV ckrv;
1317 	KMF_RETURN rv;
1318 
1319 	*auth = 0;
1320 	rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
1321 	if (rv != KMF_OK)
1322 		return (rv);
1323 
1324 	ckrv = C_GetTokenInfo(slot, &info);
1325 	if (ckrv != KMF_OK)
1326 		return (KMF_ERR_INTERNAL);
1327 
1328 	*auth = (info.flags & CKF_LOGIN_REQUIRED);
1329 
1330 	return (KMF_OK);
1331 }
1332 
1333 void
1334 show_ecc_curves()
1335 {
1336 	int i;
1337 
1338 	(void) printf(gettext("Supported ECC curve names:\n"));
1339 	for (i = 0; i < number_of_curves; i++) {
1340 		(void) printf("%s", oid_table[i].name);
1341 		if (i > 0 && ((i+1) % 5) == 0)
1342 			(void) printf("\n");
1343 		else if (i+1 < number_of_curves)
1344 			(void) printf(", ");
1345 	}
1346 	(void) printf("\n");
1347 }
1348 
1349 KMF_OID *
1350 ecc_name_to_oid(char *name)
1351 {
1352 	int i;
1353 	for (i = 0; i < number_of_oids; i++) {
1354 		if (strcasecmp(name, oid_table[i].name) == 0)
1355 			return ((KMF_OID *)oid_table[i].oid);
1356 	}
1357 	return (NULL);
1358 }
1359