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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This file implements the token object list operation for this tool.
30  * It loads the PKCS#11 modules, finds the object to list, lists it,
31  * and cleans up.  User must be logged into the token to list private
32  * objects.
33  */
34 
35 #include <stdio.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <cryptoutil.h>
39 #include <security/cryptoki.h>
40 #include "common.h"
41 
42 #include <kmfapi.h>
43 
44 static void
45 pk_show_certs(KMF_HANDLE_T kmfhandle, KMF_X509_DER_CERT *certs, int num_certs)
46 {
47 	int i;
48 	char *subject, *issuer, *serial, *id, *altname;
49 
50 	for (i = 0; i < num_certs; i++) {
51 		subject = NULL;
52 		issuer = NULL;
53 		serial = NULL;
54 		id = NULL;
55 		altname = NULL;
56 
57 		(void) fprintf(stdout,
58 			gettext("%d. (X.509 certificate)\n"), i + 1);
59 		if (certs[i].kmf_private.label != NULL)
60 			(void) fprintf(stdout, gettext("\t%s: %s\n"),
61 				(certs[i].kmf_private.keystore_type ==
62 				KMF_KEYSTORE_OPENSSL ?  "Filename" : "Label"),
63 				certs[i].kmf_private.label);
64 		if (KMF_GetCertIDString(&certs[i].certificate,
65 				&id) == KMF_OK)
66 			(void) fprintf(stdout, gettext("\tID: %s\n"), id);
67 		if (KMF_GetCertSubjectNameString(kmfhandle,
68 			&certs[i].certificate, &subject) == KMF_OK)
69 			(void) fprintf(stdout, gettext("\tSubject: %s\n"),
70 				subject);
71 		if (KMF_GetCertIssuerNameString(kmfhandle,
72 			&certs[i].certificate, &issuer) == KMF_OK)
73 			(void) fprintf(stdout, gettext("\tIssuer: %s\n"),
74 				issuer);
75 		if (KMF_GetCertSerialNumberString(kmfhandle,
76 			&certs[i].certificate, &serial) == KMF_OK)
77 			(void) fprintf(stdout, gettext("\tSerial: %s\n"),
78 				serial);
79 
80 		if (KMF_GetCertExtensionString(kmfhandle,
81 			&certs[i].certificate, KMF_X509_EXT_SUBJ_ALTNAME,
82 			&altname) == KMF_OK)  {
83 			(void) fprintf(stdout, gettext("\t%s\n"),
84 				altname);
85 		}
86 
87 		KMF_FreeString(subject);
88 		KMF_FreeString(issuer);
89 		KMF_FreeString(serial);
90 		KMF_FreeString(id);
91 		KMF_FreeString(altname);
92 		(void) fprintf(stdout, "\n");
93 	}
94 }
95 
96 static char *
97 describeKey(KMF_KEY_HANDLE *key)
98 {
99 	if (key->keyclass == KMF_ASYM_PUB) {
100 		if (key->keyalg == KMF_RSA)
101 			return (gettext("RSA public key"));
102 		if (key->keyalg == KMF_DSA)
103 			return (gettext("DSA public key"));
104 	}
105 	if (key->keyclass == KMF_ASYM_PRI) {
106 		if (key->keyalg == KMF_RSA)
107 			return ("RSA private key");
108 		if (key->keyalg == KMF_DSA)
109 			return ("DSA private key");
110 	}
111 	if (key->keyclass == KMF_SYMMETRIC) {
112 		switch (key->keyalg) {
113 			case KMF_AES:
114 				return (gettext("AES"));
115 				break;
116 			case KMF_RC4:
117 				return (gettext("ARCFOUR"));
118 				break;
119 			case KMF_DES:
120 				return (gettext("DES"));
121 				break;
122 			case KMF_DES3:
123 				return (gettext("Triple-DES"));
124 				break;
125 			default:
126 				return (gettext("symmetric"));
127 				break;
128 		}
129 	}
130 
131 	return (gettext("unrecognized key object"));
132 
133 }
134 
135 
136 static void
137 pk_show_keys(void *handle, KMF_KEY_HANDLE *keys, int numkeys)
138 {
139 	int i;
140 
141 	for (i = 0; i < numkeys; i++) {
142 		(void) fprintf(stdout, gettext("Key #%d - %s:  %s"),
143 			i+1, describeKey(&keys[i]),
144 			keys[i].keylabel ? keys[i].keylabel :
145 			gettext("No label"));
146 
147 		if (keys[i].keyclass == KMF_SYMMETRIC) {
148 			KMF_RETURN rv;
149 			KMF_RAW_SYM_KEY rkey;
150 
151 			rv = KMF_GetSymKeyValue(handle, &keys[i],
152 				&rkey);
153 			if (rv == KMF_OK) {
154 				(void) fprintf(stdout, " (%d bits)",
155 					rkey.keydata.len * 8);
156 				KMF_FreeRawSymKey(&rkey);
157 			}
158 		}
159 		(void) fprintf(stdout, "\n");
160 	}
161 }
162 
163 /*
164  * Generic routine used by all "list cert" operations to find
165  * all matching certificates.
166  */
167 static KMF_RETURN
168 pk_find_certs(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *params)
169 {
170 	KMF_RETURN rv = KMF_OK;
171 	KMF_X509_DER_CERT *certlist = NULL;
172 	uint32_t numcerts = 0;
173 
174 	numcerts = 0;
175 	rv = KMF_FindCert(kmfhandle, params, NULL, &numcerts);
176 	if (rv == KMF_OK && numcerts > 0) {
177 		(void) printf(gettext("Found %d certificates.\n"),
178 			numcerts);
179 		certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
180 				sizeof (KMF_X509_DER_CERT));
181 		if (certlist == NULL)
182 			return (KMF_ERR_MEMORY);
183 		(void) memset(certlist, 0, numcerts *
184 			sizeof (KMF_X509_DER_CERT));
185 
186 		rv = KMF_FindCert(kmfhandle, params, certlist, &numcerts);
187 		if (rv == KMF_OK) {
188 			int i;
189 			(void) pk_show_certs(kmfhandle, certlist,
190 				numcerts);
191 			for (i = 0; i < numcerts; i++)
192 				KMF_FreeKMFCert(kmfhandle, &certlist[i]);
193 		}
194 		free(certlist);
195 	}
196 	if (rv == KMF_ERR_CERT_NOT_FOUND &&
197 		params->kstype != KMF_KEYSTORE_OPENSSL)
198 		rv = KMF_OK;
199 
200 	return (rv);
201 }
202 
203 static KMF_RETURN
204 pk_list_keys(void *handle, KMF_FINDKEY_PARAMS *parms)
205 {
206 	KMF_RETURN rv;
207 	KMF_KEY_HANDLE *keys;
208 	uint32_t numkeys = 0;
209 
210 	numkeys = 0;
211 	rv = KMF_FindKey(handle, parms, NULL, &numkeys);
212 	if (rv == KMF_OK && numkeys > 0) {
213 		int i;
214 		(void) printf(gettext("Found %d keys.\n"), numkeys);
215 		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
216 				sizeof (KMF_KEY_HANDLE));
217 		if (keys == NULL)
218 			return (KMF_ERR_MEMORY);
219 		(void) memset(keys, 0, numkeys *
220 			sizeof (KMF_KEY_HANDLE));
221 
222 		rv = KMF_FindKey(handle, parms, keys, &numkeys);
223 		if (rv == KMF_OK)
224 			pk_show_keys(handle, keys, numkeys);
225 		for (i = 0; i < numkeys; i++)
226 			KMF_FreeKMFKey(handle, &keys[i]);
227 		free(keys);
228 	}
229 	if (rv == KMF_ERR_KEY_NOT_FOUND &&
230 		parms->kstype != KMF_KEYSTORE_OPENSSL)
231 		rv = KMF_OK;
232 	return (rv);
233 }
234 
235 static KMF_RETURN
236 list_pk11_objects(KMF_HANDLE_T kmfhandle, char *token, int oclass,
237 	char *objlabel, KMF_BIGINT *serial, char *issuer, char *subject,
238 	char *dir, char *filename, KMF_CREDENTIAL *tokencred,
239 	KMF_CERT_VALIDITY find_criteria_flag)
240 {
241 	KMF_RETURN rv;
242 	KMF_LISTCRL_PARAMS lcrlargs;
243 
244 	/*
245 	 * Symmetric keys and RSA/DSA private keys are always
246 	 * created with the "CKA_PRIVATE" field == TRUE, so
247 	 * make sure we search for them with it also set.
248 	 */
249 	if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
250 		oclass |= PK_PRIVATE_OBJ;
251 
252 	rv = select_token(kmfhandle, token,
253 		!(oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)));
254 
255 	if (rv != KMF_OK) {
256 		return (rv);
257 	}
258 
259 	if (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) {
260 		KMF_FINDKEY_PARAMS parms;
261 
262 		(void) memset(&parms, 0, sizeof (parms));
263 		parms.kstype = KMF_KEYSTORE_PK11TOKEN;
264 
265 		if (oclass & PK_PRIKEY_OBJ) {
266 			parms.keyclass = KMF_ASYM_PRI;
267 			parms.findLabel = objlabel;
268 			parms.cred = *tokencred;
269 			parms.pkcs11parms.private =
270 				((oclass & PK_PRIVATE_OBJ) > 0);
271 			parms.pkcs11parms.token = 1;
272 
273 			/* list asymmetric private keys */
274 			rv = pk_list_keys(kmfhandle, &parms);
275 		}
276 
277 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
278 			parms.keyclass = KMF_SYMMETRIC;
279 			parms.findLabel = objlabel;
280 			parms.cred = *tokencred;
281 			parms.format = KMF_FORMAT_RAWKEY;
282 			parms.pkcs11parms.private =
283 				((oclass & PK_PRIVATE_OBJ) > 0);
284 			parms.pkcs11parms.token = 1;
285 
286 			/* list symmetric keys */
287 			rv = pk_list_keys(kmfhandle, &parms);
288 		}
289 
290 		if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
291 			parms.keyclass = KMF_ASYM_PUB;
292 			parms.findLabel = objlabel;
293 			parms.pkcs11parms.private =
294 				((oclass & PK_PRIVATE_OBJ) > 0);
295 			parms.pkcs11parms.token = 1;
296 
297 			/* list asymmetric public keys (if any) */
298 			rv = pk_list_keys(kmfhandle, &parms);
299 		}
300 
301 		if (rv != KMF_OK)
302 			return (rv);
303 	}
304 
305 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
306 		KMF_FINDCERT_PARAMS parms;
307 
308 		(void) memset(&parms, 0, sizeof (parms));
309 		parms.kstype = KMF_KEYSTORE_PK11TOKEN;
310 		parms.certLabel = objlabel;
311 		parms.issuer = issuer;
312 		parms.subject = subject;
313 		parms.serial = serial;
314 		parms.pkcs11parms.private = FALSE;
315 		parms.find_cert_validity = find_criteria_flag;
316 
317 		rv = pk_find_certs(kmfhandle, &parms);
318 		if (rv != KMF_OK)
319 			return (rv);
320 	}
321 
322 	if (oclass & PK_CRL_OBJ) {
323 		char *crldata;
324 
325 		(void) memset(&lcrlargs, 0, sizeof (lcrlargs));
326 		lcrlargs.kstype = KMF_KEYSTORE_OPENSSL;
327 		lcrlargs.sslparms.dirpath = dir;
328 		lcrlargs.sslparms.crlfile = filename;
329 
330 		rv = KMF_ListCRL(kmfhandle, &lcrlargs, &crldata);
331 		if (rv == KMF_OK) {
332 			(void) printf("%s\n", crldata);
333 			free(crldata);
334 		}
335 	}
336 
337 	return (rv);
338 }
339 
340 static int
341 list_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
342 	char *dir, char *filename, KMF_BIGINT *serial,
343 	char *issuer, char *subject,
344 	KMF_CERT_VALIDITY find_criteria_flag)
345 {
346 	int rv;
347 	KMF_FINDCERT_PARAMS fcargs;
348 	KMF_FINDKEY_PARAMS fkargs;
349 	KMF_LISTCRL_PARAMS lcrlargs;
350 
351 	if (oclass & PK_KEY_OBJ) {
352 		(void) memset(&fkargs, 0, sizeof (fkargs));
353 		fkargs.kstype = KMF_KEYSTORE_OPENSSL;
354 		fkargs.sslparms.dirpath = dir;
355 		fkargs.sslparms.keyfile = filename;
356 		if (oclass & PK_PRIKEY_OBJ) {
357 			fkargs.keyclass = KMF_ASYM_PRI;
358 
359 			rv = pk_list_keys(kmfhandle, &fkargs);
360 		}
361 		if (rv == KMF_ERR_KEY_NOT_FOUND)
362 			rv = KMF_OK;
363 
364 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
365 			fkargs.keyclass = KMF_SYMMETRIC;
366 			fkargs.format = KMF_FORMAT_RAWKEY;
367 
368 			rv = pk_list_keys(kmfhandle, &fkargs);
369 		}
370 		if (rv == KMF_ERR_KEY_NOT_FOUND)
371 			rv = KMF_OK;
372 		if (rv != KMF_OK)
373 			return (rv);
374 	}
375 
376 	if (oclass & PK_CERT_OBJ) {
377 		(void) memset(&fcargs, 0, sizeof (fcargs));
378 		fcargs.kstype = KMF_KEYSTORE_OPENSSL;
379 		fcargs.certLabel = NULL;
380 		fcargs.issuer = issuer;
381 		fcargs.subject = subject;
382 		fcargs.serial = serial;
383 		fcargs.sslparms.dirpath = dir;
384 		fcargs.sslparms.certfile = filename;
385 		fcargs.find_cert_validity = find_criteria_flag;
386 
387 		rv = pk_find_certs(kmfhandle, &fcargs);
388 		if (rv != KMF_OK)
389 			return (rv);
390 	}
391 
392 	if (oclass & PK_CRL_OBJ) {
393 		char *crldata;
394 
395 		(void) memset(&lcrlargs, 0, sizeof (lcrlargs));
396 		lcrlargs.kstype = KMF_KEYSTORE_OPENSSL;
397 		lcrlargs.sslparms.dirpath = dir;
398 		lcrlargs.sslparms.crlfile = filename;
399 
400 		rv = KMF_ListCRL(kmfhandle, &lcrlargs, &crldata);
401 		if (rv == KMF_OK) {
402 			(void) printf("%s\n", crldata);
403 			free(crldata);
404 		}
405 	}
406 
407 	return (rv);
408 }
409 
410 static int
411 list_nss_objects(KMF_HANDLE_T kmfhandle,
412 	int oclass, char *token_spec, char *dir, char *prefix,
413 	char *nickname, KMF_BIGINT *serial, char *issuer, char *subject,
414 	KMF_CREDENTIAL *tokencred,
415 	KMF_CERT_VALIDITY find_criteria_flag)
416 {
417 	KMF_RETURN rv = KMF_OK;
418 	KMF_FINDKEY_PARAMS fkargs;
419 
420 	rv = configure_nss(kmfhandle, dir, prefix);
421 	if (rv != KMF_OK)
422 		return (rv);
423 
424 	if (oclass & PK_KEY_OBJ) {
425 		(void) memset(&fkargs, 0, sizeof (fkargs));
426 		fkargs.kstype = KMF_KEYSTORE_NSS;
427 		fkargs.findLabel = nickname;
428 		fkargs.cred = *tokencred;
429 		fkargs.nssparms.slotlabel = token_spec;
430 	}
431 
432 	if (oclass & PK_PRIKEY_OBJ) {
433 		fkargs.keyclass = KMF_ASYM_PRI;
434 		rv = pk_list_keys(kmfhandle, &fkargs);
435 	}
436 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
437 		fkargs.keyclass = KMF_SYMMETRIC;
438 		fkargs.format = KMF_FORMAT_RAWKEY;
439 		rv = pk_list_keys(kmfhandle, &fkargs);
440 	}
441 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
442 		fkargs.keyclass = KMF_ASYM_PUB;
443 		rv = pk_list_keys(kmfhandle, &fkargs);
444 	}
445 
446 	/* If searching for public objects or certificates, find certs now */
447 	if (rv == KMF_OK && (oclass & PK_CERT_OBJ)) {
448 		KMF_FINDCERT_PARAMS fcargs;
449 
450 		(void) memset(&fcargs, 0, sizeof (fcargs));
451 		fcargs.kstype = KMF_KEYSTORE_NSS;
452 		fcargs.certLabel = nickname;
453 		fcargs.issuer = issuer;
454 		fcargs.subject = subject;
455 		fcargs.serial = serial;
456 		fcargs.nssparms.slotlabel = token_spec;
457 		fcargs.find_cert_validity = find_criteria_flag;
458 
459 		rv = pk_find_certs(kmfhandle, &fcargs);
460 	}
461 
462 	if (rv == KMF_OK && (oclass & PK_CRL_OBJ)) {
463 		int numcrls;
464 		KMF_FINDCRL_PARAMS fcrlargs;
465 
466 		(void) memset(&fcrlargs, 0, sizeof (fcrlargs));
467 		fcrlargs.kstype = KMF_KEYSTORE_NSS;
468 		fcrlargs.nssparms.slotlabel = token_spec;
469 
470 		rv = KMF_FindCRL(kmfhandle, &fcrlargs, NULL, &numcrls);
471 		if (rv == KMF_OK) {
472 			char **p;
473 			if (numcrls == 0) {
474 				(void) printf(gettext("No CRLs found in "
475 					"NSS keystore.\n"));
476 
477 				return (KMF_OK);
478 			}
479 			p = malloc(numcrls * sizeof (char *));
480 			if (p == NULL) {
481 				return (KMF_ERR_MEMORY);
482 			}
483 			(void) memset(p, 0, numcrls * sizeof (char *));
484 			rv = KMF_FindCRL(kmfhandle, &fcrlargs,
485 				p, &numcrls);
486 			if (rv == KMF_OK) {
487 				int i;
488 				for (i = 0; i < numcrls; i++) {
489 					(void) printf("%d. Name = %s\n",
490 						i + 1, p[i]);
491 					free(p[i]);
492 				}
493 			}
494 			free(p);
495 		}
496 	}
497 	return (rv);
498 }
499 
500 /*
501  * List token object.
502  */
503 int
504 pk_list(int argc, char *argv[])
505 {
506 	int			opt;
507 	extern int		optind_av;
508 	extern char		*optarg_av;
509 	char			*token_spec = NULL;
510 	char			*subject = NULL;
511 	char			*issuer = NULL;
512 	char			*dir = NULL;
513 	char			*prefix = NULL;
514 	char			*filename = NULL;
515 	char			*serstr = NULL;
516 	KMF_BIGINT		serial = { NULL, 0 };
517 
518 	char			*list_label = NULL;
519 	int			oclass = 0;
520 	KMF_KEYSTORE_TYPE	kstype = 0;
521 	KMF_RETURN		rv = KMF_OK;
522 	KMF_HANDLE_T		kmfhandle = NULL;
523 	char			*find_criteria = NULL;
524 	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
525 	KMF_CREDENTIAL		tokencred = {NULL, 0};
526 
527 	/* Parse command line options.  Do NOT i18n/l10n. */
528 	while ((opt = getopt_av(argc, argv,
529 		"k:(keystore)t:(objtype)T:(token)d:(dir)"
530 		"p:(prefix)n:(nickname)S:(serial)s:(subject)"
531 		"c:(criteria)"
532 		"i:(issuer)l:(label)f:(infile)")) != EOF) {
533 		if (EMPTYSTRING(optarg_av))
534 			return (PK_ERR_USAGE);
535 		switch (opt) {
536 			case 'k':
537 				if (kstype != 0)
538 					return (PK_ERR_USAGE);
539 				kstype = KS2Int(optarg_av);
540 				if (kstype == 0)
541 					return (PK_ERR_USAGE);
542 				break;
543 			case 't':
544 				if (oclass != 0)
545 					return (PK_ERR_USAGE);
546 				oclass = OT2Int(optarg_av);
547 				if (oclass == -1)
548 					return (PK_ERR_USAGE);
549 				break;
550 			case 's':
551 				if (subject)
552 					return (PK_ERR_USAGE);
553 				subject = optarg_av;
554 				break;
555 			case 'i':
556 				if (issuer)
557 					return (PK_ERR_USAGE);
558 				issuer = optarg_av;
559 				break;
560 			case 'd':
561 				if (dir)
562 					return (PK_ERR_USAGE);
563 				dir = optarg_av;
564 				break;
565 			case 'p':
566 				if (prefix)
567 					return (PK_ERR_USAGE);
568 				prefix = optarg_av;
569 				break;
570 			case 'S':
571 				serstr = optarg_av;
572 				break;
573 			case 'f':
574 				if (filename)
575 					return (PK_ERR_USAGE);
576 				filename = optarg_av;
577 				break;
578 			case 'T':	/* token specifier */
579 				if (token_spec)
580 					return (PK_ERR_USAGE);
581 				token_spec = optarg_av;
582 				break;
583 			case 'n':
584 			case 'l':	/* object with specific label */
585 				if (list_label)
586 					return (PK_ERR_USAGE);
587 				list_label = optarg_av;
588 				break;
589 			case 'c':
590 				find_criteria = optarg_av;
591 				if (!strcasecmp(find_criteria, "valid"))
592 					find_criteria_flag =
593 					    KMF_NONEXPIRED_CERTS;
594 				else if (!strcasecmp(find_criteria, "expired"))
595 					find_criteria_flag = KMF_EXPIRED_CERTS;
596 				else if (!strcasecmp(find_criteria, "both"))
597 					find_criteria_flag = KMF_ALL_CERTS;
598 				else
599 					return (PK_ERR_USAGE);
600 				break;
601 			default:
602 				return (PK_ERR_USAGE);
603 		}
604 	}
605 	/* No additional args allowed. */
606 	argc -= optind_av;
607 	argv += optind_av;
608 	if (argc)
609 		return (PK_ERR_USAGE);
610 
611 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
612 		/* Error message ? */
613 		return (rv);
614 	}
615 
616 	/* Assume keystore = PKCS#11 if not specified. */
617 	if (kstype == 0)
618 		kstype = KMF_KEYSTORE_PK11TOKEN;
619 
620 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
621 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
622 		kstype != KMF_KEYSTORE_PK11TOKEN) {
623 
624 		(void) fprintf(stderr, gettext("The objtype parameter "
625 			"is only relevant if keystore=pkcs11\n"));
626 		return (PK_ERR_USAGE);
627 	}
628 
629 	/* If no object class specified, list certificate objects. */
630 	if (oclass == 0)
631 		oclass = PK_CERT_OBJ;
632 
633 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
634 		token_spec = PK_DEFAULT_PK11TOKEN;
635 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
636 		token_spec = DEFAULT_NSS_TOKEN;
637 	}
638 
639 	if (serstr != NULL) {
640 		uchar_t *bytes = NULL;
641 		size_t bytelen;
642 
643 		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
644 		if (rv != KMF_OK || bytes == NULL) {
645 			(void) fprintf(stderr, gettext("serial number "
646 				"must be specified as a hex number "
647 				"(ex: 0x0102030405ffeeddee)\n"));
648 			return (PK_ERR_USAGE);
649 		}
650 		serial.val = bytes;
651 		serial.len = bytelen;
652 	}
653 
654 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
655 		kstype == KMF_KEYSTORE_NSS) &&
656 		(oclass & (PK_PRIKEY_OBJ | PK_PRIVATE_OBJ))) {
657 
658 		(void) get_token_password(kstype, token_spec,
659 			&tokencred);
660 	}
661 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
662 		rv = list_pk11_objects(kmfhandle, token_spec,
663 			oclass, list_label, &serial,
664 			issuer, subject, dir, filename,
665 			&tokencred, find_criteria_flag);
666 
667 	} else if (kstype == KMF_KEYSTORE_NSS) {
668 		if (dir == NULL)
669 			dir = PK_DEFAULT_DIRECTORY;
670 		rv = list_nss_objects(kmfhandle,
671 			oclass, token_spec, dir, prefix,
672 			list_label, &serial, issuer, subject,
673 			&tokencred, find_criteria_flag);
674 
675 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
676 
677 		rv = list_file_objects(kmfhandle,
678 			oclass, dir, filename,
679 			&serial, issuer, subject, find_criteria_flag);
680 	}
681 
682 	if (rv != KMF_OK) {
683 		display_error(kmfhandle, rv,
684 			gettext("Error listing objects"));
685 	}
686 
687 	if (serial.val != NULL)
688 		free(serial.val);
689 
690 	if (tokencred.cred != NULL)
691 		free(tokencred.cred);
692 
693 	(void) KMF_Finalize(kmfhandle);
694 	return (rv);
695 }
696