xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/list.c (revision 17:003a85e6a25c)
1*17Sdinak /*
2*17Sdinak  * CDDL HEADER START
3*17Sdinak  *
4*17Sdinak  * The contents of this file are subject to the terms of the
5*17Sdinak  * Common Development and Distribution License, Version 1.0 only
6*17Sdinak  * (the "License").  You may not use this file except in compliance
7*17Sdinak  * with the License.
8*17Sdinak  *
9*17Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*17Sdinak  * or http://www.opensolaris.org/os/licensing.
11*17Sdinak  * See the License for the specific language governing permissions
12*17Sdinak  * and limitations under the License.
13*17Sdinak  *
14*17Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
15*17Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*17Sdinak  * If applicable, add the following below this CDDL HEADER, with the
17*17Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
18*17Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
19*17Sdinak  *
20*17Sdinak  * CDDL HEADER END
21*17Sdinak  */
22*17Sdinak /*
23*17Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*17Sdinak  * Use is subject to license terms.
25*17Sdinak  */
26*17Sdinak 
27*17Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*17Sdinak 
29*17Sdinak /*
30*17Sdinak  * This file implements the token object list operation for this tool.
31*17Sdinak  * It loads the PKCS#11 modules, finds the object to list, lists it,
32*17Sdinak  * and cleans up.  User must be logged into the token to list private
33*17Sdinak  * objects.
34*17Sdinak  */
35*17Sdinak 
36*17Sdinak #include <stdio.h>
37*17Sdinak #include <errno.h>
38*17Sdinak #include <string.h>
39*17Sdinak #include <cryptoutil.h>
40*17Sdinak #include <security/cryptoki.h>
41*17Sdinak #include "common.h"
42*17Sdinak #include "derparse.h"
43*17Sdinak 
44*17Sdinak /*
45*17Sdinak  * Get key size based on the key type.
46*17Sdinak  */
47*17Sdinak static CK_ULONG
48*17Sdinak get_key_size(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, CK_KEY_TYPE key_type)
49*17Sdinak {
50*17Sdinak 	CK_RV		rv = CKR_OK;
51*17Sdinak 	CK_ULONG	key_size;
52*17Sdinak 	CK_ATTRIBUTE	modulus_sz =
53*17Sdinak 		{ CKA_MODULUS, NULL, 0 };	/* RSA */
54*17Sdinak 	CK_ATTRIBUTE	prime_sz =
55*17Sdinak 		{ CKA_PRIME, NULL, 0 };		/* DSA, DH X9.42 */
56*17Sdinak 	CK_ATTRIBUTE	value_sz =
57*17Sdinak 		{ CKA_VALUE, NULL_PTR, 0 };	/* DH, DES/DES3, AES, GENERIC */
58*17Sdinak 
59*17Sdinak 	cryptodebug("inside get_key_size");
60*17Sdinak 
61*17Sdinak 	switch (key_type) {
62*17Sdinak 	case CKK_RSA:
63*17Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &modulus_sz, 1)) !=
64*17Sdinak 		    CKR_OK) {
65*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
66*17Sdinak 			    "Unable to get modulus attribute size (%s)."),
67*17Sdinak 			    pkcs11_strerror(rv));
68*17Sdinak 		} else
69*17Sdinak 			/* Convert key size to bits. */
70*17Sdinak 			key_size = modulus_sz.ulValueLen * 8;
71*17Sdinak 		break;
72*17Sdinak 	case CKK_DH:
73*17Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
74*17Sdinak 		    CKR_OK) {
75*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
76*17Sdinak 			    "Unable to get value attribute size (%s)."),
77*17Sdinak 			    pkcs11_strerror(rv));
78*17Sdinak 		} else
79*17Sdinak 			/* Convert key size to bits. */
80*17Sdinak 			key_size = value_sz.ulValueLen * 8;
81*17Sdinak 		break;
82*17Sdinak 	case CKK_X9_42_DH:
83*17Sdinak 	case CKK_DSA:
84*17Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &prime_sz, 1)) !=
85*17Sdinak 		    CKR_OK) {
86*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
87*17Sdinak 			    "Unable to get prime attribute size (%s)."),
88*17Sdinak 			    pkcs11_strerror(rv));
89*17Sdinak 		} else
90*17Sdinak 			/* Convert key size to bits. */
91*17Sdinak 			key_size = prime_sz.ulValueLen * 8;
92*17Sdinak 		break;
93*17Sdinak 	case CKK_DES:
94*17Sdinak 	case CKK_DES3:
95*17Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
96*17Sdinak 		    CKR_OK) {
97*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
98*17Sdinak 			    "Unable to get value attribute size (%s)."),
99*17Sdinak 			    pkcs11_strerror(rv));
100*17Sdinak 		} else
101*17Sdinak 			/* Convert key size to bits -- omitting parity bit. */
102*17Sdinak 			key_size = value_sz.ulValueLen * 7;
103*17Sdinak 		break;
104*17Sdinak 	case CKK_AES:
105*17Sdinak 	case CKK_GENERIC_SECRET:
106*17Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
107*17Sdinak 		    CKR_OK) {
108*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
109*17Sdinak 			    "Unable to get value attribute size (%s)."),
110*17Sdinak 			    pkcs11_strerror(rv));
111*17Sdinak 		} else
112*17Sdinak 			/* Convert key size to bits. */
113*17Sdinak 			key_size = value_sz.ulValueLen * 8;
114*17Sdinak 		break;
115*17Sdinak 	default:
116*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
117*17Sdinak 		    "Unknown object key type (0x%02x)."), key_type);
118*17Sdinak 		break;
119*17Sdinak 	}
120*17Sdinak 
121*17Sdinak 	return (key_size);
122*17Sdinak }
123*17Sdinak 
124*17Sdinak /*
125*17Sdinak  * Display private key.
126*17Sdinak  */
127*17Sdinak static CK_RV
128*17Sdinak display_prikey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
129*17Sdinak {
130*17Sdinak 	CK_RV			rv = CKR_OK;
131*17Sdinak 	static CK_BBOOL		private;
132*17Sdinak 	static CK_BBOOL		modifiable;
133*17Sdinak 	static CK_KEY_TYPE	key_type;
134*17Sdinak 	CK_ULONG		key_size;
135*17Sdinak 	CK_BYTE			*label = NULL;
136*17Sdinak 	CK_ULONG		label_len = 0;
137*17Sdinak 	CK_BYTE			*id = NULL;
138*17Sdinak 	CK_ULONG		id_len = 0;
139*17Sdinak 	CK_BYTE			*subject = NULL;
140*17Sdinak 	CK_ULONG		subject_len = 0;
141*17Sdinak 	CK_DATE			*start_date = NULL;
142*17Sdinak 	CK_ULONG		start_date_len = 0;
143*17Sdinak 	CK_DATE			*end_date = NULL;
144*17Sdinak 	CK_ULONG		end_date_len = 0;
145*17Sdinak 	CK_ATTRIBUTE		attrs[18] = {
146*17Sdinak 		/* 0 to 2 */
147*17Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
148*17Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
149*17Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
150*17Sdinak 		/* 3 to 12 */
151*17Sdinak 		{ CKA_DERIVE, NULL, 0 },
152*17Sdinak 		{ CKA_LOCAL, NULL, 0 },
153*17Sdinak 		{ CKA_DECRYPT, NULL, 0 },
154*17Sdinak 		{ CKA_SIGN, NULL, 0 },
155*17Sdinak 		{ CKA_SIGN_RECOVER, NULL, 0 },
156*17Sdinak 		{ CKA_UNWRAP, NULL, 0 },
157*17Sdinak 		{ CKA_SENSITIVE, NULL, 0 },
158*17Sdinak 		{ CKA_ALWAYS_SENSITIVE, NULL, 0 },
159*17Sdinak 		{ CKA_EXTRACTABLE, NULL, 0 },
160*17Sdinak 		{ CKA_NEVER_EXTRACTABLE, NULL, 0 },
161*17Sdinak 		/* 13 to 17 */
162*17Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
163*17Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
164*17Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* optional */
165*17Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
166*17Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
167*17Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
168*17Sdinak 	    };
169*17Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
170*17Sdinak 	int		i;
171*17Sdinak 	char		*hex_id = NULL;
172*17Sdinak 	int		hex_id_len = 0;
173*17Sdinak 	char		*hex_subject = NULL;
174*17Sdinak 	int		hex_subject_len = 0;
175*17Sdinak 
176*17Sdinak 	cryptodebug("inside display_prikey");
177*17Sdinak 
178*17Sdinak 	/* Get the sizes of the attributes we need. */
179*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
180*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
181*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
182*17Sdinak 		    "Unable to get private key attribute sizes (%s)."),
183*17Sdinak 		    pkcs11_strerror(rv));
184*17Sdinak 		return (rv);
185*17Sdinak 	}
186*17Sdinak 
187*17Sdinak 	/* Allocate memory for each variable-length attribute. */
188*17Sdinak 	for (i = 3; i < n_attrs; i++) {
189*17Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
190*17Sdinak 		    attrs[i].ulValueLen == 0) {
191*17Sdinak 			cryptodebug("display_prikey: *** should not happen");
192*17Sdinak 			attrs[i].ulValueLen = 0;
193*17Sdinak 			continue;
194*17Sdinak 		}
195*17Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
196*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
197*17Sdinak 			rv = CKR_HOST_MEMORY;
198*17Sdinak 			goto free_display_prikey;
199*17Sdinak 		}
200*17Sdinak 	}
201*17Sdinak 
202*17Sdinak 	/* Now really get the attributes. */
203*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
204*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
205*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
206*17Sdinak 		    "Unable to get private key attributes (%s)."),
207*17Sdinak 		    pkcs11_strerror(rv));
208*17Sdinak 		goto free_display_prikey;
209*17Sdinak 	}
210*17Sdinak 
211*17Sdinak 	/* Fill in all the optional temp variables. */
212*17Sdinak 	i = 13;
213*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
214*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
215*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
216*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
217*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
218*17Sdinak 
219*17Sdinak 	/* Get the key size for the object. */
220*17Sdinak 	key_size = get_key_size(sess, obj, key_type);
221*17Sdinak 
222*17Sdinak 	/* Display the object ... */
223*17Sdinak 		/* ... the label and what it is (and key size in bits) ... */
224*17Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
225*17Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
226*17Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
227*17Sdinak 	    class_str(CKO_PRIVATE_KEY));
228*17Sdinak 
229*17Sdinak 		/* ... the id ... */
230*17Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
231*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
232*17Sdinak 	else {
233*17Sdinak 		hex_id_len = 3 * id_len + 1;
234*17Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
235*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
236*17Sdinak 			rv = CKR_HOST_MEMORY;
237*17Sdinak 			goto free_display_prikey;
238*17Sdinak 		}
239*17Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
240*17Sdinak 		    "\n\t\t", "");
241*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
242*17Sdinak 		free(hex_id);
243*17Sdinak 	}
244*17Sdinak 
245*17Sdinak 		/* ... the subject name ... */
246*17Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
247*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
248*17Sdinak 	else {
249*17Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
250*17Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
251*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
252*17Sdinak 			rv = CKR_HOST_MEMORY;
253*17Sdinak 			goto free_display_prikey;
254*17Sdinak 		}
255*17Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
256*17Sdinak 		    hex_subject_len);
257*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
258*17Sdinak 		    hex_subject_len, hex_subject);
259*17Sdinak 		free(hex_subject);
260*17Sdinak 	}
261*17Sdinak 
262*17Sdinak 		/* ... the start date ... */
263*17Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
264*17Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
265*17Sdinak 	else
266*17Sdinak 		(void) fprintf(stdout, gettext(
267*17Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
268*17Sdinak 		    start_date->month, start_date->day, start_date->year);
269*17Sdinak 
270*17Sdinak 		/* ... the end date ... */
271*17Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
272*17Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
273*17Sdinak 	else
274*17Sdinak 		(void) fprintf(stdout, gettext(
275*17Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
276*17Sdinak 		    end_date->month, end_date->day, end_date->year);
277*17Sdinak 
278*17Sdinak 		/* ... and its capabilities */
279*17Sdinak 	(void) fprintf(stdout, "\t(%s, %s",
280*17Sdinak 	    private != pk_false ? gettext("private") : gettext("public"),
281*17Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
282*17Sdinak 	    gettext("not modifiable"));
283*17Sdinak 	for (i = 3; i <= 12; i++) {
284*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
285*17Sdinak 		    attrs[i].ulValueLen != 0 &&
286*17Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
287*17Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
288*17Sdinak 	}
289*17Sdinak 	(void) fprintf(stdout, ")\n");
290*17Sdinak 
291*17Sdinak free_display_prikey:
292*17Sdinak 	for (i = 3; i < n_attrs; i++)
293*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
294*17Sdinak 		    attrs[i].ulValueLen != 0)
295*17Sdinak 			free(attrs[i].pValue);
296*17Sdinak 	return (rv);
297*17Sdinak }
298*17Sdinak 
299*17Sdinak /*
300*17Sdinak  * Display public key.
301*17Sdinak  */
302*17Sdinak static CK_RV
303*17Sdinak display_pubkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
304*17Sdinak {
305*17Sdinak 	CK_RV			rv = CKR_OK;
306*17Sdinak 	static CK_BBOOL		private;
307*17Sdinak 	static CK_BBOOL		modifiable;
308*17Sdinak 	static CK_BBOOL		trusted;
309*17Sdinak 	static CK_KEY_TYPE	key_type;
310*17Sdinak 	CK_ULONG		key_size;
311*17Sdinak 	CK_BYTE			*label = NULL;
312*17Sdinak 	CK_ULONG		label_len = 0;
313*17Sdinak 	CK_BYTE			*id = NULL;
314*17Sdinak 	CK_ULONG		id_len = 0;
315*17Sdinak 	CK_BYTE			*subject = NULL;
316*17Sdinak 	CK_ULONG		subject_len = 0;
317*17Sdinak 	CK_DATE			*start_date = NULL;
318*17Sdinak 	CK_ULONG		start_date_len = 0;
319*17Sdinak 	CK_DATE			*end_date = NULL;
320*17Sdinak 	CK_ULONG		end_date_len = 0;
321*17Sdinak 	CK_ATTRIBUTE		attrs[15] = {
322*17Sdinak 		/* 0 to 3 */
323*17Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
324*17Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
325*17Sdinak 		{ CKA_TRUSTED, &trusted, sizeof (trusted) },
326*17Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
327*17Sdinak 		/* 4 to 9 */
328*17Sdinak 		{ CKA_DERIVE, NULL, 0 },
329*17Sdinak 		{ CKA_LOCAL, NULL, 0 },
330*17Sdinak 		{ CKA_ENCRYPT, NULL, 0 },
331*17Sdinak 		{ CKA_VERIFY, NULL, 0 },
332*17Sdinak 		{ CKA_VERIFY_RECOVER, NULL, 0 },
333*17Sdinak 		{ CKA_WRAP, NULL, 0 },
334*17Sdinak 		/* 10 to 14 */
335*17Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
336*17Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
337*17Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* optional */
338*17Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
339*17Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
340*17Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
341*17Sdinak 	    };
342*17Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
343*17Sdinak 	int		i;
344*17Sdinak 	char		*hex_id = NULL;
345*17Sdinak 	int		hex_id_len = 0;
346*17Sdinak 	char		*hex_subject = NULL;
347*17Sdinak 	int		hex_subject_len = 0;
348*17Sdinak 
349*17Sdinak 	cryptodebug("inside display_pubkey");
350*17Sdinak 
351*17Sdinak 	/* Get the sizes of the attributes we need. */
352*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
353*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
354*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
355*17Sdinak 		    "Unable to get public key attribute sizes (%s)."),
356*17Sdinak 		    pkcs11_strerror(rv));
357*17Sdinak 		return (rv);
358*17Sdinak 	}
359*17Sdinak 
360*17Sdinak 	/* Allocate memory for each variable-length attribute. */
361*17Sdinak 	for (i = 4; i < n_attrs; i++) {
362*17Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
363*17Sdinak 		    attrs[i].ulValueLen == 0) {
364*17Sdinak 			cryptodebug("display_pubkey: *** should not happen");
365*17Sdinak 			attrs[i].ulValueLen = 0;
366*17Sdinak 			continue;
367*17Sdinak 		}
368*17Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
369*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
370*17Sdinak 			rv = CKR_HOST_MEMORY;
371*17Sdinak 			goto free_display_pubkey;
372*17Sdinak 		}
373*17Sdinak 	}
374*17Sdinak 
375*17Sdinak 	/* Now really get the attributes. */
376*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
377*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
378*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
379*17Sdinak 		    "Unable to get public key attributes (%s)."),
380*17Sdinak 		    pkcs11_strerror(rv));
381*17Sdinak 		goto free_display_pubkey;
382*17Sdinak 	}
383*17Sdinak 
384*17Sdinak 	/* Fill in all the optional temp variables. */
385*17Sdinak 	i = 10;
386*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
387*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
388*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
389*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
390*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
391*17Sdinak 
392*17Sdinak 	/* Get the key size for the object. */
393*17Sdinak 	key_size = get_key_size(sess, obj, key_type);
394*17Sdinak 
395*17Sdinak 	/* Display the object ... */
396*17Sdinak 		/* ... the label and what it is (and key size in bits) ... */
397*17Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
398*17Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
399*17Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
400*17Sdinak 	    class_str(CKO_PUBLIC_KEY));
401*17Sdinak 
402*17Sdinak 		/* ... the id ... */
403*17Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
404*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
405*17Sdinak 	else {
406*17Sdinak 		hex_id_len = 3 * id_len + 1;
407*17Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
408*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
409*17Sdinak 			rv = CKR_HOST_MEMORY;
410*17Sdinak 			goto free_display_pubkey;
411*17Sdinak 		}
412*17Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
413*17Sdinak 		    "\n\t\t", "");
414*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
415*17Sdinak 		free(hex_id);
416*17Sdinak 	}
417*17Sdinak 
418*17Sdinak 		/* ... the subject name ... */
419*17Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
420*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
421*17Sdinak 	else {
422*17Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
423*17Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
424*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
425*17Sdinak 			rv = CKR_HOST_MEMORY;
426*17Sdinak 			goto free_display_pubkey;
427*17Sdinak 		}
428*17Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
429*17Sdinak 		    hex_subject_len);
430*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
431*17Sdinak 		    hex_subject_len, hex_subject);
432*17Sdinak 		free(hex_subject);
433*17Sdinak 	}
434*17Sdinak 
435*17Sdinak 		/* ... the start date ... */
436*17Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
437*17Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
438*17Sdinak 	else
439*17Sdinak 		(void) fprintf(stdout, gettext(
440*17Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
441*17Sdinak 		    start_date->month, start_date->day, start_date->year);
442*17Sdinak 
443*17Sdinak 		/* ... the end date ... */
444*17Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
445*17Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
446*17Sdinak 	else
447*17Sdinak 		(void) fprintf(stdout, gettext(
448*17Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
449*17Sdinak 		    end_date->month, end_date->day, end_date->year);
450*17Sdinak 
451*17Sdinak 		/* ... and its capabilities */
452*17Sdinak 	(void) fprintf(stdout, "\t(%s, %s, %s",
453*17Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
454*17Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
455*17Sdinak 	    gettext("not modifiable"),
456*17Sdinak 	    trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
457*17Sdinak 	for (i = 4; i <= 9; i++) {
458*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
459*17Sdinak 		    attrs[i].ulValueLen != 0 &&
460*17Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
461*17Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
462*17Sdinak 	}
463*17Sdinak 	(void) fprintf(stdout, ")\n");
464*17Sdinak 
465*17Sdinak free_display_pubkey:
466*17Sdinak 	for (i = 4; i < n_attrs; i++)
467*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
468*17Sdinak 		    attrs[i].ulValueLen != 0)
469*17Sdinak 			free(attrs[i].pValue);
470*17Sdinak 	return (rv);
471*17Sdinak }
472*17Sdinak 
473*17Sdinak /*
474*17Sdinak  * Display secret key.
475*17Sdinak  */
476*17Sdinak static CK_RV
477*17Sdinak display_seckey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
478*17Sdinak {
479*17Sdinak 	CK_RV			rv = CKR_OK;
480*17Sdinak 	static CK_BBOOL		private;
481*17Sdinak 	static CK_BBOOL		modifiable;
482*17Sdinak 	static CK_KEY_TYPE	key_type;
483*17Sdinak 	static CK_ULONG		key_size;
484*17Sdinak 	CK_BYTE			*label = NULL;
485*17Sdinak 	CK_ULONG		label_len = 0;
486*17Sdinak 	CK_BYTE			*id = NULL;
487*17Sdinak 	CK_ULONG		id_len = 0;
488*17Sdinak 	CK_DATE			*start_date = NULL;
489*17Sdinak 	CK_ULONG		start_date_len = 0;
490*17Sdinak 	CK_DATE			*end_date = NULL;
491*17Sdinak 	CK_ULONG		end_date_len = 0;
492*17Sdinak 	CK_ATTRIBUTE		attrs[19] = {
493*17Sdinak 		/* 0 to 2 */
494*17Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
495*17Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
496*17Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
497*17Sdinak 		/* 3 to 14 */
498*17Sdinak 		{ CKA_DERIVE, NULL, 0 },
499*17Sdinak 		{ CKA_LOCAL, NULL, 0 },
500*17Sdinak 		{ CKA_ENCRYPT, NULL, 0 },
501*17Sdinak 		{ CKA_DECRYPT, NULL, 0 },
502*17Sdinak 		{ CKA_SIGN, NULL, 0 },
503*17Sdinak 		{ CKA_VERIFY, NULL, 0 },
504*17Sdinak 		{ CKA_WRAP, NULL, 0 },
505*17Sdinak 		{ CKA_UNWRAP, NULL, 0 },
506*17Sdinak 		{ CKA_SENSITIVE, NULL, 0 },
507*17Sdinak 		{ CKA_ALWAYS_SENSITIVE, NULL, 0 },
508*17Sdinak 		{ CKA_EXTRACTABLE, NULL, 0 },
509*17Sdinak 		{ CKA_NEVER_EXTRACTABLE, 0 },
510*17Sdinak 		/* 15 to 18 */
511*17Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
512*17Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
513*17Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
514*17Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
515*17Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
516*17Sdinak 	    };
517*17Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
518*17Sdinak 	int		i;
519*17Sdinak 	char		*hex_id = NULL;
520*17Sdinak 	int		hex_id_len = 0;
521*17Sdinak 
522*17Sdinak 	cryptodebug("inside display_seckey");
523*17Sdinak 
524*17Sdinak 	/* Get the sizes of the attributes we need. */
525*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
526*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
527*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
528*17Sdinak 		    "Unable to get secret key attribute sizes (%s)."),
529*17Sdinak 		    pkcs11_strerror(rv));
530*17Sdinak 		return (rv);
531*17Sdinak 	}
532*17Sdinak 
533*17Sdinak 	/* Allocate memory for each variable-length attribute. */
534*17Sdinak 	for (i = 3; i < n_attrs; i++) {
535*17Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
536*17Sdinak 		    attrs[i].ulValueLen == 0) {
537*17Sdinak 			cryptodebug("display_seckey: *** should not happen");
538*17Sdinak 			attrs[i].ulValueLen = 0;
539*17Sdinak 			continue;
540*17Sdinak 		}
541*17Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
542*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
543*17Sdinak 			rv = CKR_HOST_MEMORY;
544*17Sdinak 			goto free_display_seckey;
545*17Sdinak 		}
546*17Sdinak 	}
547*17Sdinak 
548*17Sdinak 	/* Now really get the attributes. */
549*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
550*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
551*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
552*17Sdinak 		    "Unable to get secret key attributes (%s)."),
553*17Sdinak 		    pkcs11_strerror(rv));
554*17Sdinak 		goto free_display_seckey;
555*17Sdinak 	}
556*17Sdinak 
557*17Sdinak 	/* Fill in all the optional temp variables. */
558*17Sdinak 	i = 15;
559*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
560*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
561*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
562*17Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
563*17Sdinak 
564*17Sdinak 	/* Get the key size for the object. */
565*17Sdinak 	key_size = get_key_size(sess, obj, key_type);
566*17Sdinak 
567*17Sdinak 	/* Display the object ... */
568*17Sdinak 		/* ... the label and what it is (and key size in bytes) ... */
569*17Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
570*17Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
571*17Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
572*17Sdinak 	    class_str(CKO_SECRET_KEY));
573*17Sdinak 
574*17Sdinak 		/* ... the id ... */
575*17Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
576*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
577*17Sdinak 	else {
578*17Sdinak 		hex_id_len = 3 * id_len + 1;
579*17Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
580*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
581*17Sdinak 			rv = CKR_HOST_MEMORY;
582*17Sdinak 			goto free_display_seckey;
583*17Sdinak 		}
584*17Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
585*17Sdinak 		    "\n\t\t", "");
586*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
587*17Sdinak 		free(hex_id);
588*17Sdinak 	}
589*17Sdinak 
590*17Sdinak 		/* ... the start date ... */
591*17Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
592*17Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
593*17Sdinak 	else
594*17Sdinak 		(void) fprintf(stdout, gettext(
595*17Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
596*17Sdinak 		    start_date->month, start_date->day, start_date->year);
597*17Sdinak 
598*17Sdinak 		/* ... the end date ... */
599*17Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
600*17Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
601*17Sdinak 	else
602*17Sdinak 		(void) fprintf(stdout, gettext(
603*17Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
604*17Sdinak 		    end_date->month, end_date->day, end_date->year);
605*17Sdinak 
606*17Sdinak 		/* ... and its capabilities */
607*17Sdinak 	(void) fprintf(stdout, "\t(%s, %s",
608*17Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
609*17Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
610*17Sdinak 	    gettext("not modifiable"));
611*17Sdinak 	for (i = 3; i <= 14; i++) {
612*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
613*17Sdinak 		    attrs[i].ulValueLen != 0 &&
614*17Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
615*17Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
616*17Sdinak 	}
617*17Sdinak 	(void) fprintf(stdout, ")\n");
618*17Sdinak 
619*17Sdinak free_display_seckey:
620*17Sdinak 	for (i = 3; i < n_attrs; i++)
621*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
622*17Sdinak 		    attrs[i].ulValueLen != 0)
623*17Sdinak 			free(attrs[i].pValue);
624*17Sdinak 	return (rv);
625*17Sdinak }
626*17Sdinak 
627*17Sdinak /*
628*17Sdinak  * Display certificate.
629*17Sdinak  */
630*17Sdinak static CK_RV
631*17Sdinak display_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
632*17Sdinak {
633*17Sdinak 	CK_RV			rv = CKR_OK;
634*17Sdinak 	static CK_BBOOL		private;
635*17Sdinak 	static CK_BBOOL		modifiable;
636*17Sdinak 	static CK_BBOOL		trusted;
637*17Sdinak 	CK_BYTE			*subject = NULL;
638*17Sdinak 	CK_ULONG		subject_len = 0;
639*17Sdinak 	CK_BYTE			*value = NULL;
640*17Sdinak 	CK_ULONG		value_len = 0;
641*17Sdinak 	CK_BYTE			*label = NULL;
642*17Sdinak 	CK_ULONG		label_len = 0;
643*17Sdinak 	CK_BYTE			*id = NULL;
644*17Sdinak 	CK_ULONG		id_len = 0;
645*17Sdinak 	CK_BYTE			*issuer = NULL;
646*17Sdinak 	CK_ULONG		issuer_len = 0;
647*17Sdinak 	CK_BYTE			*serial = NULL;
648*17Sdinak 	CK_ULONG		serial_len = 0;
649*17Sdinak 	CK_ATTRIBUTE		attrs[9] = {
650*17Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
651*17Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
652*17Sdinak 		{ CKA_TRUSTED, &trusted, sizeof (trusted) },
653*17Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
654*17Sdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
655*17Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
656*17Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
657*17Sdinak 		{ CKA_ISSUER, NULL, 0 },		/* optional */
658*17Sdinak 		{ CKA_SERIAL_NUMBER, NULL, 0 }		/* optional */
659*17Sdinak 	    };
660*17Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
661*17Sdinak 	int		i;
662*17Sdinak 	char		*hex_id = NULL;
663*17Sdinak 	int		hex_id_len = 0;
664*17Sdinak 	char		*hex_subject = NULL;
665*17Sdinak 	int		hex_subject_len = 0;
666*17Sdinak 	char		*hex_issuer = NULL;
667*17Sdinak 	int		hex_issuer_len = 0;
668*17Sdinak 	char		*hex_serial = NULL;
669*17Sdinak 	int		hex_serial_len = NULL;
670*17Sdinak 	uint32_t	serial_value = 0;
671*17Sdinak 	char		*hex_value = NULL;
672*17Sdinak 	int		hex_value_len = 0;
673*17Sdinak 
674*17Sdinak 	cryptodebug("inside display_cert");
675*17Sdinak 
676*17Sdinak 	/* Get the sizes of the attributes we need. */
677*17Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
678*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
679*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
680*17Sdinak 		    "Unable to get certificate attribute sizes (%s)."),
681*17Sdinak 		    pkcs11_strerror(rv));
682*17Sdinak 		return (rv);
683*17Sdinak 	}
684*17Sdinak 
685*17Sdinak 	/* Allocate memory for each variable-length attribute. */
686*17Sdinak 	for (i = 3; i < n_attrs; i++) {
687*17Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
688*17Sdinak 		    attrs[i].ulValueLen == 0) {
689*17Sdinak 			cryptodebug("display_cert: *** should not happen");
690*17Sdinak 			attrs[i].ulValueLen = 0;
691*17Sdinak 			continue;
692*17Sdinak 		}
693*17Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
694*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
695*17Sdinak 			rv = CKR_HOST_MEMORY;
696*17Sdinak 			goto free_display_cert;
697*17Sdinak 		}
698*17Sdinak 	}
699*17Sdinak 
700*17Sdinak 	/* Now really get the attributes. */
701*17Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
702*17Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
703*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
704*17Sdinak 		    "Unable to get certificate attributes (%s)."),
705*17Sdinak 		    pkcs11_strerror(rv));
706*17Sdinak 		goto free_display_cert;
707*17Sdinak 	}
708*17Sdinak 
709*17Sdinak 	/*
710*17Sdinak 	 * Fill in all the temp variables.  Subject and value are required.
711*17Sdinak 	 * The rest are optional.
712*17Sdinak 	 */
713*17Sdinak 	i = 3;
714*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
715*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &value, &value_len);
716*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
717*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
718*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &issuer, &issuer_len);
719*17Sdinak 	copy_attr_to_string(&(attrs[i++]), &serial, &serial_len);
720*17Sdinak 
721*17Sdinak 	/* Display the object ... */
722*17Sdinak 		/* ... the label and what it is ... */
723*17Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%s %s)\n"),
724*17Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
725*17Sdinak 	    gettext("<no label>"), "X.509", class_str(CKO_CERTIFICATE));
726*17Sdinak 
727*17Sdinak 		/* ... its capabilities ... */
728*17Sdinak 	(void) fprintf(stdout, gettext("\t(%s, %s, %s)\n"),
729*17Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
730*17Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
731*17Sdinak 	    gettext("not modifiable"),
732*17Sdinak 	    trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
733*17Sdinak 
734*17Sdinak 		/* ... the id ... */
735*17Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
736*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
737*17Sdinak 	else {
738*17Sdinak 		hex_id_len = 3 * id_len + 1;
739*17Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
740*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
741*17Sdinak 			rv = CKR_HOST_MEMORY;
742*17Sdinak 			goto free_display_cert;
743*17Sdinak 		}
744*17Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
745*17Sdinak 		    "\n\t\t", "");
746*17Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
747*17Sdinak 		free(hex_id);
748*17Sdinak 	}
749*17Sdinak 
750*17Sdinak 		/* ... the subject name ... */
751*17Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
752*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
753*17Sdinak 	else {
754*17Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
755*17Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
756*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
757*17Sdinak 			rv = CKR_HOST_MEMORY;
758*17Sdinak 			goto free_display_cert;
759*17Sdinak 		}
760*17Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
761*17Sdinak 		    hex_subject_len);
762*17Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
763*17Sdinak 		    hex_subject_len, hex_subject);
764*17Sdinak 		free(hex_subject);
765*17Sdinak 	}
766*17Sdinak 
767*17Sdinak 		/* ... the issuer name ... */
768*17Sdinak 	if (issuer_len == (CK_ULONG)-1 || issuer_len == 0)
769*17Sdinak 		(void) fprintf(stdout, gettext("\tIssuer:  --\n"));
770*17Sdinak 	else {
771*17Sdinak 		hex_issuer_len = 2 * issuer_len + 1;	/* best guesstimate */
772*17Sdinak 		if ((hex_issuer = malloc(hex_issuer_len)) == NULL) {
773*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
774*17Sdinak 			rv = CKR_HOST_MEMORY;
775*17Sdinak 			goto free_display_cert;
776*17Sdinak 		}
777*17Sdinak 		rdnseq_to_str(issuer, issuer_len, hex_issuer, hex_issuer_len);
778*17Sdinak 		(void) fprintf(stdout, gettext("\tIssuer:  %.*s\n"),
779*17Sdinak 		    hex_issuer_len, hex_issuer);
780*17Sdinak 		free(hex_issuer);
781*17Sdinak 	}
782*17Sdinak 
783*17Sdinak 		/* ... the serial number ... */
784*17Sdinak 	if (serial_len == (CK_ULONG)-1 || serial_len == 0)
785*17Sdinak 		(void) fprintf(stdout, gettext("\tSerial:  --\n"));
786*17Sdinak 	else {
787*17Sdinak 		hex_serial_len = 3 * serial_len + 1;
788*17Sdinak 		if ((hex_serial = malloc(hex_serial_len)) == NULL) {
789*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
790*17Sdinak 			rv = CKR_HOST_MEMORY;
791*17Sdinak 			goto free_display_cert;
792*17Sdinak 		}
793*17Sdinak 		octetify(serial, serial_len, hex_serial, hex_serial_len,
794*17Sdinak 		    B_FALSE, B_FALSE, 60, "\n\t\t", "");
795*17Sdinak 		if (serial_len > 4)
796*17Sdinak 			(void) fprintf(stdout, gettext("\tSerial:  %s\n"),
797*17Sdinak 			    hex_serial);
798*17Sdinak 		else {
799*17Sdinak 			for (i = 0; i < serial_len; i++) {
800*17Sdinak 				serial_value <<= 8;
801*17Sdinak 				serial_value |= (serial[i] & 0xff);
802*17Sdinak 			}
803*17Sdinak 			(void) fprintf(stdout, gettext("\tSerial:  %s (%d)\n"),
804*17Sdinak 			    hex_serial, serial_value);
805*17Sdinak 		}
806*17Sdinak 		free(hex_serial);
807*17Sdinak 	}
808*17Sdinak 
809*17Sdinak 		/* ... and the value */
810*17Sdinak 	if (value_len == (CK_ULONG)-1 || value_len == 0)
811*17Sdinak 		(void) fprintf(stdout, gettext("\tValue:  --\n"));
812*17Sdinak 	else {
813*17Sdinak 		hex_value_len = 3 * value_len + 1;
814*17Sdinak 		if ((hex_value = malloc(hex_value_len)) == NULL) {
815*17Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
816*17Sdinak 			rv = CKR_HOST_MEMORY;
817*17Sdinak 			goto free_display_cert;
818*17Sdinak 		}
819*17Sdinak 		octetify(value, value_len, hex_value, hex_value_len,
820*17Sdinak 		    B_FALSE, B_FALSE, 60, "\n\t\t", "");
821*17Sdinak 		(void) fprintf(stdout, gettext("\tValue:  %s\n"), hex_value);
822*17Sdinak 		free(hex_value);
823*17Sdinak 	}
824*17Sdinak 
825*17Sdinak free_display_cert:
826*17Sdinak 	for (i = 3; i < n_attrs; i++)
827*17Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
828*17Sdinak 		    attrs[i].ulValueLen != 0)
829*17Sdinak 			free(attrs[i].pValue);
830*17Sdinak 	return (rv);
831*17Sdinak }
832*17Sdinak 
833*17Sdinak /*
834*17Sdinak  * List token object.
835*17Sdinak  */
836*17Sdinak int
837*17Sdinak pk_list(int argc, char *argv[])
838*17Sdinak {
839*17Sdinak 	int			opt;
840*17Sdinak 	extern int		optind;
841*17Sdinak 	extern char		*optarg;
842*17Sdinak 	char			*token_name = NULL;
843*17Sdinak 	char			*manuf_id = NULL;
844*17Sdinak 	char			*serial_no = NULL;
845*17Sdinak 	char			full_name[FULL_NAME_LEN];
846*17Sdinak 	boolean_t		public_objs = B_FALSE;
847*17Sdinak 	boolean_t		private_objs = B_FALSE;
848*17Sdinak 	CK_BYTE			*list_label = NULL;
849*17Sdinak 	int			obj_type = 0x00;
850*17Sdinak 	CK_SLOT_ID		slot_id;
851*17Sdinak 	CK_FLAGS		pin_state;
852*17Sdinak 	CK_UTF8CHAR_PTR		pin = NULL;
853*17Sdinak 	CK_ULONG		pinlen = 0;
854*17Sdinak 	CK_SESSION_HANDLE	sess;
855*17Sdinak 	CK_OBJECT_HANDLE	*objs;
856*17Sdinak 	CK_ULONG		num_objs;
857*17Sdinak 	CK_RV			rv = CKR_OK;
858*17Sdinak 	int			i;
859*17Sdinak 	static CK_OBJECT_CLASS	objclass;
860*17Sdinak 	CK_ATTRIBUTE		class_attr =
861*17Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) };
862*17Sdinak 
863*17Sdinak 	cryptodebug("inside pk_list");
864*17Sdinak 
865*17Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
866*17Sdinak 	while ((opt = getopt(argc, argv, "p(private)P(public)l:(label)")) !=
867*17Sdinak 	    EOF) {
868*17Sdinak 		switch (opt) {
869*17Sdinak 		case 'p':	/* private objects */
870*17Sdinak 			private_objs = B_TRUE;
871*17Sdinak 			obj_type |= PK_PRIVATE_OBJ;
872*17Sdinak 			break;
873*17Sdinak 		case 'P':	/* public objects */
874*17Sdinak 			public_objs = B_TRUE;
875*17Sdinak 			obj_type |= PK_PUBLIC_OBJ;
876*17Sdinak 			break;
877*17Sdinak 		case 'l':	/* object with specific label */
878*17Sdinak 			if (list_label)
879*17Sdinak 				return (PK_ERR_USAGE);
880*17Sdinak 			list_label = (CK_BYTE *)optarg;
881*17Sdinak 			break;
882*17Sdinak 		default:
883*17Sdinak 			return (PK_ERR_USAGE);
884*17Sdinak 			break;
885*17Sdinak 		}
886*17Sdinak 	}
887*17Sdinak 
888*17Sdinak 	/* If nothing specified, default is public objects. */
889*17Sdinak 	if (!public_objs && !private_objs) {
890*17Sdinak 		public_objs = B_TRUE;
891*17Sdinak 		obj_type |= PK_PUBLIC_OBJ;
892*17Sdinak 	}
893*17Sdinak 
894*17Sdinak 	/* No additional args allowed. */
895*17Sdinak 	argc -= optind;
896*17Sdinak 	argv += optind;
897*17Sdinak 	if (argc)
898*17Sdinak 		return (PK_ERR_USAGE);
899*17Sdinak 	/* Done parsing command line options. */
900*17Sdinak 
901*17Sdinak 	/* List operation only supported on softtoken. */
902*17Sdinak 	if (token_name == NULL)
903*17Sdinak 		token_name = SOFT_TOKEN_LABEL;
904*17Sdinak 	if (manuf_id == NULL)
905*17Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
906*17Sdinak 	if (serial_no == NULL)
907*17Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
908*17Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
909*17Sdinak 
910*17Sdinak 	/* Find the slot with token. */
911*17Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
912*17Sdinak 	    &pin_state)) != CKR_OK) {
913*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
914*17Sdinak 		    "Unable to find token %s (%s)."), full_name,
915*17Sdinak 		    pkcs11_strerror(rv));
916*17Sdinak 		return (PK_ERR_PK11);
917*17Sdinak 	}
918*17Sdinak 
919*17Sdinak 	/* If private objects are to be listed, user must be logged in. */
920*17Sdinak 	if (private_objs) {
921*17Sdinak 		/* Get the user's PIN. */
922*17Sdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
923*17Sdinak 		    &pin, &pinlen)) != CKR_OK) {
924*17Sdinak 			cryptoerror(LOG_STDERR,
925*17Sdinak 			    gettext("Unable to get token passphrase (%s)."),
926*17Sdinak 			    pkcs11_strerror(rv));
927*17Sdinak 			quick_finish(NULL);
928*17Sdinak 			return (PK_ERR_PK11);
929*17Sdinak 		}
930*17Sdinak 
931*17Sdinak 		/* Logging in user R/O into the token is sufficient. */
932*17Sdinak 		cryptodebug("logging in with readonly session");
933*17Sdinak 		if ((rv = quick_start(slot_id, 0, pin, pinlen, &sess)) !=
934*17Sdinak 		    CKR_OK) {
935*17Sdinak 			cryptoerror(LOG_STDERR,
936*17Sdinak 			    gettext("Unable to log into token (%s)."),
937*17Sdinak 			    pkcs11_strerror(rv));
938*17Sdinak 			quick_finish(sess);
939*17Sdinak 			return (PK_ERR_PK11);
940*17Sdinak 		}
941*17Sdinak 	/* Otherwise, just create a session. */
942*17Sdinak 	} else {
943*17Sdinak 		cryptodebug("opening a readonly session");
944*17Sdinak 		if ((rv = open_sess(slot_id, 0, &sess)) != CKR_OK) {
945*17Sdinak 			cryptoerror(LOG_STDERR,
946*17Sdinak 			    gettext("Unable to open token session (%s)."),
947*17Sdinak 			    pkcs11_strerror(rv));
948*17Sdinak 			quick_finish(sess);
949*17Sdinak 			return (PK_ERR_PK11);
950*17Sdinak 		}
951*17Sdinak 	}
952*17Sdinak 
953*17Sdinak 	/* Find the object(s) with the given label and/or type. */
954*17Sdinak 	if ((rv = find_objs(sess, obj_type, list_label, &objs, &num_objs)) !=
955*17Sdinak 	    CKR_OK) {
956*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
957*17Sdinak 		    "Unable to find token objects (%s)."), pkcs11_strerror(rv));
958*17Sdinak 		quick_finish(sess);
959*17Sdinak 		return (PK_ERR_PK11);
960*17Sdinak 	}
961*17Sdinak 
962*17Sdinak 	if (num_objs == 0) {
963*17Sdinak 		cryptoerror(LOG_STDERR, gettext("No objects found."));
964*17Sdinak 		quick_finish(sess);
965*17Sdinak 		return (0);
966*17Sdinak 	}
967*17Sdinak 
968*17Sdinak 	/* List the objects found. */
969*17Sdinak 	for (i = 0; i < num_objs; i++) {
970*17Sdinak 		/* Get object class first, then decide what is next. */
971*17Sdinak 		cryptodebug("calling C_GetAttributeValue for object class");
972*17Sdinak 		if ((rv = C_GetAttributeValue(sess, objs[i], &class_attr, 1))
973*17Sdinak 		    != CKR_OK) {
974*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
975*17Sdinak 			    "Unable to get object #%d class attribute (%s)."),
976*17Sdinak 			    i+1, pkcs11_strerror(rv));
977*17Sdinak 			continue;
978*17Sdinak 		}
979*17Sdinak 
980*17Sdinak 		/* Display based on the type of object. */
981*17Sdinak 		switch (objclass) {
982*17Sdinak 		case CKO_CERTIFICATE:
983*17Sdinak 			if ((rv = display_cert(sess, objs[i], i+1)) != CKR_OK)
984*17Sdinak 				cryptoerror(LOG_STDERR,
985*17Sdinak 				    gettext("Unable to display certificate."));
986*17Sdinak 			break;
987*17Sdinak 		case CKO_PUBLIC_KEY:
988*17Sdinak 			if ((rv = display_pubkey(sess, objs[i], i+1)) != CKR_OK)
989*17Sdinak 				cryptoerror(LOG_STDERR,
990*17Sdinak 				    gettext("Unable to display public key."));
991*17Sdinak 			break;
992*17Sdinak 		case CKO_PRIVATE_KEY:
993*17Sdinak 			if ((rv = display_prikey(sess, objs[i], i+1)) != CKR_OK)
994*17Sdinak 				cryptoerror(LOG_STDERR,
995*17Sdinak 				    gettext("Unable to display private key."));
996*17Sdinak 			break;
997*17Sdinak 		case CKO_SECRET_KEY:
998*17Sdinak 			if ((rv = display_seckey(sess, objs[i], i+1)) != CKR_OK)
999*17Sdinak 				cryptoerror(LOG_STDERR,
1000*17Sdinak 				    gettext("Unable to display secret key."));
1001*17Sdinak 			break;
1002*17Sdinak 		case CKO_DATA:
1003*17Sdinak 			cryptoerror(LOG_STDERR,
1004*17Sdinak 			    gettext("Data object display not implemented."));
1005*17Sdinak 			break;
1006*17Sdinak 		default:
1007*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
1008*17Sdinak 			    "Unknown token object class (0x%02x)."), objclass);
1009*17Sdinak 			break;
1010*17Sdinak 		}
1011*17Sdinak 	}
1012*17Sdinak 
1013*17Sdinak 	/* Clean up. */
1014*17Sdinak 	quick_finish(sess);
1015*17Sdinak 	return (0);
1016*17Sdinak }
1017