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