xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/list.c (revision 864:75df3e9f93de)
117Sdinak /*
217Sdinak  * CDDL HEADER START
317Sdinak  *
417Sdinak  * The contents of this file are subject to the terms of the
517Sdinak  * Common Development and Distribution License, Version 1.0 only
617Sdinak  * (the "License").  You may not use this file except in compliance
717Sdinak  * with the License.
817Sdinak  *
917Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1017Sdinak  * or http://www.opensolaris.org/os/licensing.
1117Sdinak  * See the License for the specific language governing permissions
1217Sdinak  * and limitations under the License.
1317Sdinak  *
1417Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
1517Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1617Sdinak  * If applicable, add the following below this CDDL HEADER, with the
1717Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
1817Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
1917Sdinak  *
2017Sdinak  * CDDL HEADER END
2117Sdinak  */
2217Sdinak /*
2317Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2417Sdinak  * Use is subject to license terms.
2517Sdinak  */
2617Sdinak 
2717Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
2817Sdinak 
2917Sdinak /*
3017Sdinak  * This file implements the token object list operation for this tool.
3117Sdinak  * It loads the PKCS#11 modules, finds the object to list, lists it,
3217Sdinak  * and cleans up.  User must be logged into the token to list private
3317Sdinak  * objects.
3417Sdinak  */
3517Sdinak 
3617Sdinak #include <stdio.h>
3717Sdinak #include <errno.h>
3817Sdinak #include <string.h>
3917Sdinak #include <cryptoutil.h>
4017Sdinak #include <security/cryptoki.h>
4117Sdinak #include "common.h"
4217Sdinak #include "derparse.h"
4317Sdinak 
4417Sdinak /*
4517Sdinak  * Get key size based on the key type.
4617Sdinak  */
4717Sdinak static CK_ULONG
4817Sdinak get_key_size(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, CK_KEY_TYPE key_type)
4917Sdinak {
5017Sdinak 	CK_RV		rv = CKR_OK;
5117Sdinak 	CK_ULONG	key_size;
5217Sdinak 	CK_ATTRIBUTE	modulus_sz =
5317Sdinak 		{ CKA_MODULUS, NULL, 0 };	/* RSA */
5417Sdinak 	CK_ATTRIBUTE	prime_sz =
5517Sdinak 		{ CKA_PRIME, NULL, 0 };		/* DSA, DH X9.42 */
5617Sdinak 	CK_ATTRIBUTE	value_sz =
5717Sdinak 		{ CKA_VALUE, NULL_PTR, 0 };	/* DH, DES/DES3, AES, GENERIC */
5817Sdinak 
5917Sdinak 	cryptodebug("inside get_key_size");
6017Sdinak 
6117Sdinak 	switch (key_type) {
6217Sdinak 	case CKK_RSA:
6317Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &modulus_sz, 1)) !=
6417Sdinak 		    CKR_OK) {
6517Sdinak 			cryptoerror(LOG_STDERR, gettext(
6617Sdinak 			    "Unable to get modulus attribute size (%s)."),
6717Sdinak 			    pkcs11_strerror(rv));
6817Sdinak 		} else
6917Sdinak 			/* Convert key size to bits. */
7017Sdinak 			key_size = modulus_sz.ulValueLen * 8;
7117Sdinak 		break;
7217Sdinak 	case CKK_DH:
7317Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
7417Sdinak 		    CKR_OK) {
7517Sdinak 			cryptoerror(LOG_STDERR, gettext(
7617Sdinak 			    "Unable to get value attribute size (%s)."),
7717Sdinak 			    pkcs11_strerror(rv));
7817Sdinak 		} else
7917Sdinak 			/* Convert key size to bits. */
8017Sdinak 			key_size = value_sz.ulValueLen * 8;
8117Sdinak 		break;
8217Sdinak 	case CKK_X9_42_DH:
8317Sdinak 	case CKK_DSA:
8417Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &prime_sz, 1)) !=
8517Sdinak 		    CKR_OK) {
8617Sdinak 			cryptoerror(LOG_STDERR, gettext(
8717Sdinak 			    "Unable to get prime attribute size (%s)."),
8817Sdinak 			    pkcs11_strerror(rv));
8917Sdinak 		} else
9017Sdinak 			/* Convert key size to bits. */
9117Sdinak 			key_size = prime_sz.ulValueLen * 8;
9217Sdinak 		break;
9317Sdinak 	case CKK_DES:
9417Sdinak 	case CKK_DES3:
9517Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
9617Sdinak 		    CKR_OK) {
9717Sdinak 			cryptoerror(LOG_STDERR, gettext(
9817Sdinak 			    "Unable to get value attribute size (%s)."),
9917Sdinak 			    pkcs11_strerror(rv));
10017Sdinak 		} else
10117Sdinak 			/* Convert key size to bits -- omitting parity bit. */
10217Sdinak 			key_size = value_sz.ulValueLen * 7;
10317Sdinak 		break;
10417Sdinak 	case CKK_AES:
10517Sdinak 	case CKK_GENERIC_SECRET:
10617Sdinak 		if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
10717Sdinak 		    CKR_OK) {
10817Sdinak 			cryptoerror(LOG_STDERR, gettext(
10917Sdinak 			    "Unable to get value attribute size (%s)."),
11017Sdinak 			    pkcs11_strerror(rv));
11117Sdinak 		} else
11217Sdinak 			/* Convert key size to bits. */
11317Sdinak 			key_size = value_sz.ulValueLen * 8;
11417Sdinak 		break;
11517Sdinak 	default:
11617Sdinak 		cryptoerror(LOG_STDERR, gettext(
11717Sdinak 		    "Unknown object key type (0x%02x)."), key_type);
11817Sdinak 		break;
11917Sdinak 	}
12017Sdinak 
12117Sdinak 	return (key_size);
12217Sdinak }
12317Sdinak 
12417Sdinak /*
12517Sdinak  * Display private key.
12617Sdinak  */
12717Sdinak static CK_RV
12817Sdinak display_prikey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
12917Sdinak {
13017Sdinak 	CK_RV			rv = CKR_OK;
13117Sdinak 	static CK_BBOOL		private;
13217Sdinak 	static CK_BBOOL		modifiable;
13317Sdinak 	static CK_KEY_TYPE	key_type;
13417Sdinak 	CK_ULONG		key_size;
13517Sdinak 	CK_BYTE			*label = NULL;
13617Sdinak 	CK_ULONG		label_len = 0;
13717Sdinak 	CK_BYTE			*id = NULL;
13817Sdinak 	CK_ULONG		id_len = 0;
13917Sdinak 	CK_BYTE			*subject = NULL;
14017Sdinak 	CK_ULONG		subject_len = 0;
14117Sdinak 	CK_DATE			*start_date = NULL;
14217Sdinak 	CK_ULONG		start_date_len = 0;
14317Sdinak 	CK_DATE			*end_date = NULL;
14417Sdinak 	CK_ULONG		end_date_len = 0;
14517Sdinak 	CK_ATTRIBUTE		attrs[18] = {
14617Sdinak 		/* 0 to 2 */
14717Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
14817Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
14917Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
15017Sdinak 		/* 3 to 12 */
15117Sdinak 		{ CKA_DERIVE, NULL, 0 },
15217Sdinak 		{ CKA_LOCAL, NULL, 0 },
15317Sdinak 		{ CKA_DECRYPT, NULL, 0 },
15417Sdinak 		{ CKA_SIGN, NULL, 0 },
15517Sdinak 		{ CKA_SIGN_RECOVER, NULL, 0 },
15617Sdinak 		{ CKA_UNWRAP, NULL, 0 },
15717Sdinak 		{ CKA_SENSITIVE, NULL, 0 },
15817Sdinak 		{ CKA_ALWAYS_SENSITIVE, NULL, 0 },
15917Sdinak 		{ CKA_EXTRACTABLE, NULL, 0 },
16017Sdinak 		{ CKA_NEVER_EXTRACTABLE, NULL, 0 },
16117Sdinak 		/* 13 to 17 */
16217Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
16317Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
16417Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* optional */
16517Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
16617Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
16717Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
16817Sdinak 	    };
16917Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
17017Sdinak 	int		i;
17117Sdinak 	char		*hex_id = NULL;
17217Sdinak 	int		hex_id_len = 0;
17317Sdinak 	char		*hex_subject = NULL;
17417Sdinak 	int		hex_subject_len = 0;
17517Sdinak 
17617Sdinak 	cryptodebug("inside display_prikey");
17717Sdinak 
17817Sdinak 	/* Get the sizes of the attributes we need. */
17917Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
18017Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
18117Sdinak 		cryptoerror(LOG_STDERR, gettext(
18217Sdinak 		    "Unable to get private key attribute sizes (%s)."),
18317Sdinak 		    pkcs11_strerror(rv));
18417Sdinak 		return (rv);
18517Sdinak 	}
18617Sdinak 
18717Sdinak 	/* Allocate memory for each variable-length attribute. */
18817Sdinak 	for (i = 3; i < n_attrs; i++) {
18917Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
19017Sdinak 		    attrs[i].ulValueLen == 0) {
19117Sdinak 			cryptodebug("display_prikey: *** should not happen");
19217Sdinak 			attrs[i].ulValueLen = 0;
19317Sdinak 			continue;
19417Sdinak 		}
19517Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
19617Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
19717Sdinak 			rv = CKR_HOST_MEMORY;
19817Sdinak 			goto free_display_prikey;
19917Sdinak 		}
20017Sdinak 	}
20117Sdinak 
20217Sdinak 	/* Now really get the attributes. */
20317Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
20417Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
20517Sdinak 		cryptoerror(LOG_STDERR, gettext(
20617Sdinak 		    "Unable to get private key attributes (%s)."),
20717Sdinak 		    pkcs11_strerror(rv));
20817Sdinak 		goto free_display_prikey;
20917Sdinak 	}
21017Sdinak 
21117Sdinak 	/* Fill in all the optional temp variables. */
21217Sdinak 	i = 13;
21317Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
21417Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
21517Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
21617Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
21717Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
21817Sdinak 
21917Sdinak 	/* Get the key size for the object. */
22017Sdinak 	key_size = get_key_size(sess, obj, key_type);
22117Sdinak 
22217Sdinak 	/* Display the object ... */
22317Sdinak 		/* ... the label and what it is (and key size in bits) ... */
22417Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
22517Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
22617Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
22717Sdinak 	    class_str(CKO_PRIVATE_KEY));
22817Sdinak 
22917Sdinak 		/* ... the id ... */
23017Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
23117Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
23217Sdinak 	else {
23317Sdinak 		hex_id_len = 3 * id_len + 1;
23417Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
23517Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
23617Sdinak 			rv = CKR_HOST_MEMORY;
23717Sdinak 			goto free_display_prikey;
23817Sdinak 		}
23917Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
24017Sdinak 		    "\n\t\t", "");
24117Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
24217Sdinak 		free(hex_id);
24317Sdinak 	}
24417Sdinak 
24517Sdinak 		/* ... the subject name ... */
24617Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
24717Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
24817Sdinak 	else {
24917Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
25017Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
25117Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
25217Sdinak 			rv = CKR_HOST_MEMORY;
25317Sdinak 			goto free_display_prikey;
25417Sdinak 		}
25517Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
25617Sdinak 		    hex_subject_len);
25717Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
25817Sdinak 		    hex_subject_len, hex_subject);
25917Sdinak 		free(hex_subject);
26017Sdinak 	}
26117Sdinak 
26217Sdinak 		/* ... the start date ... */
26317Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
26417Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
26517Sdinak 	else
26617Sdinak 		(void) fprintf(stdout, gettext(
26717Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
26817Sdinak 		    start_date->month, start_date->day, start_date->year);
26917Sdinak 
27017Sdinak 		/* ... the end date ... */
27117Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
27217Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
27317Sdinak 	else
27417Sdinak 		(void) fprintf(stdout, gettext(
27517Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
27617Sdinak 		    end_date->month, end_date->day, end_date->year);
27717Sdinak 
27817Sdinak 		/* ... and its capabilities */
27917Sdinak 	(void) fprintf(stdout, "\t(%s, %s",
28017Sdinak 	    private != pk_false ? gettext("private") : gettext("public"),
28117Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
28217Sdinak 	    gettext("not modifiable"));
28317Sdinak 	for (i = 3; i <= 12; i++) {
28417Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
28517Sdinak 		    attrs[i].ulValueLen != 0 &&
28617Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
28717Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
28817Sdinak 	}
28917Sdinak 	(void) fprintf(stdout, ")\n");
29017Sdinak 
29117Sdinak free_display_prikey:
29217Sdinak 	for (i = 3; i < n_attrs; i++)
29317Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
29417Sdinak 		    attrs[i].ulValueLen != 0)
29517Sdinak 			free(attrs[i].pValue);
29617Sdinak 	return (rv);
29717Sdinak }
29817Sdinak 
29917Sdinak /*
30017Sdinak  * Display public key.
30117Sdinak  */
30217Sdinak static CK_RV
30317Sdinak display_pubkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
30417Sdinak {
30517Sdinak 	CK_RV			rv = CKR_OK;
30617Sdinak 	static CK_BBOOL		private;
30717Sdinak 	static CK_BBOOL		modifiable;
30817Sdinak 	static CK_BBOOL		trusted;
30917Sdinak 	static CK_KEY_TYPE	key_type;
31017Sdinak 	CK_ULONG		key_size;
31117Sdinak 	CK_BYTE			*label = NULL;
31217Sdinak 	CK_ULONG		label_len = 0;
31317Sdinak 	CK_BYTE			*id = NULL;
31417Sdinak 	CK_ULONG		id_len = 0;
31517Sdinak 	CK_BYTE			*subject = NULL;
31617Sdinak 	CK_ULONG		subject_len = 0;
31717Sdinak 	CK_DATE			*start_date = NULL;
31817Sdinak 	CK_ULONG		start_date_len = 0;
31917Sdinak 	CK_DATE			*end_date = NULL;
32017Sdinak 	CK_ULONG		end_date_len = 0;
32117Sdinak 	CK_ATTRIBUTE		attrs[15] = {
32217Sdinak 		/* 0 to 3 */
32317Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
32417Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
32517Sdinak 		{ CKA_TRUSTED, &trusted, sizeof (trusted) },
32617Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
32717Sdinak 		/* 4 to 9 */
32817Sdinak 		{ CKA_DERIVE, NULL, 0 },
32917Sdinak 		{ CKA_LOCAL, NULL, 0 },
33017Sdinak 		{ CKA_ENCRYPT, NULL, 0 },
33117Sdinak 		{ CKA_VERIFY, NULL, 0 },
33217Sdinak 		{ CKA_VERIFY_RECOVER, NULL, 0 },
33317Sdinak 		{ CKA_WRAP, NULL, 0 },
33417Sdinak 		/* 10 to 14 */
33517Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
33617Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
33717Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* optional */
33817Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
33917Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
34017Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
34117Sdinak 	    };
34217Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
34317Sdinak 	int		i;
34417Sdinak 	char		*hex_id = NULL;
34517Sdinak 	int		hex_id_len = 0;
34617Sdinak 	char		*hex_subject = NULL;
34717Sdinak 	int		hex_subject_len = 0;
34817Sdinak 
34917Sdinak 	cryptodebug("inside display_pubkey");
35017Sdinak 
35117Sdinak 	/* Get the sizes of the attributes we need. */
35217Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
35317Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
35417Sdinak 		cryptoerror(LOG_STDERR, gettext(
35517Sdinak 		    "Unable to get public key attribute sizes (%s)."),
35617Sdinak 		    pkcs11_strerror(rv));
35717Sdinak 		return (rv);
35817Sdinak 	}
35917Sdinak 
36017Sdinak 	/* Allocate memory for each variable-length attribute. */
36117Sdinak 	for (i = 4; i < n_attrs; i++) {
36217Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
36317Sdinak 		    attrs[i].ulValueLen == 0) {
36417Sdinak 			cryptodebug("display_pubkey: *** should not happen");
36517Sdinak 			attrs[i].ulValueLen = 0;
36617Sdinak 			continue;
36717Sdinak 		}
36817Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
36917Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
37017Sdinak 			rv = CKR_HOST_MEMORY;
37117Sdinak 			goto free_display_pubkey;
37217Sdinak 		}
37317Sdinak 	}
37417Sdinak 
37517Sdinak 	/* Now really get the attributes. */
37617Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
37717Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
37817Sdinak 		cryptoerror(LOG_STDERR, gettext(
37917Sdinak 		    "Unable to get public key attributes (%s)."),
38017Sdinak 		    pkcs11_strerror(rv));
38117Sdinak 		goto free_display_pubkey;
38217Sdinak 	}
38317Sdinak 
38417Sdinak 	/* Fill in all the optional temp variables. */
38517Sdinak 	i = 10;
38617Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
38717Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
38817Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
38917Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
39017Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
39117Sdinak 
39217Sdinak 	/* Get the key size for the object. */
39317Sdinak 	key_size = get_key_size(sess, obj, key_type);
39417Sdinak 
39517Sdinak 	/* Display the object ... */
39617Sdinak 		/* ... the label and what it is (and key size in bits) ... */
39717Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
39817Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
39917Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
40017Sdinak 	    class_str(CKO_PUBLIC_KEY));
40117Sdinak 
40217Sdinak 		/* ... the id ... */
40317Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
40417Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
40517Sdinak 	else {
40617Sdinak 		hex_id_len = 3 * id_len + 1;
40717Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
40817Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
40917Sdinak 			rv = CKR_HOST_MEMORY;
41017Sdinak 			goto free_display_pubkey;
41117Sdinak 		}
41217Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
41317Sdinak 		    "\n\t\t", "");
41417Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
41517Sdinak 		free(hex_id);
41617Sdinak 	}
41717Sdinak 
41817Sdinak 		/* ... the subject name ... */
41917Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
42017Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
42117Sdinak 	else {
42217Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
42317Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
42417Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
42517Sdinak 			rv = CKR_HOST_MEMORY;
42617Sdinak 			goto free_display_pubkey;
42717Sdinak 		}
42817Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
42917Sdinak 		    hex_subject_len);
43017Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
43117Sdinak 		    hex_subject_len, hex_subject);
43217Sdinak 		free(hex_subject);
43317Sdinak 	}
43417Sdinak 
43517Sdinak 		/* ... the start date ... */
43617Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
43717Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
43817Sdinak 	else
43917Sdinak 		(void) fprintf(stdout, gettext(
44017Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
44117Sdinak 		    start_date->month, start_date->day, start_date->year);
44217Sdinak 
44317Sdinak 		/* ... the end date ... */
44417Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
44517Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
44617Sdinak 	else
44717Sdinak 		(void) fprintf(stdout, gettext(
44817Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
44917Sdinak 		    end_date->month, end_date->day, end_date->year);
45017Sdinak 
45117Sdinak 		/* ... and its capabilities */
45217Sdinak 	(void) fprintf(stdout, "\t(%s, %s, %s",
45317Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
45417Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
45517Sdinak 	    gettext("not modifiable"),
45617Sdinak 	    trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
45717Sdinak 	for (i = 4; i <= 9; i++) {
45817Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
45917Sdinak 		    attrs[i].ulValueLen != 0 &&
46017Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
46117Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
46217Sdinak 	}
46317Sdinak 	(void) fprintf(stdout, ")\n");
46417Sdinak 
46517Sdinak free_display_pubkey:
46617Sdinak 	for (i = 4; i < n_attrs; i++)
46717Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
46817Sdinak 		    attrs[i].ulValueLen != 0)
46917Sdinak 			free(attrs[i].pValue);
47017Sdinak 	return (rv);
47117Sdinak }
47217Sdinak 
47317Sdinak /*
47417Sdinak  * Display secret key.
47517Sdinak  */
47617Sdinak static CK_RV
47717Sdinak display_seckey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
47817Sdinak {
47917Sdinak 	CK_RV			rv = CKR_OK;
48017Sdinak 	static CK_BBOOL		private;
48117Sdinak 	static CK_BBOOL		modifiable;
48217Sdinak 	static CK_KEY_TYPE	key_type;
48317Sdinak 	static CK_ULONG		key_size;
48417Sdinak 	CK_BYTE			*label = NULL;
48517Sdinak 	CK_ULONG		label_len = 0;
48617Sdinak 	CK_BYTE			*id = NULL;
48717Sdinak 	CK_ULONG		id_len = 0;
48817Sdinak 	CK_DATE			*start_date = NULL;
48917Sdinak 	CK_ULONG		start_date_len = 0;
49017Sdinak 	CK_DATE			*end_date = NULL;
49117Sdinak 	CK_ULONG		end_date_len = 0;
49217Sdinak 	CK_ATTRIBUTE		attrs[19] = {
49317Sdinak 		/* 0 to 2 */
49417Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
49517Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
49617Sdinak 		{ CKA_KEY_TYPE, &key_type, sizeof (key_type) },
49717Sdinak 		/* 3 to 14 */
49817Sdinak 		{ CKA_DERIVE, NULL, 0 },
49917Sdinak 		{ CKA_LOCAL, NULL, 0 },
50017Sdinak 		{ CKA_ENCRYPT, NULL, 0 },
50117Sdinak 		{ CKA_DECRYPT, NULL, 0 },
50217Sdinak 		{ CKA_SIGN, NULL, 0 },
50317Sdinak 		{ CKA_VERIFY, NULL, 0 },
50417Sdinak 		{ CKA_WRAP, NULL, 0 },
50517Sdinak 		{ CKA_UNWRAP, NULL, 0 },
50617Sdinak 		{ CKA_SENSITIVE, NULL, 0 },
50717Sdinak 		{ CKA_ALWAYS_SENSITIVE, NULL, 0 },
50817Sdinak 		{ CKA_EXTRACTABLE, NULL, 0 },
50917Sdinak 		{ CKA_NEVER_EXTRACTABLE, 0 },
51017Sdinak 		/* 15 to 18 */
51117Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
51217Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
51317Sdinak 		{ CKA_START_DATE, NULL, 0 },		/* optional */
51417Sdinak 		{ CKA_END_DATE, NULL, 0 }		/* optional */
51517Sdinak 		/* not displaying CKA_KEY_GEN_MECHANISM */
51617Sdinak 	    };
51717Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
51817Sdinak 	int		i;
51917Sdinak 	char		*hex_id = NULL;
52017Sdinak 	int		hex_id_len = 0;
52117Sdinak 
52217Sdinak 	cryptodebug("inside display_seckey");
52317Sdinak 
52417Sdinak 	/* Get the sizes of the attributes we need. */
52517Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
52617Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
52717Sdinak 		cryptoerror(LOG_STDERR, gettext(
52817Sdinak 		    "Unable to get secret key attribute sizes (%s)."),
52917Sdinak 		    pkcs11_strerror(rv));
53017Sdinak 		return (rv);
53117Sdinak 	}
53217Sdinak 
53317Sdinak 	/* Allocate memory for each variable-length attribute. */
53417Sdinak 	for (i = 3; i < n_attrs; i++) {
53517Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
53617Sdinak 		    attrs[i].ulValueLen == 0) {
53717Sdinak 			cryptodebug("display_seckey: *** should not happen");
53817Sdinak 			attrs[i].ulValueLen = 0;
53917Sdinak 			continue;
54017Sdinak 		}
54117Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
54217Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
54317Sdinak 			rv = CKR_HOST_MEMORY;
54417Sdinak 			goto free_display_seckey;
54517Sdinak 		}
54617Sdinak 	}
54717Sdinak 
54817Sdinak 	/* Now really get the attributes. */
54917Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
55017Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
55117Sdinak 		cryptoerror(LOG_STDERR, gettext(
55217Sdinak 		    "Unable to get secret key attributes (%s)."),
55317Sdinak 		    pkcs11_strerror(rv));
55417Sdinak 		goto free_display_seckey;
55517Sdinak 	}
55617Sdinak 
55717Sdinak 	/* Fill in all the optional temp variables. */
55817Sdinak 	i = 15;
55917Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
56017Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
56117Sdinak 	copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
56217Sdinak 	copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
56317Sdinak 
56417Sdinak 	/* Get the key size for the object. */
56517Sdinak 	key_size = get_key_size(sess, obj, key_type);
56617Sdinak 
56717Sdinak 	/* Display the object ... */
56817Sdinak 		/* ... the label and what it is (and key size in bytes) ... */
56917Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%d-bit %s %s)\n"),
57017Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
57117Sdinak 	    gettext("<no label>"), key_size, keytype_str(key_type),
57217Sdinak 	    class_str(CKO_SECRET_KEY));
57317Sdinak 
57417Sdinak 		/* ... the id ... */
57517Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
57617Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
57717Sdinak 	else {
57817Sdinak 		hex_id_len = 3 * id_len + 1;
57917Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
58017Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
58117Sdinak 			rv = CKR_HOST_MEMORY;
58217Sdinak 			goto free_display_seckey;
58317Sdinak 		}
58417Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
58517Sdinak 		    "\n\t\t", "");
58617Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
58717Sdinak 		free(hex_id);
58817Sdinak 	}
58917Sdinak 
59017Sdinak 		/* ... the start date ... */
59117Sdinak 	if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
59217Sdinak 		(void) fprintf(stdout, gettext("\tStart Date:  --\n"));
59317Sdinak 	else
59417Sdinak 		(void) fprintf(stdout, gettext(
59517Sdinak 		    "\tStart Date:  %02.2s/%02.2s/%04.4s\n"),
59617Sdinak 		    start_date->month, start_date->day, start_date->year);
59717Sdinak 
59817Sdinak 		/* ... the end date ... */
59917Sdinak 	if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
60017Sdinak 		(void) fprintf(stdout, gettext("\tEnd Date:  --\n"));
60117Sdinak 	else
60217Sdinak 		(void) fprintf(stdout, gettext(
60317Sdinak 		    "\tEnd Date:  %02.2s/%02.2s/%04.4s\n"),
60417Sdinak 		    end_date->month, end_date->day, end_date->year);
60517Sdinak 
60617Sdinak 		/* ... and its capabilities */
60717Sdinak 	(void) fprintf(stdout, "\t(%s, %s",
60817Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
60917Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
61017Sdinak 	    gettext("not modifiable"));
61117Sdinak 	for (i = 3; i <= 14; i++) {
61217Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
61317Sdinak 		    attrs[i].ulValueLen != 0 &&
61417Sdinak 		    *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
61517Sdinak 			(void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
61617Sdinak 	}
61717Sdinak 	(void) fprintf(stdout, ")\n");
61817Sdinak 
61917Sdinak free_display_seckey:
62017Sdinak 	for (i = 3; i < n_attrs; i++)
62117Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
62217Sdinak 		    attrs[i].ulValueLen != 0)
62317Sdinak 			free(attrs[i].pValue);
62417Sdinak 	return (rv);
62517Sdinak }
62617Sdinak 
62717Sdinak /*
62817Sdinak  * Display certificate.
62917Sdinak  */
63017Sdinak static CK_RV
63117Sdinak display_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
63217Sdinak {
63317Sdinak 	CK_RV			rv = CKR_OK;
63417Sdinak 	static CK_BBOOL		private;
63517Sdinak 	static CK_BBOOL		modifiable;
63617Sdinak 	static CK_BBOOL		trusted;
63717Sdinak 	CK_BYTE			*subject = NULL;
63817Sdinak 	CK_ULONG		subject_len = 0;
63917Sdinak 	CK_BYTE			*value = NULL;
64017Sdinak 	CK_ULONG		value_len = 0;
64117Sdinak 	CK_BYTE			*label = NULL;
64217Sdinak 	CK_ULONG		label_len = 0;
64317Sdinak 	CK_BYTE			*id = NULL;
64417Sdinak 	CK_ULONG		id_len = 0;
64517Sdinak 	CK_BYTE			*issuer = NULL;
64617Sdinak 	CK_ULONG		issuer_len = 0;
64717Sdinak 	CK_BYTE			*serial = NULL;
64817Sdinak 	CK_ULONG		serial_len = 0;
64917Sdinak 	CK_ATTRIBUTE		attrs[9] = {
65017Sdinak 		{ CKA_PRIVATE, &private, sizeof (private) },
65117Sdinak 		{ CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
65217Sdinak 		{ CKA_TRUSTED, &trusted, sizeof (trusted) },
65317Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
65417Sdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
65517Sdinak 		{ CKA_LABEL, NULL, 0 },			/* optional */
65617Sdinak 		{ CKA_ID, NULL, 0 },			/* optional */
65717Sdinak 		{ CKA_ISSUER, NULL, 0 },		/* optional */
65817Sdinak 		{ CKA_SERIAL_NUMBER, NULL, 0 }		/* optional */
65917Sdinak 	    };
66017Sdinak 	CK_ULONG	n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
66117Sdinak 	int		i;
66217Sdinak 	char		*hex_id = NULL;
66317Sdinak 	int		hex_id_len = 0;
66417Sdinak 	char		*hex_subject = NULL;
66517Sdinak 	int		hex_subject_len = 0;
66617Sdinak 	char		*hex_issuer = NULL;
66717Sdinak 	int		hex_issuer_len = 0;
66817Sdinak 	char		*hex_serial = NULL;
66917Sdinak 	int		hex_serial_len = NULL;
67017Sdinak 	uint32_t	serial_value = 0;
67117Sdinak 	char		*hex_value = NULL;
67217Sdinak 	int		hex_value_len = 0;
67317Sdinak 
67417Sdinak 	cryptodebug("inside display_cert");
67517Sdinak 
67617Sdinak 	/* Get the sizes of the attributes we need. */
67717Sdinak 	cryptodebug("calling C_GetAttributeValue for size info");
67817Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
67917Sdinak 		cryptoerror(LOG_STDERR, gettext(
68017Sdinak 		    "Unable to get certificate attribute sizes (%s)."),
68117Sdinak 		    pkcs11_strerror(rv));
68217Sdinak 		return (rv);
68317Sdinak 	}
68417Sdinak 
68517Sdinak 	/* Allocate memory for each variable-length attribute. */
68617Sdinak 	for (i = 3; i < n_attrs; i++) {
68717Sdinak 		if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
68817Sdinak 		    attrs[i].ulValueLen == 0) {
68917Sdinak 			cryptodebug("display_cert: *** should not happen");
69017Sdinak 			attrs[i].ulValueLen = 0;
69117Sdinak 			continue;
69217Sdinak 		}
69317Sdinak 		if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
69417Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
69517Sdinak 			rv = CKR_HOST_MEMORY;
69617Sdinak 			goto free_display_cert;
69717Sdinak 		}
69817Sdinak 	}
69917Sdinak 
70017Sdinak 	/* Now really get the attributes. */
70117Sdinak 	cryptodebug("calling C_GetAttributeValue for attribute info");
70217Sdinak 	if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
70317Sdinak 		cryptoerror(LOG_STDERR, gettext(
70417Sdinak 		    "Unable to get certificate attributes (%s)."),
70517Sdinak 		    pkcs11_strerror(rv));
70617Sdinak 		goto free_display_cert;
70717Sdinak 	}
70817Sdinak 
70917Sdinak 	/*
71017Sdinak 	 * Fill in all the temp variables.  Subject and value are required.
71117Sdinak 	 * The rest are optional.
71217Sdinak 	 */
71317Sdinak 	i = 3;
71417Sdinak 	copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
71517Sdinak 	copy_attr_to_string(&(attrs[i++]), &value, &value_len);
71617Sdinak 	copy_attr_to_string(&(attrs[i++]), &label, &label_len);
71717Sdinak 	copy_attr_to_string(&(attrs[i++]), &id, &id_len);
71817Sdinak 	copy_attr_to_string(&(attrs[i++]), &issuer, &issuer_len);
71917Sdinak 	copy_attr_to_string(&(attrs[i++]), &serial, &serial_len);
72017Sdinak 
72117Sdinak 	/* Display the object ... */
72217Sdinak 		/* ... the label and what it is ... */
72317Sdinak 	(void) fprintf(stdout, gettext("%d.  \"%.*s\" (%s %s)\n"),
72417Sdinak 	    counter, label_len, label_len > 0 ? (char *)label :
72517Sdinak 	    gettext("<no label>"), "X.509", class_str(CKO_CERTIFICATE));
72617Sdinak 
72717Sdinak 		/* ... its capabilities ... */
72817Sdinak 	(void) fprintf(stdout, gettext("\t(%s, %s, %s)\n"),
72917Sdinak 	    private == B_TRUE ? gettext("private") : gettext("public"),
73017Sdinak 	    modifiable == B_TRUE ? gettext("modifiable") :
73117Sdinak 	    gettext("not modifiable"),
73217Sdinak 	    trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
73317Sdinak 
73417Sdinak 		/* ... the id ... */
73517Sdinak 	if (id_len == (CK_ULONG)-1 || id_len == 0)
73617Sdinak 		(void) fprintf(stdout, gettext("\tId:  --\n"));
73717Sdinak 	else {
73817Sdinak 		hex_id_len = 3 * id_len + 1;
73917Sdinak 		if ((hex_id = malloc(hex_id_len)) == NULL) {
74017Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
74117Sdinak 			rv = CKR_HOST_MEMORY;
74217Sdinak 			goto free_display_cert;
74317Sdinak 		}
74417Sdinak 		octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
74517Sdinak 		    "\n\t\t", "");
74617Sdinak 		(void) fprintf(stdout, gettext("\tId:  %s\n"), hex_id);
74717Sdinak 		free(hex_id);
74817Sdinak 	}
74917Sdinak 
75017Sdinak 		/* ... the subject name ... */
75117Sdinak 	if (subject_len == (CK_ULONG)-1 || subject_len == 0)
75217Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  --\n"));
75317Sdinak 	else {
75417Sdinak 		hex_subject_len = 2 * subject_len + 1;	/* best guesstimate */
75517Sdinak 		if ((hex_subject = malloc(hex_subject_len)) == NULL) {
75617Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
75717Sdinak 			rv = CKR_HOST_MEMORY;
75817Sdinak 			goto free_display_cert;
75917Sdinak 		}
76017Sdinak 		rdnseq_to_str(subject, subject_len, hex_subject,
76117Sdinak 		    hex_subject_len);
76217Sdinak 		(void) fprintf(stdout, gettext("\tSubject:  %.*s\n"),
76317Sdinak 		    hex_subject_len, hex_subject);
76417Sdinak 		free(hex_subject);
76517Sdinak 	}
76617Sdinak 
76717Sdinak 		/* ... the issuer name ... */
76817Sdinak 	if (issuer_len == (CK_ULONG)-1 || issuer_len == 0)
76917Sdinak 		(void) fprintf(stdout, gettext("\tIssuer:  --\n"));
77017Sdinak 	else {
77117Sdinak 		hex_issuer_len = 2 * issuer_len + 1;	/* best guesstimate */
77217Sdinak 		if ((hex_issuer = malloc(hex_issuer_len)) == NULL) {
77317Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
77417Sdinak 			rv = CKR_HOST_MEMORY;
77517Sdinak 			goto free_display_cert;
77617Sdinak 		}
77717Sdinak 		rdnseq_to_str(issuer, issuer_len, hex_issuer, hex_issuer_len);
77817Sdinak 		(void) fprintf(stdout, gettext("\tIssuer:  %.*s\n"),
77917Sdinak 		    hex_issuer_len, hex_issuer);
78017Sdinak 		free(hex_issuer);
78117Sdinak 	}
78217Sdinak 
78317Sdinak 		/* ... the serial number ... */
78417Sdinak 	if (serial_len == (CK_ULONG)-1 || serial_len == 0)
78517Sdinak 		(void) fprintf(stdout, gettext("\tSerial:  --\n"));
78617Sdinak 	else {
78717Sdinak 		hex_serial_len = 3 * serial_len + 1;
78817Sdinak 		if ((hex_serial = malloc(hex_serial_len)) == NULL) {
78917Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
79017Sdinak 			rv = CKR_HOST_MEMORY;
79117Sdinak 			goto free_display_cert;
79217Sdinak 		}
79317Sdinak 		octetify(serial, serial_len, hex_serial, hex_serial_len,
79417Sdinak 		    B_FALSE, B_FALSE, 60, "\n\t\t", "");
79517Sdinak 		if (serial_len > 4)
79617Sdinak 			(void) fprintf(stdout, gettext("\tSerial:  %s\n"),
79717Sdinak 			    hex_serial);
79817Sdinak 		else {
79917Sdinak 			for (i = 0; i < serial_len; i++) {
80017Sdinak 				serial_value <<= 8;
80117Sdinak 				serial_value |= (serial[i] & 0xff);
80217Sdinak 			}
80317Sdinak 			(void) fprintf(stdout, gettext("\tSerial:  %s (%d)\n"),
80417Sdinak 			    hex_serial, serial_value);
80517Sdinak 		}
80617Sdinak 		free(hex_serial);
80717Sdinak 	}
80817Sdinak 
80917Sdinak 		/* ... and the value */
81017Sdinak 	if (value_len == (CK_ULONG)-1 || value_len == 0)
81117Sdinak 		(void) fprintf(stdout, gettext("\tValue:  --\n"));
81217Sdinak 	else {
81317Sdinak 		hex_value_len = 3 * value_len + 1;
81417Sdinak 		if ((hex_value = malloc(hex_value_len)) == NULL) {
81517Sdinak 			cryptoerror(LOG_STDERR, "%s.", strerror(errno));
81617Sdinak 			rv = CKR_HOST_MEMORY;
81717Sdinak 			goto free_display_cert;
81817Sdinak 		}
81917Sdinak 		octetify(value, value_len, hex_value, hex_value_len,
82017Sdinak 		    B_FALSE, B_FALSE, 60, "\n\t\t", "");
82117Sdinak 		(void) fprintf(stdout, gettext("\tValue:  %s\n"), hex_value);
82217Sdinak 		free(hex_value);
82317Sdinak 	}
82417Sdinak 
82517Sdinak free_display_cert:
82617Sdinak 	for (i = 3; i < n_attrs; i++)
82717Sdinak 		if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
82817Sdinak 		    attrs[i].ulValueLen != 0)
82917Sdinak 			free(attrs[i].pValue);
83017Sdinak 	return (rv);
83117Sdinak }
83217Sdinak 
83317Sdinak /*
83417Sdinak  * List token object.
83517Sdinak  */
83617Sdinak int
83717Sdinak pk_list(int argc, char *argv[])
83817Sdinak {
83917Sdinak 	int			opt;
840*864Sdinak 	extern int		optind_av;
841*864Sdinak 	extern char		*optarg_av;
842*864Sdinak 	char			*token_spec = NULL;
84317Sdinak 	char			*token_name = NULL;
84417Sdinak 	char			*manuf_id = NULL;
84517Sdinak 	char			*serial_no = NULL;
846*864Sdinak 	char			*type_spec = NULL;
84717Sdinak 	char			full_name[FULL_NAME_LEN];
84817Sdinak 	boolean_t		public_objs = B_FALSE;
84917Sdinak 	boolean_t		private_objs = B_FALSE;
85017Sdinak 	CK_BYTE			*list_label = NULL;
85117Sdinak 	int			obj_type = 0x00;
85217Sdinak 	CK_SLOT_ID		slot_id;
85317Sdinak 	CK_FLAGS		pin_state;
85417Sdinak 	CK_UTF8CHAR_PTR		pin = NULL;
85517Sdinak 	CK_ULONG		pinlen = 0;
85617Sdinak 	CK_SESSION_HANDLE	sess;
85717Sdinak 	CK_OBJECT_HANDLE	*objs;
85817Sdinak 	CK_ULONG		num_objs;
85917Sdinak 	CK_RV			rv = CKR_OK;
86017Sdinak 	int			i;
86117Sdinak 	static CK_OBJECT_CLASS	objclass;
86217Sdinak 	CK_ATTRIBUTE		class_attr =
86317Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) };
86417Sdinak 
86517Sdinak 	cryptodebug("inside pk_list");
86617Sdinak 
86717Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
868*864Sdinak 	while ((opt = getopt_av(argc, argv,
869*864Sdinak 	    "T:(token)y:(objtype)l:(label)")) != EOF) {
87017Sdinak 		switch (opt) {
871*864Sdinak 		case 'T':	/* token specifier */
872*864Sdinak 			if (token_spec)
873*864Sdinak 				return (PK_ERR_USAGE);
874*864Sdinak 			token_spec = optarg_av;
87517Sdinak 			break;
876*864Sdinak 		case 'y':	/* object type:  public, private, both */
877*864Sdinak 			if (type_spec)
878*864Sdinak 				return (PK_ERR_USAGE);
879*864Sdinak 			type_spec = optarg_av;
88017Sdinak 			break;
88117Sdinak 		case 'l':	/* object with specific label */
88217Sdinak 			if (list_label)
88317Sdinak 				return (PK_ERR_USAGE);
884*864Sdinak 			list_label = (CK_BYTE *)optarg_av;
88517Sdinak 			break;
88617Sdinak 		default:
88717Sdinak 			return (PK_ERR_USAGE);
88817Sdinak 			break;
88917Sdinak 		}
89017Sdinak 	}
89117Sdinak 
892*864Sdinak 	/* If no token is specified, default is to use softtoken. */
893*864Sdinak 	if (token_spec == NULL) {
894*864Sdinak 		token_name = SOFT_TOKEN_LABEL;
895*864Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
896*864Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
897*864Sdinak 	} else {
898*864Sdinak 		/*
899*864Sdinak 		 * Parse token specifier into token_name, manuf_id, serial_no.
900*864Sdinak 		 * Token_name is required; manuf_id and serial_no are optional.
901*864Sdinak 		 */
902*864Sdinak 		if (parse_token_spec(token_spec, &token_name, &manuf_id,
903*864Sdinak 		    &serial_no) < 0)
904*864Sdinak 			return (PK_ERR_USAGE);
90517Sdinak 	}
90617Sdinak 
907*864Sdinak 	/* If no object type specified, default is public objects. */
908*864Sdinak 	if (!type_spec) {
909*864Sdinak 		public_objs = B_TRUE;
910*864Sdinak 	} else {
911*864Sdinak 		/*
912*864Sdinak 		 * Otherwise, the object type must be "public", "private",
913*864Sdinak 		 * or "both".
914*864Sdinak 		 */
915*864Sdinak 		if (strcmp(type_spec, "private") == 0) {
916*864Sdinak 			private_objs = B_TRUE;
917*864Sdinak 		} else if (strcmp(type_spec, "public") == 0) {
918*864Sdinak 			public_objs = B_TRUE;
919*864Sdinak 		} else if (strcmp(type_spec, "both") == 0) {
920*864Sdinak 			private_objs = B_TRUE;
921*864Sdinak 			public_objs = B_TRUE;
922*864Sdinak 		} else
923*864Sdinak 			return (PK_ERR_USAGE);
924*864Sdinak 	}
925*864Sdinak 
926*864Sdinak 	if (private_objs)
927*864Sdinak 		obj_type |= PK_PRIVATE_OBJ;
928*864Sdinak 	if (public_objs)
929*864Sdinak 		obj_type |= PK_PUBLIC_OBJ;
930*864Sdinak 
93117Sdinak 	/* No additional args allowed. */
932*864Sdinak 	argc -= optind_av;
933*864Sdinak 	argv += optind_av;
93417Sdinak 	if (argc)
93517Sdinak 		return (PK_ERR_USAGE);
93617Sdinak 	/* Done parsing command line options. */
93717Sdinak 
93817Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
93917Sdinak 
94017Sdinak 	/* Find the slot with token. */
94117Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
94217Sdinak 	    &pin_state)) != CKR_OK) {
94317Sdinak 		cryptoerror(LOG_STDERR, gettext(
94417Sdinak 		    "Unable to find token %s (%s)."), full_name,
94517Sdinak 		    pkcs11_strerror(rv));
94617Sdinak 		return (PK_ERR_PK11);
94717Sdinak 	}
94817Sdinak 
94917Sdinak 	/* If private objects are to be listed, user must be logged in. */
95017Sdinak 	if (private_objs) {
95117Sdinak 		/* Get the user's PIN. */
95217Sdinak 		if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
95317Sdinak 		    &pin, &pinlen)) != CKR_OK) {
95417Sdinak 			cryptoerror(LOG_STDERR,
95517Sdinak 			    gettext("Unable to get token passphrase (%s)."),
95617Sdinak 			    pkcs11_strerror(rv));
95717Sdinak 			quick_finish(NULL);
95817Sdinak 			return (PK_ERR_PK11);
95917Sdinak 		}
96017Sdinak 
96117Sdinak 		/* Logging in user R/O into the token is sufficient. */
96217Sdinak 		cryptodebug("logging in with readonly session");
96317Sdinak 		if ((rv = quick_start(slot_id, 0, pin, pinlen, &sess)) !=
96417Sdinak 		    CKR_OK) {
96517Sdinak 			cryptoerror(LOG_STDERR,
96617Sdinak 			    gettext("Unable to log into token (%s)."),
96717Sdinak 			    pkcs11_strerror(rv));
96817Sdinak 			quick_finish(sess);
96917Sdinak 			return (PK_ERR_PK11);
97017Sdinak 		}
97117Sdinak 	/* Otherwise, just create a session. */
97217Sdinak 	} else {
97317Sdinak 		cryptodebug("opening a readonly session");
97417Sdinak 		if ((rv = open_sess(slot_id, 0, &sess)) != CKR_OK) {
97517Sdinak 			cryptoerror(LOG_STDERR,
97617Sdinak 			    gettext("Unable to open token session (%s)."),
97717Sdinak 			    pkcs11_strerror(rv));
97817Sdinak 			quick_finish(sess);
97917Sdinak 			return (PK_ERR_PK11);
98017Sdinak 		}
98117Sdinak 	}
98217Sdinak 
98317Sdinak 	/* Find the object(s) with the given label and/or type. */
98417Sdinak 	if ((rv = find_objs(sess, obj_type, list_label, &objs, &num_objs)) !=
98517Sdinak 	    CKR_OK) {
98617Sdinak 		cryptoerror(LOG_STDERR, gettext(
98717Sdinak 		    "Unable to find token objects (%s)."), pkcs11_strerror(rv));
98817Sdinak 		quick_finish(sess);
98917Sdinak 		return (PK_ERR_PK11);
99017Sdinak 	}
99117Sdinak 
99217Sdinak 	if (num_objs == 0) {
99317Sdinak 		cryptoerror(LOG_STDERR, gettext("No objects found."));
99417Sdinak 		quick_finish(sess);
99517Sdinak 		return (0);
99617Sdinak 	}
99717Sdinak 
99817Sdinak 	/* List the objects found. */
99917Sdinak 	for (i = 0; i < num_objs; i++) {
100017Sdinak 		/* Get object class first, then decide what is next. */
100117Sdinak 		cryptodebug("calling C_GetAttributeValue for object class");
100217Sdinak 		if ((rv = C_GetAttributeValue(sess, objs[i], &class_attr, 1))
100317Sdinak 		    != CKR_OK) {
100417Sdinak 			cryptoerror(LOG_STDERR, gettext(
100517Sdinak 			    "Unable to get object #%d class attribute (%s)."),
100617Sdinak 			    i+1, pkcs11_strerror(rv));
100717Sdinak 			continue;
100817Sdinak 		}
100917Sdinak 
101017Sdinak 		/* Display based on the type of object. */
101117Sdinak 		switch (objclass) {
101217Sdinak 		case CKO_CERTIFICATE:
101317Sdinak 			if ((rv = display_cert(sess, objs[i], i+1)) != CKR_OK)
101417Sdinak 				cryptoerror(LOG_STDERR,
101517Sdinak 				    gettext("Unable to display certificate."));
101617Sdinak 			break;
101717Sdinak 		case CKO_PUBLIC_KEY:
101817Sdinak 			if ((rv = display_pubkey(sess, objs[i], i+1)) != CKR_OK)
101917Sdinak 				cryptoerror(LOG_STDERR,
102017Sdinak 				    gettext("Unable to display public key."));
102117Sdinak 			break;
102217Sdinak 		case CKO_PRIVATE_KEY:
102317Sdinak 			if ((rv = display_prikey(sess, objs[i], i+1)) != CKR_OK)
102417Sdinak 				cryptoerror(LOG_STDERR,
102517Sdinak 				    gettext("Unable to display private key."));
102617Sdinak 			break;
102717Sdinak 		case CKO_SECRET_KEY:
102817Sdinak 			if ((rv = display_seckey(sess, objs[i], i+1)) != CKR_OK)
102917Sdinak 				cryptoerror(LOG_STDERR,
103017Sdinak 				    gettext("Unable to display secret key."));
103117Sdinak 			break;
103217Sdinak 		case CKO_DATA:
103317Sdinak 			cryptoerror(LOG_STDERR,
103417Sdinak 			    gettext("Data object display not implemented."));
103517Sdinak 			break;
103617Sdinak 		default:
103717Sdinak 			cryptoerror(LOG_STDERR, gettext(
103817Sdinak 			    "Unknown token object class (0x%02x)."), objclass);
103917Sdinak 			break;
104017Sdinak 		}
104117Sdinak 	}
104217Sdinak 
104317Sdinak 	/* Clean up. */
104417Sdinak 	quick_finish(sess);
104517Sdinak 	return (0);
104617Sdinak }
1047