xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/list.c (revision 30a5e8fa1253cb33980ee4514743cf683f584b4e)
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 	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)
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 keys.\n"), numkeys);
279 		keys = (KMF_KEY_HANDLE *)malloc(numkeys *
280 		    sizeof (KMF_KEY_HANDLE));
281 		if (keys == NULL)
282 			return (KMF_ERR_MEMORY);
283 		(void) memset(keys, 0, numkeys *
284 		    sizeof (KMF_KEY_HANDLE));
285 
286 		kmf_set_attr_at_index(attrlist, numattr,
287 		    KMF_KEY_HANDLE_ATTR,
288 		    keys, sizeof (KMF_KEY_HANDLE));
289 		numattr++;
290 
291 		rv = kmf_find_key(handle, numattr, attrlist);
292 		if (rv == KMF_OK)
293 			pk_show_keys(handle, keys, numkeys);
294 		for (i = 0; i < numkeys; i++)
295 			kmf_free_kmf_key(handle, &keys[i]);
296 		free(keys);
297 	}
298 	if (rv == KMF_ERR_KEY_NOT_FOUND &&
299 	    kstype != KMF_KEYSTORE_OPENSSL)
300 		rv = KMF_OK;
301 	return (rv);
302 }
303 
304 static KMF_RETURN
305 list_pk11_objects(KMF_HANDLE_T kmfhandle, char *token, int oclass,
306 	char *objlabel, KMF_BIGINT *serial, char *issuer, char *subject,
307 	char *dir, char *filename, KMF_CREDENTIAL *tokencred,
308 	KMF_CERT_VALIDITY find_criteria_flag)
309 {
310 	KMF_RETURN rv;
311 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
312 	int numattr = 0;
313 	KMF_ATTRIBUTE attrlist[16];
314 	boolean_t token_bool = B_TRUE;
315 	boolean_t private = B_FALSE;
316 	KMF_KEY_CLASS keyclass;
317 	KMF_ENCODE_FORMAT format;
318 
319 	/*
320 	 * Symmetric keys and RSA/DSA 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 	if (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) {
335 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
336 		    &kstype, sizeof (kstype));
337 		numattr++;
338 
339 		if (objlabel != NULL) {
340 			kmf_set_attr_at_index(attrlist, numattr,
341 			    KMF_KEYLABEL_ATTR, objlabel,
342 			    strlen(objlabel));
343 			numattr++;
344 		}
345 
346 		private = ((oclass & PK_PRIVATE_OBJ) > 0);
347 
348 		kmf_set_attr_at_index(attrlist, numattr,
349 		    KMF_PRIVATE_BOOL_ATTR, &private,
350 		    sizeof (private));
351 		numattr++;
352 
353 		kmf_set_attr_at_index(attrlist, numattr,
354 		    KMF_TOKEN_BOOL_ATTR, &token_bool,
355 		    sizeof (token_bool));
356 		numattr++;
357 
358 		if (oclass & PK_PRIKEY_OBJ) {
359 			int num = numattr;
360 
361 			keyclass = KMF_ASYM_PRI;
362 			kmf_set_attr_at_index(attrlist, num,
363 			    KMF_KEYCLASS_ATTR, &keyclass,
364 			    sizeof (keyclass));
365 			num++;
366 
367 			if (tokencred != NULL &&
368 			    tokencred->credlen > 0) {
369 				kmf_set_attr_at_index(attrlist, num,
370 				    KMF_CREDENTIAL_ATTR, tokencred,
371 				    sizeof (KMF_CREDENTIAL));
372 				num++;
373 			}
374 
375 			/* list asymmetric private keys */
376 			rv = pk_list_keys(kmfhandle, attrlist, num);
377 		}
378 
379 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
380 			int num = numattr;
381 
382 			keyclass = KMF_SYMMETRIC;
383 			kmf_set_attr_at_index(attrlist, num,
384 			    KMF_KEYCLASS_ATTR, &keyclass,
385 			    sizeof (keyclass));
386 			num++;
387 
388 			if (tokencred != NULL &&
389 			    tokencred->credlen > 0) {
390 				kmf_set_attr_at_index(attrlist, num,
391 				    KMF_CREDENTIAL_ATTR, tokencred,
392 				    sizeof (KMF_CREDENTIAL));
393 				num++;
394 			}
395 
396 			format = KMF_FORMAT_RAWKEY;
397 			kmf_set_attr_at_index(attrlist, num,
398 			    KMF_ENCODE_FORMAT_ATTR, &format,
399 			    sizeof (format));
400 			num++;
401 
402 			/* list symmetric keys */
403 			rv = pk_list_keys(kmfhandle, attrlist, num);
404 		}
405 
406 		if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
407 			int num = numattr;
408 
409 			keyclass = KMF_ASYM_PUB;
410 			kmf_set_attr_at_index(attrlist, num,
411 			    KMF_KEYCLASS_ATTR, &keyclass,
412 			    sizeof (keyclass));
413 			num++;
414 
415 			/* list asymmetric public keys (if any) */
416 			rv = pk_list_keys(kmfhandle, attrlist, num);
417 		}
418 
419 		if (rv != KMF_OK)
420 			return (rv);
421 	}
422 
423 	numattr = 0;
424 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
425 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
426 		    &kstype, sizeof (kstype));
427 		numattr++;
428 
429 		if (objlabel != NULL) {
430 			kmf_set_attr_at_index(attrlist, numattr,
431 			    KMF_CERT_LABEL_ATTR, objlabel,
432 			    strlen(objlabel));
433 			numattr++;
434 		}
435 
436 		if (issuer != NULL) {
437 			kmf_set_attr_at_index(attrlist, numattr,
438 			    KMF_ISSUER_NAME_ATTR, issuer,
439 			    strlen(issuer));
440 			numattr++;
441 		}
442 
443 		if (subject != NULL) {
444 			kmf_set_attr_at_index(attrlist, numattr,
445 			    KMF_SUBJECT_NAME_ATTR, subject,
446 			    strlen(subject));
447 			numattr++;
448 		}
449 
450 		if (serial != NULL) {
451 			kmf_set_attr_at_index(attrlist, numattr,
452 			    KMF_BIGINT_ATTR, serial,
453 			    sizeof (KMF_BIGINT));
454 			numattr++;
455 		}
456 
457 		kmf_set_attr_at_index(attrlist, numattr,
458 		    KMF_PRIVATE_BOOL_ATTR, &private,
459 		    sizeof (private));
460 		numattr++;
461 
462 		kmf_set_attr_at_index(attrlist, numattr,
463 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
464 		    sizeof (KMF_CERT_VALIDITY));
465 		numattr++;
466 
467 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
468 		if (rv != KMF_OK)
469 			return (rv);
470 	}
471 
472 	numattr = 0;
473 	kstype = KMF_KEYSTORE_OPENSSL; /* CRL is file-based */
474 	if (oclass & PK_CRL_OBJ) {
475 		char *crldata = NULL;
476 
477 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
478 		    &kstype, sizeof (kstype));
479 		numattr++;
480 
481 		if (dir != NULL) {
482 			kmf_set_attr_at_index(attrlist, numattr,
483 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
484 			numattr++;
485 		}
486 		if (filename != NULL) {
487 			kmf_set_attr_at_index(attrlist, numattr,
488 			    KMF_CRL_FILENAME_ATTR,
489 			    filename, strlen(filename));
490 			numattr++;
491 		}
492 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_DATA_ATTR,
493 		    &crldata, sizeof (char *));
494 		numattr++;
495 
496 		rv = kmf_list_crl(kmfhandle, numattr, attrlist);
497 		if (rv == KMF_OK && crldata != NULL) {
498 			(void) printf("%s\n", crldata);
499 			free(crldata);
500 		}
501 	}
502 
503 	return (rv);
504 }
505 
506 static int
507 list_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
508 	char *dir, char *filename, KMF_BIGINT *serial,
509 	char *issuer, char *subject,
510 	KMF_CERT_VALIDITY find_criteria_flag)
511 {
512 	int rv;
513 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
514 	int numattr = 0;
515 	KMF_ATTRIBUTE attrlist[16];
516 	KMF_KEY_CLASS keyclass;
517 	KMF_ENCODE_FORMAT format;
518 	char *defaultdir = ".";
519 
520 	if (oclass & PK_KEY_OBJ) {
521 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
522 		    &kstype, sizeof (kstype));
523 		numattr++;
524 
525 		if (dir == NULL && filename == NULL)
526 			dir = defaultdir;
527 
528 		if (dir != NULL) {
529 			kmf_set_attr_at_index(attrlist, numattr,
530 			    KMF_DIRPATH_ATTR, dir,
531 			    strlen(dir));
532 			numattr++;
533 		}
534 
535 		if (filename != NULL) {
536 			kmf_set_attr_at_index(attrlist, numattr,
537 			    KMF_KEY_FILENAME_ATTR, filename,
538 			    strlen(filename));
539 			numattr++;
540 		}
541 
542 		if (oclass & PK_PRIKEY_OBJ) {
543 			int num = numattr;
544 
545 			keyclass = KMF_ASYM_PRI;
546 			kmf_set_attr_at_index(attrlist, num,
547 			    KMF_KEYCLASS_ATTR, &keyclass,
548 			    sizeof (keyclass));
549 			num++;
550 
551 			/* list asymmetric private keys */
552 			rv = pk_list_keys(kmfhandle, attrlist, num);
553 		}
554 		if (rv == KMF_ERR_KEY_NOT_FOUND)
555 			rv = KMF_OK;
556 
557 		if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
558 			int num = numattr;
559 
560 			keyclass = KMF_SYMMETRIC;
561 			kmf_set_attr_at_index(attrlist, num,
562 			    KMF_KEYCLASS_ATTR, &keyclass,
563 			    sizeof (keyclass));
564 			num++;
565 
566 			format = KMF_FORMAT_RAWKEY;
567 			kmf_set_attr_at_index(attrlist, num,
568 			    KMF_ENCODE_FORMAT_ATTR, &format,
569 			    sizeof (format));
570 			num++;
571 
572 			/* list symmetric keys */
573 			rv = pk_list_keys(kmfhandle, attrlist, num);
574 		}
575 		if (rv == KMF_ERR_KEY_NOT_FOUND)
576 			rv = KMF_OK;
577 		if (rv != KMF_OK)
578 			return (rv);
579 	}
580 
581 	numattr = 0;
582 	if (oclass & PK_CERT_OBJ) {
583 		kmf_set_attr_at_index(attrlist, numattr,
584 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
585 		    sizeof (kstype));
586 		numattr++;
587 
588 		if (issuer != NULL) {
589 			kmf_set_attr_at_index(attrlist, numattr,
590 			    KMF_ISSUER_NAME_ATTR, issuer,
591 			    strlen(issuer));
592 			numattr++;
593 		}
594 
595 		if (subject != NULL) {
596 			kmf_set_attr_at_index(attrlist, numattr,
597 			    KMF_SUBJECT_NAME_ATTR, subject,
598 			    strlen(subject));
599 			numattr++;
600 		}
601 
602 		if (serial != NULL) {
603 			kmf_set_attr_at_index(attrlist, numattr,
604 			    KMF_BIGINT_ATTR, serial,
605 			    sizeof (KMF_BIGINT));
606 			numattr++;
607 		}
608 
609 		if (filename != NULL) {
610 			kmf_set_attr_at_index(attrlist, numattr,
611 			    KMF_CERT_FILENAME_ATTR, filename,
612 			    strlen(filename));
613 			numattr++;
614 		}
615 
616 		if (dir != NULL) {
617 			kmf_set_attr_at_index(attrlist, numattr,
618 			    KMF_DIRPATH_ATTR, dir,
619 			    strlen(dir));
620 			numattr++;
621 		}
622 
623 		kmf_set_attr_at_index(attrlist, numattr,
624 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
625 		    sizeof (KMF_CERT_VALIDITY));
626 		numattr++;
627 
628 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
629 		if (rv != KMF_OK)
630 			return (rv);
631 	}
632 
633 	numattr = 0;
634 	if (oclass & PK_CRL_OBJ) {
635 		char *crldata = NULL;
636 
637 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
638 		    &kstype, sizeof (kstype));
639 		numattr++;
640 
641 		if (dir != NULL) {
642 			kmf_set_attr_at_index(attrlist, numattr,
643 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
644 			numattr++;
645 		}
646 		if (filename != NULL) {
647 			kmf_set_attr_at_index(attrlist, numattr,
648 			    KMF_CRL_FILENAME_ATTR,
649 			    filename, strlen(filename));
650 			numattr++;
651 		}
652 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_DATA_ATTR,
653 		    &crldata, sizeof (char *));
654 		numattr++;
655 
656 		rv = kmf_list_crl(kmfhandle, numattr, attrlist);
657 		if (rv == KMF_OK && crldata != NULL) {
658 			(void) printf("%s\n", crldata);
659 			free(crldata);
660 		}
661 	}
662 
663 	return (rv);
664 }
665 
666 static int
667 list_nss_objects(KMF_HANDLE_T kmfhandle,
668 	int oclass, char *token_spec, char *dir, char *prefix,
669 	char *nickname, KMF_BIGINT *serial, char *issuer, char *subject,
670 	KMF_CREDENTIAL *tokencred,
671 	KMF_CERT_VALIDITY find_criteria_flag)
672 {
673 	KMF_RETURN rv = KMF_OK;
674 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
675 	int numattr = 0;
676 	KMF_ATTRIBUTE attrlist[16];
677 	KMF_KEY_CLASS keyclass;
678 	KMF_ENCODE_FORMAT format;
679 
680 	rv = configure_nss(kmfhandle, dir, prefix);
681 	if (rv != KMF_OK)
682 		return (rv);
683 
684 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
685 	    &kstype, sizeof (kstype));
686 	numattr++;
687 
688 	if (oclass & PK_KEY_OBJ) {
689 		if (tokencred != NULL && tokencred->credlen > 0) {
690 			kmf_set_attr_at_index(attrlist, numattr,
691 			    KMF_CREDENTIAL_ATTR, tokencred,
692 			    sizeof (KMF_CREDENTIAL));
693 			numattr++;
694 		}
695 
696 		if (token_spec && strlen(token_spec)) {
697 			kmf_set_attr_at_index(attrlist, numattr,
698 			    KMF_TOKEN_LABEL_ATTR, token_spec,
699 			    strlen(token_spec));
700 			numattr++;
701 		}
702 
703 		if (nickname != NULL) {
704 			kmf_set_attr_at_index(attrlist, numattr,
705 			    KMF_KEYLABEL_ATTR, nickname,
706 			    strlen(nickname));
707 			numattr++;
708 		}
709 	}
710 
711 	if (oclass & PK_PRIKEY_OBJ) {
712 		int num = numattr;
713 
714 		keyclass = KMF_ASYM_PRI;
715 		kmf_set_attr_at_index(attrlist, num,
716 		    KMF_KEYCLASS_ATTR, &keyclass,
717 		    sizeof (keyclass));
718 		num++;
719 
720 		/* list asymmetric private keys */
721 		rv = pk_list_keys(kmfhandle, attrlist, num);
722 	}
723 
724 	if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
725 		int num = numattr;
726 
727 		keyclass = KMF_SYMMETRIC;
728 		kmf_set_attr_at_index(attrlist, num,
729 		    KMF_KEYCLASS_ATTR, &keyclass,
730 		    sizeof (keyclass));
731 		num++;
732 
733 		format = KMF_FORMAT_RAWKEY;
734 		kmf_set_attr_at_index(attrlist, num,
735 		    KMF_ENCODE_FORMAT_ATTR, &format,
736 		    sizeof (format));
737 		num++;
738 
739 		/* list symmetric keys */
740 		rv = pk_list_keys(kmfhandle, attrlist, num);
741 	}
742 
743 	if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
744 		int num = numattr;
745 
746 		keyclass = KMF_ASYM_PUB;
747 		kmf_set_attr_at_index(attrlist, num,
748 		    KMF_KEYCLASS_ATTR, &keyclass,
749 		    sizeof (keyclass));
750 		num++;
751 
752 		/* list asymmetric public keys */
753 		rv = pk_list_keys(kmfhandle, attrlist, num);
754 	}
755 
756 	/* If searching for public objects or certificates, find certs now */
757 	numattr = 0;
758 	if (rv == KMF_OK && (oclass & PK_CERT_OBJ)) {
759 		kmf_set_attr_at_index(attrlist, numattr,
760 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
761 		    sizeof (kstype));
762 		numattr++;
763 
764 		if (nickname != NULL) {
765 			kmf_set_attr_at_index(attrlist, numattr,
766 			    KMF_CERT_LABEL_ATTR, nickname,
767 			    strlen(nickname));
768 			numattr++;
769 		}
770 
771 		if (issuer != NULL) {
772 			kmf_set_attr_at_index(attrlist, numattr,
773 			    KMF_ISSUER_NAME_ATTR, issuer,
774 			    strlen(issuer));
775 			numattr++;
776 		}
777 
778 		if (subject != NULL) {
779 			kmf_set_attr_at_index(attrlist, numattr,
780 			    KMF_SUBJECT_NAME_ATTR, subject,
781 			    strlen(subject));
782 			numattr++;
783 		}
784 
785 		if (serial != NULL) {
786 			kmf_set_attr_at_index(attrlist, numattr,
787 			    KMF_BIGINT_ATTR, serial,
788 			    sizeof (KMF_BIGINT));
789 			numattr++;
790 		}
791 
792 		if (token_spec != NULL) {
793 			kmf_set_attr_at_index(attrlist, numattr,
794 			    KMF_TOKEN_LABEL_ATTR, token_spec,
795 			    strlen(token_spec));
796 			numattr++;
797 		}
798 
799 		kmf_set_attr_at_index(attrlist, numattr,
800 		    KMF_CERT_VALIDITY_ATTR, &find_criteria_flag,
801 		    sizeof (KMF_CERT_VALIDITY));
802 		numattr++;
803 
804 		rv = pk_find_certs(kmfhandle, attrlist, numattr);
805 	}
806 
807 	numattr = 0;
808 	if (rv == KMF_OK && (oclass & PK_CRL_OBJ)) {
809 		int numcrls;
810 
811 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
812 		    &kstype, sizeof (kstype));
813 		numattr++;
814 
815 		if (token_spec != NULL) {
816 			kmf_set_attr_at_index(attrlist, numattr,
817 			    KMF_TOKEN_LABEL_ATTR,
818 			    token_spec, strlen(token_spec));
819 			numattr++;
820 		}
821 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_COUNT_ATTR,
822 		    &numcrls, sizeof (int));
823 		numattr++;
824 
825 		rv = kmf_find_crl(kmfhandle, numattr, attrlist);
826 		if (rv == KMF_OK) {
827 			char **p;
828 			if (numcrls == 0) {
829 				(void) printf(gettext("No CRLs found in "
830 				    "NSS keystore.\n"));
831 
832 				return (KMF_OK);
833 			}
834 			p = malloc(numcrls * sizeof (char *));
835 			if (p == NULL) {
836 				return (KMF_ERR_MEMORY);
837 			}
838 			(void) memset(p, 0, numcrls * sizeof (char *));
839 
840 			kmf_set_attr_at_index(attrlist, numattr,
841 			    KMF_CRL_NAMELIST_ATTR, p, sizeof (char *));
842 			numattr++;
843 			rv = kmf_find_crl(kmfhandle, numattr, attrlist);
844 			if (rv == KMF_OK) {
845 				int i;
846 				for (i = 0; i < numcrls; i++) {
847 					(void) printf("%d. Name = %s\n",
848 					    i + 1, p[i]);
849 					free(p[i]);
850 				}
851 			}
852 			free(p);
853 		}
854 	}
855 	return (rv);
856 }
857 
858 /*
859  * List token object.
860  */
861 int
862 pk_list(int argc, char *argv[])
863 {
864 	int			opt;
865 	extern int		optind_av;
866 	extern char		*optarg_av;
867 	char			*token_spec = NULL;
868 	char			*subject = NULL;
869 	char			*issuer = NULL;
870 	char			*dir = NULL;
871 	char			*prefix = NULL;
872 	char			*filename = NULL;
873 	char			*serstr = NULL;
874 	KMF_BIGINT		serial = { NULL, 0 };
875 
876 	char			*list_label = NULL;
877 	int			oclass = 0;
878 	KMF_KEYSTORE_TYPE	kstype = 0;
879 	KMF_RETURN		rv = KMF_OK;
880 	KMF_HANDLE_T		kmfhandle = NULL;
881 	char			*find_criteria = NULL;
882 	KMF_CERT_VALIDITY	find_criteria_flag = KMF_ALL_CERTS;
883 	KMF_CREDENTIAL		tokencred = {NULL, 0};
884 
885 	/* Parse command line options.  Do NOT i18n/l10n. */
886 	while ((opt = getopt_av(argc, argv,
887 	    "k:(keystore)t:(objtype)T:(token)d:(dir)"
888 	    "p:(prefix)n:(nickname)S:(serial)s:(subject)"
889 	    "c:(criteria)"
890 	    "i:(issuer)l:(label)f:(infile)")) != EOF) {
891 		if (EMPTYSTRING(optarg_av))
892 			return (PK_ERR_USAGE);
893 		switch (opt) {
894 			case 'k':
895 				if (kstype != 0)
896 					return (PK_ERR_USAGE);
897 				kstype = KS2Int(optarg_av);
898 				if (kstype == 0)
899 					return (PK_ERR_USAGE);
900 				break;
901 			case 't':
902 				if (oclass != 0)
903 					return (PK_ERR_USAGE);
904 				oclass = OT2Int(optarg_av);
905 				if (oclass == -1)
906 					return (PK_ERR_USAGE);
907 				break;
908 			case 's':
909 				if (subject)
910 					return (PK_ERR_USAGE);
911 				subject = optarg_av;
912 				break;
913 			case 'i':
914 				if (issuer)
915 					return (PK_ERR_USAGE);
916 				issuer = optarg_av;
917 				break;
918 			case 'd':
919 				if (dir)
920 					return (PK_ERR_USAGE);
921 				dir = optarg_av;
922 				break;
923 			case 'p':
924 				if (prefix)
925 					return (PK_ERR_USAGE);
926 				prefix = optarg_av;
927 				break;
928 			case 'S':
929 				serstr = optarg_av;
930 				break;
931 			case 'f':
932 				if (filename)
933 					return (PK_ERR_USAGE);
934 				filename = optarg_av;
935 				break;
936 			case 'T':	/* token specifier */
937 				if (token_spec)
938 					return (PK_ERR_USAGE);
939 				token_spec = optarg_av;
940 				break;
941 			case 'n':
942 			case 'l':	/* object with specific label */
943 				if (list_label)
944 					return (PK_ERR_USAGE);
945 				list_label = optarg_av;
946 				break;
947 			case 'c':
948 				find_criteria = optarg_av;
949 				if (!strcasecmp(find_criteria, "valid"))
950 					find_criteria_flag =
951 					    KMF_NONEXPIRED_CERTS;
952 				else if (!strcasecmp(find_criteria, "expired"))
953 					find_criteria_flag = KMF_EXPIRED_CERTS;
954 				else if (!strcasecmp(find_criteria, "both"))
955 					find_criteria_flag = KMF_ALL_CERTS;
956 				else
957 					return (PK_ERR_USAGE);
958 				break;
959 			default:
960 				return (PK_ERR_USAGE);
961 		}
962 	}
963 	/* No additional args allowed. */
964 	argc -= optind_av;
965 	argv += optind_av;
966 	if (argc)
967 		return (PK_ERR_USAGE);
968 
969 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
970 		/* Error message ? */
971 		return (rv);
972 	}
973 
974 	/* Assume keystore = PKCS#11 if not specified. */
975 	if (kstype == 0)
976 		kstype = KMF_KEYSTORE_PK11TOKEN;
977 
978 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
979 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
980 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
981 
982 		(void) fprintf(stderr, gettext("The objtype parameter "
983 		    "is only relevant if keystore=pkcs11\n"));
984 		return (PK_ERR_USAGE);
985 	}
986 
987 	/* If no object class specified, list certificate objects. */
988 	if (oclass == 0)
989 		oclass = PK_CERT_OBJ;
990 
991 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
992 		token_spec = PK_DEFAULT_PK11TOKEN;
993 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
994 		token_spec = DEFAULT_NSS_TOKEN;
995 	}
996 
997 	if (serstr != NULL) {
998 		uchar_t *bytes = NULL;
999 		size_t bytelen;
1000 
1001 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
1002 		if (rv != KMF_OK || bytes == NULL) {
1003 			(void) fprintf(stderr, gettext("serial number "
1004 			    "must be specified as a hex number "
1005 			    "(ex: 0x0102030405ffeeddee)\n"));
1006 			return (PK_ERR_USAGE);
1007 		}
1008 		serial.val = bytes;
1009 		serial.len = bytelen;
1010 	}
1011 
1012 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
1013 	    kstype == KMF_KEYSTORE_NSS) &&
1014 	    (oclass & (PK_PRIKEY_OBJ | PK_PRIVATE_OBJ))) {
1015 
1016 		(void) get_token_password(kstype, token_spec,
1017 		    &tokencred);
1018 	}
1019 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
1020 		rv = list_pk11_objects(kmfhandle, token_spec,
1021 		    oclass, list_label, &serial,
1022 		    issuer, subject, dir, filename,
1023 		    &tokencred, find_criteria_flag);
1024 
1025 	} else if (kstype == KMF_KEYSTORE_NSS) {
1026 		if (dir == NULL)
1027 			dir = PK_DEFAULT_DIRECTORY;
1028 		rv = list_nss_objects(kmfhandle,
1029 		    oclass, token_spec, dir, prefix,
1030 		    list_label, &serial, issuer, subject,
1031 		    &tokencred, find_criteria_flag);
1032 
1033 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
1034 
1035 		rv = list_file_objects(kmfhandle,
1036 		    oclass, dir, filename,
1037 		    &serial, issuer, subject, find_criteria_flag);
1038 	}
1039 
1040 	if (rv != KMF_OK) {
1041 		display_error(kmfhandle, rv,
1042 		    gettext("Error listing objects"));
1043 	}
1044 
1045 	if (serial.val != NULL)
1046 		free(serial.val);
1047 
1048 	if (tokencred.cred != NULL)
1049 		free(tokencred.cred);
1050 
1051 	(void) kmf_finalize(kmfhandle);
1052 	return (rv);
1053 }
1054