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