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