xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/list.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2012 Milan Jurik. All rights reserved.
24  */
25 
26 /*
27  * This file implements the token object list operation for this tool.
28  * It loads the PKCS#11 modules, finds the object to list, lists it,
29  * and cleans up.  User must be logged into the token to list private
30  * objects.
31  */
32 
33 #include <stdio.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <cryptoutil.h>
37 #include <security/cryptoki.h>
38 #include "common.h"
39 
40 #include <kmfapi.h>
41 
42 static void
43 pk_show_certs(KMF_HANDLE_T kmfhandle, KMF_X509_DER_CERT *certs, int num_certs)
44 {
45 	int i;
46 	char *subject, *issuer, *serial, *id, *altname;
47 	char *start, *end, *keyusage, *extkeyusage;
48 
49 	for (i = 0; i < num_certs; i++) {
50 		subject = NULL;
51 		issuer = NULL;
52 		serial = NULL;
53 		id = NULL;
54 		altname = NULL;
55 		start = end = NULL;
56 		keyusage = extkeyusage = NULL;
57 
58 		(void) fprintf(stdout,
59 		    gettext("%d. (X.509 certificate)\n"), i + 1);
60 		if (certs[i].kmf_private.label != NULL)
61 			(void) fprintf(stdout, gettext("\t%s: %s\n"),
62 			    (certs[i].kmf_private.keystore_type ==
63 			    KMF_KEYSTORE_OPENSSL ?  "Filename" : "Label"),
64 			    certs[i].kmf_private.label);
65 		if (kmf_get_cert_id_str(&certs[i].certificate,
66 		    &id) == KMF_OK)
67 			(void) fprintf(stdout, gettext("\tID: %s\n"), id);
68 		if (kmf_get_cert_subject_str(kmfhandle,
69 		    &certs[i].certificate, &subject) == KMF_OK)
70 			(void) fprintf(stdout, gettext("\tSubject: %s\n"),
71 			    subject);
72 		if (kmf_get_cert_issuer_str(kmfhandle,
73 		    &certs[i].certificate, &issuer) == KMF_OK)
74 			(void) fprintf(stdout, gettext("\tIssuer: %s\n"),
75 			    issuer);
76 		if (kmf_get_cert_start_date_str(kmfhandle,
77 		    &certs[i].certificate, &start) == KMF_OK)
78 			(void) fprintf(stdout, gettext("\tNot Before: %s\n"),
79 			    start);
80 		if (kmf_get_cert_end_date_str(kmfhandle,
81 		    &certs[i].certificate, &end) == KMF_OK)
82 			(void) fprintf(stdout, gettext("\tNot After: %s\n"),
83 			    end);
84 		if (kmf_get_cert_serial_str(kmfhandle,
85 		    &certs[i].certificate, &serial) == KMF_OK)
86 			(void) fprintf(stdout, gettext("\tSerial: %s\n"),
87 			    serial);
88 		if (kmf_get_cert_extn_str(kmfhandle,
89 		    &certs[i].certificate, KMF_X509_EXT_SUBJ_ALTNAME,
90 		    &altname) == KMF_OK)  {
91 			(void) fprintf(stdout, gettext("\t%s\n"),
92 			    altname);
93 		}
94 		if (kmf_get_cert_extn_str(kmfhandle,
95 		    &certs[i].certificate, KMF_X509_EXT_KEY_USAGE,
96 		    &keyusage) == KMF_OK)  {
97 			(void) fprintf(stdout, gettext("\t%s\n"),
98 			    keyusage);
99 		}
100 		if (kmf_get_cert_extn_str(kmfhandle,
101 		    &certs[i].certificate, KMF_X509_EXT_EXT_KEY_USAGE,
102 		    &extkeyusage) == KMF_OK)  {
103 			(void) fprintf(stdout, gettext("\t%s\n"),
104 			    extkeyusage);
105 		}
106 		kmf_free_str(subject);
107 		kmf_free_str(issuer);
108 		kmf_free_str(serial);
109 		kmf_free_str(id);
110 		kmf_free_str(altname);
111 		kmf_free_str(keyusage);
112 		kmf_free_str(extkeyusage);
113 		kmf_free_str(start);
114 		kmf_free_str(end);
115 		(void) fprintf(stdout, "\n");
116 	}
117 }
118 
119 static char *
120 describeKey(KMF_KEY_HANDLE *key)
121 {
122 	if (key->keyclass == KMF_ASYM_PUB) {
123 		if (key->keyalg == KMF_RSA)
124 			return (gettext("RSA public key"));
125 		if (key->keyalg == KMF_DSA)
126 			return (gettext("DSA public key"));
127 		if (key->keyalg == KMF_ECDSA)
128 			return (gettext("ECDSA public key"));
129 	}
130 	if (key->keyclass == KMF_ASYM_PRI) {
131 		if (key->keyalg == KMF_RSA)
132 			return (gettext("RSA private key"));
133 		if (key->keyalg == KMF_DSA)
134 			return (gettext("DSA private key"));
135 		if (key->keyalg == KMF_ECDSA)
136 			return (gettext("ECDSA private key"));
137 	}
138 	if (key->keyclass == KMF_SYMMETRIC) {
139 		switch (key->keyalg) {
140 			case KMF_AES:
141 				return (gettext("AES"));
142 			case KMF_RC4:
143 				return (gettext("ARCFOUR"));
144 			case KMF_DES:
145 				return (gettext("DES"));
146 			case KMF_DES3:
147 				return (gettext("Triple-DES"));
148 			default:
149 				return (gettext("symmetric"));
150 		}
151 	}
152 
153 	return (gettext("unrecognized key object"));
154 
155 }
156 
157 
158 static void
159 pk_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"),
165 		    i+1, describeKey(&keys[i]),
166 		    keys[i].keylabel ? keys[i].keylabel :
167 		    gettext("No label"));
168 
169 		if (keys[i].keyclass == KMF_SYMMETRIC) {
170 			KMF_RETURN rv;
171 			KMF_RAW_SYM_KEY rkey;
172 
173 			(void) memset(&rkey, 0, sizeof (rkey));
174 			rv = kmf_get_sym_key_value(handle, &keys[i],
175 			    &rkey);
176 			if (rv == KMF_OK) {
177 				(void) fprintf(stdout, " (%d bits)",
178 				    rkey.keydata.len * 8);
179 				kmf_free_bigint(&rkey.keydata);
180 			} else if (keys[i].kstype == KMF_KEYSTORE_PK11TOKEN) {
181 				if (rv == KMF_ERR_SENSITIVE_KEY) {
182 					(void) fprintf(stdout, " (sensitive)");
183 				} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
184 					(void) fprintf(stdout,
185 					    " (non-extractable)");
186 				} else {
187 					char *err = NULL;
188 					if (kmf_get_kmf_error_str(rv, &err) ==
189 					    KMF_OK)
190 						(void) fprintf(stdout,
191 						    " (error: %s)", err);
192 					if (err != NULL)
193 						free(err);
194 				}
195 			}
196 		}
197 		(void) fprintf(stdout, "\n");
198 	}
199 }
200 
201 /*
202  * Generic routine used by all "list cert" operations to find
203  * all matching certificates.
204  */
205 static KMF_RETURN
206 pk_find_certs(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist, int numattr)
207 {
208 	KMF_RETURN rv = KMF_OK;
209 	KMF_X509_DER_CERT *certlist = NULL;
210 	uint32_t numcerts = 0;
211 	KMF_KEYSTORE_TYPE kstype;
212 
213 	rv = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
214 	    &kstype, NULL);
215 	if (rv != KMF_OK)
216 		return (rv);
217 
218 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
219 	    &numcerts, sizeof (uint32_t));
220 	numattr++;
221 
222 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
223 	if (rv == KMF_OK && numcerts > 0) {
224 		(void) printf(gettext("Found %d certificates.\n"),
225 		    numcerts);
226 		certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
227 		    sizeof (KMF_X509_DER_CERT));
228 		if (certlist == NULL)
229 			return (KMF_ERR_MEMORY);
230 		(void) memset(certlist, 0, numcerts *
231 		    sizeof (KMF_X509_DER_CERT));
232 
233 		kmf_set_attr_at_index(attrlist, numattr,
234 		    KMF_X509_DER_CERT_ATTR, certlist,
235 		    sizeof (KMF_X509_DER_CERT));
236 		numattr++;
237 
238 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
239 		if (rv == KMF_OK) {
240 			int i;
241 			(void) pk_show_certs(kmfhandle, certlist,
242 			    numcerts);
243 			for (i = 0; i < numcerts; i++)
244 				kmf_free_kmf_cert(kmfhandle, &certlist[i]);
245 		}
246 		free(certlist);
247 	}
248 	if (rv == KMF_ERR_CERT_NOT_FOUND &&
249 	    kstype != KMF_KEYSTORE_OPENSSL)
250 		rv = KMF_OK;
251 
252 	return (rv);
253 }
254 
255 static KMF_RETURN
256 pk_list_keys(void *handle, KMF_ATTRIBUTE *attrlist, int numattr, char *label)
257 {
258 	KMF_RETURN rv;
259 	KMF_KEY_HANDLE *keys;
260 	uint32_t numkeys = 0;
261 	KMF_KEYSTORE_TYPE kstype;
262 
263 	rv = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, numattr,
264 	    &kstype, NULL);
265 	if (rv != KMF_OK)
266 		return (rv);
267 
268 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
269 	    &numkeys, sizeof (uint32_t));
270 	numattr++;
271 
272 	rv = kmf_find_key(handle, numattr, attrlist);
273 	if (rv == KMF_OK && numkeys > 0) {
274 		int i;
275 		(void) printf(gettext("Found %d %s keys.\n"),
276 		    numkeys, label);
277 		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
278 		    sizeof (KMF_KEY_HANDLE));
279 		if (keys == NULL)
280 			return (KMF_ERR_MEMORY);
281 		(void) memset(keys, 0, numkeys *
282 		    sizeof (KMF_KEY_HANDLE));
283 
284 		kmf_set_attr_at_index(attrlist, numattr,
285 		    KMF_KEY_HANDLE_ATTR,
286 		    keys, sizeof (KMF_KEY_HANDLE));
287 		numattr++;
288 
289 		rv = kmf_find_key(handle, numattr, attrlist);
290 		if (rv == KMF_OK)
291 			pk_show_keys(handle, keys, numkeys);
292 		for (i = 0; i < numkeys; i++)
293 			kmf_free_kmf_key(handle, &keys[i]);
294 		free(keys);
295 	}
296 	if (rv == KMF_ERR_KEY_NOT_FOUND &&
297 	    kstype != KMF_KEYSTORE_OPENSSL)
298 		rv = KMF_OK;
299 	return (rv);
300 }
301 
302 static KMF_RETURN
303 list_pk11_objects(KMF_HANDLE_T kmfhandle, char *token, int oclass,
304 	char *objlabel, KMF_BIGINT *serial, char *issuer, char *subject,
305 	char *dir, char *filename, KMF_CREDENTIAL *tokencred,
306 	KMF_CERT_VALIDITY find_criteria_flag)
307 {
308 	KMF_RETURN rv;
309 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
310 	int numattr = 0;
311 	KMF_ATTRIBUTE attrlist[18];
312 	boolean_t token_bool = B_TRUE;
313 	boolean_t private = B_FALSE;
314 	KMF_KEY_CLASS keyclass;
315 	KMF_ENCODE_FORMAT format;
316 	int auth = 0;
317 	KMF_CREDENTIAL cred = { NULL, 0 };
318 
319 	/*
320 	 * Symmetric keys and RSA/DSA/ECDSA private keys are always
321 	 * created with the "CKA_PRIVATE" field == TRUE, so
322 	 * make sure we search for them with it also set.
323 	 */
324 	if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
325 		oclass |= PK_PRIVATE_OBJ;
326 
327 	rv = select_token(kmfhandle, token,
328 	    !(oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)));
329 
330 	if (rv != KMF_OK) {
331 		return (rv);
332 	}
333 
334 	rv = token_auth_needed(kmfhandle, token, &auth);
335 	if (rv != KMF_OK)
336 		return (rv);
337 
338 	if (tokencred != NULL)
339 		cred = *tokencred;
340 
341 	if (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) {
342 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
343 		    &kstype, sizeof (kstype));
344 		numattr++;
345 
346 		if (objlabel != NULL) {
347 			kmf_set_attr_at_index(attrlist, numattr,
348 			    KMF_KEYLABEL_ATTR, objlabel,
349 			    strlen(objlabel));
350 			numattr++;
351 		}
352 
353 		private = ((oclass & PK_PRIVATE_OBJ) > 0);
354 
355 		kmf_set_attr_at_index(attrlist, numattr,
356 		    KMF_PRIVATE_BOOL_ATTR, &private,
357 		    sizeof (private));
358 		numattr++;
359 
360 		kmf_set_attr_at_index(attrlist, numattr,
361 		    KMF_TOKEN_BOOL_ATTR, &token_bool,
362 		    sizeof (token_bool));
363 		numattr++;
364 
365 		if (oclass & PK_PRIKEY_OBJ) {
366 			int num = numattr;
367 
368 			keyclass = KMF_ASYM_PRI;
369 			kmf_set_attr_at_index(attrlist, num,
370 			    KMF_KEYCLASS_ATTR, &keyclass,
371 			    sizeof (keyclass));
372 			num++;
373 
374 			if (tokencred != NULL &&
375 			    tokencred->credlen > 0) {
376 				kmf_set_attr_at_index(attrlist, num,
377 				    KMF_CREDENTIAL_ATTR, tokencred,
378 				    sizeof (KMF_CREDENTIAL));
379 				num++;
380 			}
381 
382 			/* list asymmetric private keys */
383 			rv = pk_list_keys(kmfhandle, attrlist, num,
384 			    "asymmetric private");
385 		}
386 
387 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
388 			int num = numattr;
389 
390 			keyclass = KMF_SYMMETRIC;
391 			kmf_set_attr_at_index(attrlist, num,
392 			    KMF_KEYCLASS_ATTR, &keyclass,
393 			    sizeof (keyclass));
394 			num++;
395 
396 			if (tokencred != NULL &&
397 			    tokencred->credlen > 0) {
398 				kmf_set_attr_at_index(attrlist, num,
399 				    KMF_CREDENTIAL_ATTR, tokencred,
400 				    sizeof (KMF_CREDENTIAL));
401 				num++;
402 			}
403 
404 			format = KMF_FORMAT_RAWKEY;
405 			kmf_set_attr_at_index(attrlist, num,
406 			    KMF_ENCODE_FORMAT_ATTR, &format,
407 			    sizeof (format));
408 			num++;
409 
410 			/* list symmetric keys */
411 			rv = pk_list_keys(kmfhandle, attrlist, num,
412 			    "symmetric");
413 		}
414 
415 		if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
416 			int num = numattr;
417 
418 			if (auth > 0 && (tokencred == NULL ||
419 			    tokencred->cred == NULL) &&
420 			    (cred.cred == NULL)) {
421 				(void) get_token_password(kstype, token, &cred);
422 				kmf_set_attr_at_index(attrlist, num,
423 				    KMF_CREDENTIAL_ATTR,
424 				    &cred, sizeof (KMF_CREDENTIAL));
425 				num++;
426 			}
427 
428 			private = B_FALSE;
429 			keyclass = KMF_ASYM_PUB;
430 			kmf_set_attr_at_index(attrlist, num,
431 			    KMF_KEYCLASS_ATTR, &keyclass,
432 			    sizeof (keyclass));
433 			num++;
434 
435 			/* list asymmetric public keys (if any) */
436 			rv = pk_list_keys(kmfhandle, attrlist, num,
437 			    "asymmetric public");
438 		}
439 
440 		if (rv != KMF_OK)
441 			return (rv);
442 	}
443 
444 	numattr = 0;
445 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
446 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
447 		    &kstype, sizeof (kstype));
448 
449 		numattr++;
450 		if (auth > 0 && (cred.cred == NULL)) {
451 			(void) get_token_password(kstype, token, &cred);
452 		}
453 
454 		if (cred.cred != NULL) {
455 			kmf_set_attr_at_index(attrlist, numattr,
456 			    KMF_CREDENTIAL_ATTR,
457 			    &cred, sizeof (KMF_CREDENTIAL));
458 			numattr++;
459 		}
460 
461 		if (objlabel != NULL) {
462 			kmf_set_attr_at_index(attrlist, numattr,
463 			    KMF_CERT_LABEL_ATTR, objlabel,
464 			    strlen(objlabel));
465 			numattr++;
466 		}
467 
468 		if (issuer != NULL) {
469 			kmf_set_attr_at_index(attrlist, numattr,
470 			    KMF_ISSUER_NAME_ATTR, issuer,
471 			    strlen(issuer));
472 			numattr++;
473 		}
474 
475 		if (subject != NULL) {
476 			kmf_set_attr_at_index(attrlist, numattr,
477 			    KMF_SUBJECT_NAME_ATTR, subject,
478 			    strlen(subject));
479 			numattr++;
480 		}
481 
482 		if (serial != NULL && serial->val != NULL) {
483 			kmf_set_attr_at_index(attrlist, numattr,
484 			    KMF_BIGINT_ATTR, serial,
485 			    sizeof (KMF_BIGINT));
486 			numattr++;
487 		}
488 
489 		kmf_set_attr_at_index(attrlist, numattr,
490 		    KMF_PRIVATE_BOOL_ATTR, &private,
491 		    sizeof (private));
492 		numattr++;
493 
494 		kmf_set_attr_at_index(attrlist, numattr,
495 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
496 		    sizeof (KMF_CERT_VALIDITY));
497 		numattr++;
498 
499 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
500 		if (rv != KMF_OK)
501 			return (rv);
502 	}
503 
504 	numattr = 0;
505 	kstype = KMF_KEYSTORE_OPENSSL; /* CRL is file-based */
506 	if (oclass & PK_CRL_OBJ) {
507 		char *crldata = NULL;
508 
509 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
510 		    &kstype, sizeof (kstype));
511 		numattr++;
512 
513 		if (dir != NULL) {
514 			kmf_set_attr_at_index(attrlist, numattr,
515 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
516 			numattr++;
517 		}
518 		if (filename != NULL) {
519 			kmf_set_attr_at_index(attrlist, numattr,
520 			    KMF_CRL_FILENAME_ATTR,
521 			    filename, strlen(filename));
522 			numattr++;
523 		}
524 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_DATA_ATTR,
525 		    &crldata, sizeof (char *));
526 		numattr++;
527 
528 		rv = kmf_list_crl(kmfhandle, numattr, attrlist);
529 		if (rv == KMF_OK && crldata != NULL) {
530 			(void) printf("%s\n", crldata);
531 			free(crldata);
532 		}
533 	}
534 
535 	return (rv);
536 }
537 
538 static int
539 list_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
540 	char *dir, char *filename, KMF_BIGINT *serial,
541 	char *issuer, char *subject,
542 	KMF_CERT_VALIDITY find_criteria_flag)
543 {
544 	KMF_RETURN rv = KMF_OK;
545 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
546 	int numattr = 0;
547 	KMF_ATTRIBUTE attrlist[16];
548 	KMF_KEY_CLASS keyclass;
549 	KMF_ENCODE_FORMAT format;
550 	char *defaultdir = ".";
551 
552 	if (oclass & PK_KEY_OBJ) {
553 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
554 		    &kstype, sizeof (kstype));
555 		numattr++;
556 
557 		if (dir == NULL && filename == NULL)
558 			dir = defaultdir;
559 
560 		if (dir != NULL) {
561 			kmf_set_attr_at_index(attrlist, numattr,
562 			    KMF_DIRPATH_ATTR, dir,
563 			    strlen(dir));
564 			numattr++;
565 		}
566 
567 		if (filename != NULL) {
568 			kmf_set_attr_at_index(attrlist, numattr,
569 			    KMF_KEY_FILENAME_ATTR, filename,
570 			    strlen(filename));
571 			numattr++;
572 		}
573 
574 		if (oclass & PK_PRIKEY_OBJ) {
575 			int num = numattr;
576 
577 			keyclass = KMF_ASYM_PRI;
578 			kmf_set_attr_at_index(attrlist, num,
579 			    KMF_KEYCLASS_ATTR, &keyclass,
580 			    sizeof (keyclass));
581 			num++;
582 
583 			/* list asymmetric private keys */
584 			rv = pk_list_keys(kmfhandle, attrlist, num,
585 			    "asymmetric private");
586 		}
587 		if (rv == KMF_ERR_KEY_NOT_FOUND)
588 			rv = KMF_OK;
589 
590 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
591 			int num = numattr;
592 
593 			keyclass = KMF_SYMMETRIC;
594 			kmf_set_attr_at_index(attrlist, num,
595 			    KMF_KEYCLASS_ATTR, &keyclass,
596 			    sizeof (keyclass));
597 			num++;
598 
599 			format = KMF_FORMAT_RAWKEY;
600 			kmf_set_attr_at_index(attrlist, num,
601 			    KMF_ENCODE_FORMAT_ATTR, &format,
602 			    sizeof (format));
603 			num++;
604 
605 			/* list symmetric keys */
606 			rv = pk_list_keys(kmfhandle, attrlist, num,
607 			    "symmetric");
608 		}
609 		if (rv == KMF_ERR_KEY_NOT_FOUND)
610 			rv = KMF_OK;
611 		if (rv != KMF_OK)
612 			return (rv);
613 	}
614 
615 	numattr = 0;
616 	if (oclass & PK_CERT_OBJ) {
617 		kmf_set_attr_at_index(attrlist, numattr,
618 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
619 		    sizeof (kstype));
620 		numattr++;
621 
622 		if (issuer != NULL) {
623 			kmf_set_attr_at_index(attrlist, numattr,
624 			    KMF_ISSUER_NAME_ATTR, issuer,
625 			    strlen(issuer));
626 			numattr++;
627 		}
628 
629 		if (subject != NULL) {
630 			kmf_set_attr_at_index(attrlist, numattr,
631 			    KMF_SUBJECT_NAME_ATTR, subject,
632 			    strlen(subject));
633 			numattr++;
634 		}
635 
636 		if (serial != NULL && serial->val != NULL) {
637 			kmf_set_attr_at_index(attrlist, numattr,
638 			    KMF_BIGINT_ATTR, serial,
639 			    sizeof (KMF_BIGINT));
640 			numattr++;
641 		}
642 
643 		if (filename != NULL) {
644 			kmf_set_attr_at_index(attrlist, numattr,
645 			    KMF_CERT_FILENAME_ATTR, filename,
646 			    strlen(filename));
647 			numattr++;
648 		}
649 
650 		if (dir != NULL) {
651 			kmf_set_attr_at_index(attrlist, numattr,
652 			    KMF_DIRPATH_ATTR, dir,
653 			    strlen(dir));
654 			numattr++;
655 		}
656 
657 		kmf_set_attr_at_index(attrlist, numattr,
658 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
659 		    sizeof (KMF_CERT_VALIDITY));
660 		numattr++;
661 
662 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
663 		if (rv != KMF_OK)
664 			return (rv);
665 	}
666 
667 	numattr = 0;
668 	if (oclass & PK_CRL_OBJ) {
669 		char *crldata = NULL;
670 
671 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
672 		    &kstype, sizeof (kstype));
673 		numattr++;
674 
675 		if (dir != NULL) {
676 			kmf_set_attr_at_index(attrlist, numattr,
677 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
678 			numattr++;
679 		}
680 		if (filename != NULL) {
681 			kmf_set_attr_at_index(attrlist, numattr,
682 			    KMF_CRL_FILENAME_ATTR,
683 			    filename, strlen(filename));
684 			numattr++;
685 		}
686 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_DATA_ATTR,
687 		    &crldata, sizeof (char *));
688 		numattr++;
689 
690 		rv = kmf_list_crl(kmfhandle, numattr, attrlist);
691 		if (rv == KMF_OK && crldata != NULL) {
692 			(void) printf("%s\n", crldata);
693 			free(crldata);
694 		}
695 	}
696 
697 	return (rv);
698 }
699 
700 static int
701 list_nss_objects(KMF_HANDLE_T kmfhandle,
702 	int oclass, char *token_spec, char *dir, char *prefix,
703 	char *nickname, KMF_BIGINT *serial, char *issuer, char *subject,
704 	KMF_CREDENTIAL *tokencred,
705 	KMF_CERT_VALIDITY find_criteria_flag)
706 {
707 	KMF_RETURN rv = KMF_OK;
708 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
709 	int numattr = 0;
710 	KMF_ATTRIBUTE attrlist[16];
711 	KMF_KEY_CLASS keyclass;
712 	KMF_ENCODE_FORMAT format;
713 
714 	rv = configure_nss(kmfhandle, dir, prefix);
715 	if (rv != KMF_OK)
716 		return (rv);
717 
718 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
719 	    &kstype, sizeof (kstype));
720 	numattr++;
721 
722 	if (oclass & PK_KEY_OBJ) {
723 		if (tokencred != NULL && tokencred->credlen > 0) {
724 			kmf_set_attr_at_index(attrlist, numattr,
725 			    KMF_CREDENTIAL_ATTR, tokencred,
726 			    sizeof (KMF_CREDENTIAL));
727 			numattr++;
728 		}
729 
730 		if (token_spec && strlen(token_spec)) {
731 			kmf_set_attr_at_index(attrlist, numattr,
732 			    KMF_TOKEN_LABEL_ATTR, token_spec,
733 			    strlen(token_spec));
734 			numattr++;
735 		}
736 
737 		if (nickname != NULL) {
738 			kmf_set_attr_at_index(attrlist, numattr,
739 			    KMF_KEYLABEL_ATTR, nickname,
740 			    strlen(nickname));
741 			numattr++;
742 		}
743 	}
744 
745 	if (oclass & PK_PRIKEY_OBJ) {
746 		int num = numattr;
747 
748 		keyclass = KMF_ASYM_PRI;
749 		kmf_set_attr_at_index(attrlist, num,
750 		    KMF_KEYCLASS_ATTR, &keyclass,
751 		    sizeof (keyclass));
752 		num++;
753 
754 		/* list asymmetric private keys */
755 		rv = pk_list_keys(kmfhandle, attrlist, num,
756 		    "asymmetric private");
757 	}
758 
759 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
760 		int num = numattr;
761 
762 		keyclass = KMF_SYMMETRIC;
763 		kmf_set_attr_at_index(attrlist, num,
764 		    KMF_KEYCLASS_ATTR, &keyclass,
765 		    sizeof (keyclass));
766 		num++;
767 
768 		format = KMF_FORMAT_RAWKEY;
769 		kmf_set_attr_at_index(attrlist, num,
770 		    KMF_ENCODE_FORMAT_ATTR, &format,
771 		    sizeof (format));
772 		num++;
773 
774 		/* list symmetric keys */
775 		rv = pk_list_keys(kmfhandle, attrlist, num, "symmetric");
776 	}
777 
778 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
779 		int num = numattr;
780 
781 		keyclass = KMF_ASYM_PUB;
782 		kmf_set_attr_at_index(attrlist, num,
783 		    KMF_KEYCLASS_ATTR, &keyclass,
784 		    sizeof (keyclass));
785 		num++;
786 
787 		/* list asymmetric public keys */
788 		rv = pk_list_keys(kmfhandle, attrlist, num,
789 		    "asymmetric public");
790 	}
791 
792 	/* If searching for public objects or certificates, find certs now */
793 	numattr = 0;
794 	if (rv == KMF_OK && (oclass & PK_CERT_OBJ)) {
795 		kmf_set_attr_at_index(attrlist, numattr,
796 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
797 		    sizeof (kstype));
798 		numattr++;
799 
800 		if (nickname != NULL) {
801 			kmf_set_attr_at_index(attrlist, numattr,
802 			    KMF_CERT_LABEL_ATTR, nickname,
803 			    strlen(nickname));
804 			numattr++;
805 		}
806 
807 		if (issuer != NULL) {
808 			kmf_set_attr_at_index(attrlist, numattr,
809 			    KMF_ISSUER_NAME_ATTR, issuer,
810 			    strlen(issuer));
811 			numattr++;
812 		}
813 
814 		if (subject != NULL) {
815 			kmf_set_attr_at_index(attrlist, numattr,
816 			    KMF_SUBJECT_NAME_ATTR, subject,
817 			    strlen(subject));
818 			numattr++;
819 		}
820 
821 		if (serial != NULL) {
822 			kmf_set_attr_at_index(attrlist, numattr,
823 			    KMF_BIGINT_ATTR, serial,
824 			    sizeof (KMF_BIGINT));
825 			numattr++;
826 		}
827 
828 		if (token_spec != NULL) {
829 			kmf_set_attr_at_index(attrlist, numattr,
830 			    KMF_TOKEN_LABEL_ATTR, token_spec,
831 			    strlen(token_spec));
832 			numattr++;
833 		}
834 
835 		kmf_set_attr_at_index(attrlist, numattr,
836 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
837 		    sizeof (KMF_CERT_VALIDITY));
838 		numattr++;
839 
840 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
841 	}
842 
843 	numattr = 0;
844 	if (rv == KMF_OK && (oclass & PK_CRL_OBJ)) {
845 		int numcrls;
846 
847 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
848 		    &kstype, sizeof (kstype));
849 		numattr++;
850 
851 		if (token_spec != NULL) {
852 			kmf_set_attr_at_index(attrlist, numattr,
853 			    KMF_TOKEN_LABEL_ATTR,
854 			    token_spec, strlen(token_spec));
855 			numattr++;
856 		}
857 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_COUNT_ATTR,
858 		    &numcrls, sizeof (int));
859 		numattr++;
860 
861 		rv = kmf_find_crl(kmfhandle, numattr, attrlist);
862 		if (rv == KMF_OK) {
863 			char **p;
864 			if (numcrls == 0) {
865 				(void) printf(gettext("No CRLs found in "
866 				    "NSS keystore.\n"));
867 
868 				return (KMF_OK);
869 			}
870 			p = malloc(numcrls * sizeof (char *));
871 			if (p == NULL) {
872 				return (KMF_ERR_MEMORY);
873 			}
874 			(void) memset(p, 0, numcrls * sizeof (char *));
875 
876 			kmf_set_attr_at_index(attrlist, numattr,
877 			    KMF_CRL_NAMELIST_ATTR, p, sizeof (char *));
878 			numattr++;
879 			rv = kmf_find_crl(kmfhandle, numattr, attrlist);
880 			if (rv == KMF_OK) {
881 				int i;
882 				for (i = 0; i < numcrls; i++) {
883 					(void) printf("%d. Name = %s\n",
884 					    i + 1, p[i]);
885 					free(p[i]);
886 				}
887 			}
888 			free(p);
889 		}
890 	}
891 	return (rv);
892 }
893 
894 /*
895  * List token object.
896  */
897 int
898 pk_list(int argc, char *argv[])
899 {
900 	int			opt;
901 	extern int		optind_av;
902 	extern char		*optarg_av;
903 	char			*token_spec = NULL;
904 	char			*subject = NULL;
905 	char			*issuer = NULL;
906 	char			*dir = NULL;
907 	char			*prefix = NULL;
908 	char			*filename = NULL;
909 	char			*serstr = NULL;
910 	KMF_BIGINT		serial = { NULL, 0 };
911 
912 	char			*list_label = NULL;
913 	int			oclass = 0;
914 	KMF_KEYSTORE_TYPE	kstype = 0;
915 	KMF_RETURN		rv = KMF_OK;
916 	KMF_HANDLE_T		kmfhandle = NULL;
917 	char			*find_criteria = NULL;
918 	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
919 	KMF_CREDENTIAL		tokencred = { NULL, 0 };
920 
921 	/* Parse command line options.  Do NOT i18n/l10n. */
922 	while ((opt = getopt_av(argc, argv,
923 	    "k:(keystore)t:(objtype)T:(token)d:(dir)"
924 	    "p:(prefix)n:(nickname)S:(serial)s:(subject)"
925 	    "c:(criteria)"
926 	    "i:(issuer)l:(label)f:(infile)")) != EOF) {
927 		if (EMPTYSTRING(optarg_av))
928 			return (PK_ERR_USAGE);
929 		switch (opt) {
930 			case 'k':
931 				if (kstype != 0)
932 					return (PK_ERR_USAGE);
933 				kstype = KS2Int(optarg_av);
934 				if (kstype == 0)
935 					return (PK_ERR_USAGE);
936 				break;
937 			case 't':
938 				if (oclass != 0)
939 					return (PK_ERR_USAGE);
940 				oclass = OT2Int(optarg_av);
941 				if (oclass == -1)
942 					return (PK_ERR_USAGE);
943 				break;
944 			case 's':
945 				if (subject)
946 					return (PK_ERR_USAGE);
947 				subject = optarg_av;
948 				break;
949 			case 'i':
950 				if (issuer)
951 					return (PK_ERR_USAGE);
952 				issuer = optarg_av;
953 				break;
954 			case 'd':
955 				if (dir)
956 					return (PK_ERR_USAGE);
957 				dir = optarg_av;
958 				break;
959 			case 'p':
960 				if (prefix)
961 					return (PK_ERR_USAGE);
962 				prefix = optarg_av;
963 				break;
964 			case 'S':
965 				serstr = optarg_av;
966 				break;
967 			case 'f':
968 				if (filename)
969 					return (PK_ERR_USAGE);
970 				filename = optarg_av;
971 				break;
972 			case 'T':	/* token specifier */
973 				if (token_spec)
974 					return (PK_ERR_USAGE);
975 				token_spec = optarg_av;
976 				break;
977 			case 'n':
978 			case 'l':	/* object with specific label */
979 				if (list_label)
980 					return (PK_ERR_USAGE);
981 				list_label = optarg_av;
982 				break;
983 			case 'c':
984 				find_criteria = optarg_av;
985 				if (!strcasecmp(find_criteria, "valid"))
986 					find_criteria_flag =
987 					    KMF_NONEXPIRED_CERTS;
988 				else if (!strcasecmp(find_criteria, "expired"))
989 					find_criteria_flag = KMF_EXPIRED_CERTS;
990 				else if (!strcasecmp(find_criteria, "both"))
991 					find_criteria_flag = KMF_ALL_CERTS;
992 				else
993 					return (PK_ERR_USAGE);
994 				break;
995 			default:
996 				return (PK_ERR_USAGE);
997 		}
998 	}
999 	/* No additional args allowed. */
1000 	argc -= optind_av;
1001 	argv += optind_av;
1002 	if (argc)
1003 		return (PK_ERR_USAGE);
1004 
1005 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
1006 		/* Error message ? */
1007 		return (rv);
1008 	}
1009 
1010 	/* Assume keystore = PKCS#11 if not specified. */
1011 	if (kstype == 0)
1012 		kstype = KMF_KEYSTORE_PK11TOKEN;
1013 
1014 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
1015 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
1016 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
1017 
1018 		(void) fprintf(stderr, gettext("The objtype parameter "
1019 		    "is only relevant if keystore=pkcs11\n"));
1020 		return (PK_ERR_USAGE);
1021 	}
1022 
1023 
1024 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
1025 		token_spec = PK_DEFAULT_PK11TOKEN;
1026 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
1027 		token_spec = DEFAULT_NSS_TOKEN;
1028 	}
1029 
1030 	if (serstr != NULL) {
1031 		uchar_t *bytes = NULL;
1032 		size_t bytelen;
1033 
1034 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
1035 		if (rv != KMF_OK || bytes == NULL) {
1036 			(void) fprintf(stderr, gettext("serial number "
1037 			    "must be specified as a hex number "
1038 			    "(ex: 0x0102030405ffeeddee)\n"));
1039 			return (PK_ERR_USAGE);
1040 		}
1041 		serial.val = bytes;
1042 		serial.len = bytelen;
1043 		/* if objtype was not given, it must be for certs */
1044 		if (oclass == 0)
1045 			oclass = PK_CERT_OBJ;
1046 	}
1047 	if (oclass == 0 && (issuer != NULL || subject != NULL))
1048 		oclass = PK_CERT_OBJ;
1049 
1050 	/* If no object class specified, list public objects. */
1051 	if (oclass == 0)
1052 		oclass = PK_CERT_OBJ | PK_PUBKEY_OBJ;
1053 
1054 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
1055 	    kstype == KMF_KEYSTORE_NSS) &&
1056 	    (oclass & (PK_PRIKEY_OBJ | PK_PRIVATE_OBJ))) {
1057 
1058 		(void) get_token_password(kstype, token_spec,
1059 		    &tokencred);
1060 	}
1061 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
1062 		rv = list_pk11_objects(kmfhandle, token_spec,
1063 		    oclass, list_label, &serial,
1064 		    issuer, subject, dir, filename,
1065 		    &tokencred, find_criteria_flag);
1066 
1067 	} else if (kstype == KMF_KEYSTORE_NSS) {
1068 		if (dir == NULL)
1069 			dir = PK_DEFAULT_DIRECTORY;
1070 		rv = list_nss_objects(kmfhandle,
1071 		    oclass, token_spec, dir, prefix,
1072 		    list_label, &serial, issuer, subject,
1073 		    &tokencred, find_criteria_flag);
1074 
1075 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
1076 
1077 		rv = list_file_objects(kmfhandle,
1078 		    oclass, dir, filename,
1079 		    &serial, issuer, subject, find_criteria_flag);
1080 	}
1081 
1082 	if (rv != KMF_OK) {
1083 		display_error(kmfhandle, rv,
1084 		    gettext("Error listing objects"));
1085 	}
1086 
1087 	if (serial.val != NULL)
1088 		free(serial.val);
1089 
1090 	if (tokencred.cred != NULL)
1091 		free(tokencred.cred);
1092 
1093 	(void) kmf_finalize(kmfhandle);
1094 	return (rv);
1095 }
1096