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