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