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