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