/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * This file implements the token object list operation for this tool. * It loads the PKCS#11 modules, finds the object to list, lists it, * and cleans up. User must be logged into the token to list private * objects. */ #include #include #include #include #include #include "common.h" #include "derparse.h" /* * Get key size based on the key type. */ static CK_ULONG get_key_size(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, CK_KEY_TYPE key_type) { CK_RV rv = CKR_OK; CK_ULONG key_size; CK_ATTRIBUTE modulus_sz = { CKA_MODULUS, NULL, 0 }; /* RSA */ CK_ATTRIBUTE prime_sz = { CKA_PRIME, NULL, 0 }; /* DSA, DH X9.42 */ CK_ATTRIBUTE value_sz = { CKA_VALUE, NULL_PTR, 0 }; /* DH, DES/DES3, AES, GENERIC */ cryptodebug("inside get_key_size"); switch (key_type) { case CKK_RSA: if ((rv = C_GetAttributeValue(sess, obj, &modulus_sz, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get modulus attribute size (%s)."), pkcs11_strerror(rv)); } else /* Convert key size to bits. */ key_size = modulus_sz.ulValueLen * 8; break; case CKK_DH: if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get value attribute size (%s)."), pkcs11_strerror(rv)); } else /* Convert key size to bits. */ key_size = value_sz.ulValueLen * 8; break; case CKK_X9_42_DH: case CKK_DSA: if ((rv = C_GetAttributeValue(sess, obj, &prime_sz, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get prime attribute size (%s)."), pkcs11_strerror(rv)); } else /* Convert key size to bits. */ key_size = prime_sz.ulValueLen * 8; break; case CKK_DES: case CKK_DES3: if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get value attribute size (%s)."), pkcs11_strerror(rv)); } else /* Convert key size to bits -- omitting parity bit. */ key_size = value_sz.ulValueLen * 7; break; case CKK_AES: case CKK_GENERIC_SECRET: if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get value attribute size (%s)."), pkcs11_strerror(rv)); } else /* Convert key size to bits. */ key_size = value_sz.ulValueLen * 8; break; default: cryptoerror(LOG_STDERR, gettext( "Unknown object key type (0x%02x)."), key_type); break; } return (key_size); } /* * Display private key. */ static CK_RV display_prikey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter) { CK_RV rv = CKR_OK; static CK_BBOOL private; static CK_BBOOL modifiable; static CK_KEY_TYPE key_type; CK_ULONG key_size; CK_BYTE *label = NULL; CK_ULONG label_len = 0; CK_BYTE *id = NULL; CK_ULONG id_len = 0; CK_BYTE *subject = NULL; CK_ULONG subject_len = 0; CK_DATE *start_date = NULL; CK_ULONG start_date_len = 0; CK_DATE *end_date = NULL; CK_ULONG end_date_len = 0; CK_ATTRIBUTE attrs[18] = { /* 0 to 2 */ { CKA_PRIVATE, &private, sizeof (private) }, { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) }, { CKA_KEY_TYPE, &key_type, sizeof (key_type) }, /* 3 to 12 */ { CKA_DERIVE, NULL, 0 }, { CKA_LOCAL, NULL, 0 }, { CKA_DECRYPT, NULL, 0 }, { CKA_SIGN, NULL, 0 }, { CKA_SIGN_RECOVER, NULL, 0 }, { CKA_UNWRAP, NULL, 0 }, { CKA_SENSITIVE, NULL, 0 }, { CKA_ALWAYS_SENSITIVE, NULL, 0 }, { CKA_EXTRACTABLE, NULL, 0 }, { CKA_NEVER_EXTRACTABLE, NULL, 0 }, /* 13 to 17 */ { CKA_LABEL, NULL, 0 }, /* optional */ { CKA_ID, NULL, 0 }, /* optional */ { CKA_SUBJECT, NULL, 0 }, /* optional */ { CKA_START_DATE, NULL, 0 }, /* optional */ { CKA_END_DATE, NULL, 0 } /* optional */ /* not displaying CKA_KEY_GEN_MECHANISM */ }; CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); int i; char *hex_id = NULL; int hex_id_len = 0; char *hex_subject = NULL; int hex_subject_len = 0; cryptodebug("inside display_prikey"); /* Get the sizes of the attributes we need. */ cryptodebug("calling C_GetAttributeValue for size info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get private key attribute sizes (%s)."), pkcs11_strerror(rv)); return (rv); } /* Allocate memory for each variable-length attribute. */ for (i = 3; i < n_attrs; i++) { if (attrs[i].ulValueLen == (CK_ULONG)-1 || attrs[i].ulValueLen == 0) { cryptodebug("display_prikey: *** should not happen"); attrs[i].ulValueLen = 0; continue; } if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_prikey; } } /* Now really get the attributes. */ cryptodebug("calling C_GetAttributeValue for attribute info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get private key attributes (%s)."), pkcs11_strerror(rv)); goto free_display_prikey; } /* Fill in all the optional temp variables. */ i = 13; copy_attr_to_string(&(attrs[i++]), &label, &label_len); copy_attr_to_string(&(attrs[i++]), &id, &id_len); copy_attr_to_string(&(attrs[i++]), &subject, &subject_len); copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len); copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len); /* Get the key size for the object. */ key_size = get_key_size(sess, obj, key_type); /* Display the object ... */ /* ... the label and what it is (and key size in bits) ... */ (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"), counter, label_len, label_len > 0 ? (char *)label : gettext(""), key_size, keytype_str(key_type), class_str(CKO_PRIVATE_KEY)); /* ... the id ... */ if (id_len == (CK_ULONG)-1 || id_len == 0) (void) fprintf(stdout, gettext("\tId: --\n")); else { hex_id_len = 3 * id_len + 1; if ((hex_id = malloc(hex_id_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_prikey; } octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id); free(hex_id); } /* ... the subject name ... */ if (subject_len == (CK_ULONG)-1 || subject_len == 0) (void) fprintf(stdout, gettext("\tSubject: --\n")); else { hex_subject_len = 2 * subject_len + 1; /* best guesstimate */ if ((hex_subject = malloc(hex_subject_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_prikey; } rdnseq_to_str(subject, subject_len, hex_subject, hex_subject_len); (void) fprintf(stdout, gettext("\tSubject: %.*s\n"), hex_subject_len, hex_subject); free(hex_subject); } /* ... the start date ... */ if (start_date_len == (CK_ULONG)-1 || start_date_len == 0) (void) fprintf(stdout, gettext("\tStart Date: --\n")); else (void) fprintf(stdout, gettext( "\tStart Date: %02.2s/%02.2s/%04.4s\n"), start_date->month, start_date->day, start_date->year); /* ... the end date ... */ if (end_date_len == (CK_ULONG)-1 || end_date_len == 0) (void) fprintf(stdout, gettext("\tEnd Date: --\n")); else (void) fprintf(stdout, gettext( "\tEnd Date: %02.2s/%02.2s/%04.4s\n"), end_date->month, end_date->day, end_date->year); /* ... and its capabilities */ (void) fprintf(stdout, "\t(%s, %s", private != pk_false ? gettext("private") : gettext("public"), modifiable == B_TRUE ? gettext("modifiable") : gettext("not modifiable")); for (i = 3; i <= 12; i++) { if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0 && *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE) (void) fprintf(stdout, ", %s", attr_str(attrs[i].type)); } (void) fprintf(stdout, ")\n"); free_display_prikey: for (i = 3; i < n_attrs; i++) if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0) free(attrs[i].pValue); return (rv); } /* * Display public key. */ static CK_RV display_pubkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter) { CK_RV rv = CKR_OK; static CK_BBOOL private; static CK_BBOOL modifiable; static CK_BBOOL trusted; static CK_KEY_TYPE key_type; CK_ULONG key_size; CK_BYTE *label = NULL; CK_ULONG label_len = 0; CK_BYTE *id = NULL; CK_ULONG id_len = 0; CK_BYTE *subject = NULL; CK_ULONG subject_len = 0; CK_DATE *start_date = NULL; CK_ULONG start_date_len = 0; CK_DATE *end_date = NULL; CK_ULONG end_date_len = 0; CK_ATTRIBUTE attrs[15] = { /* 0 to 3 */ { CKA_PRIVATE, &private, sizeof (private) }, { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) }, { CKA_TRUSTED, &trusted, sizeof (trusted) }, { CKA_KEY_TYPE, &key_type, sizeof (key_type) }, /* 4 to 9 */ { CKA_DERIVE, NULL, 0 }, { CKA_LOCAL, NULL, 0 }, { CKA_ENCRYPT, NULL, 0 }, { CKA_VERIFY, NULL, 0 }, { CKA_VERIFY_RECOVER, NULL, 0 }, { CKA_WRAP, NULL, 0 }, /* 10 to 14 */ { CKA_LABEL, NULL, 0 }, /* optional */ { CKA_ID, NULL, 0 }, /* optional */ { CKA_SUBJECT, NULL, 0 }, /* optional */ { CKA_START_DATE, NULL, 0 }, /* optional */ { CKA_END_DATE, NULL, 0 } /* optional */ /* not displaying CKA_KEY_GEN_MECHANISM */ }; CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); int i; char *hex_id = NULL; int hex_id_len = 0; char *hex_subject = NULL; int hex_subject_len = 0; cryptodebug("inside display_pubkey"); /* Get the sizes of the attributes we need. */ cryptodebug("calling C_GetAttributeValue for size info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get public key attribute sizes (%s)."), pkcs11_strerror(rv)); return (rv); } /* Allocate memory for each variable-length attribute. */ for (i = 4; i < n_attrs; i++) { if (attrs[i].ulValueLen == (CK_ULONG)-1 || attrs[i].ulValueLen == 0) { cryptodebug("display_pubkey: *** should not happen"); attrs[i].ulValueLen = 0; continue; } if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_pubkey; } } /* Now really get the attributes. */ cryptodebug("calling C_GetAttributeValue for attribute info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get public key attributes (%s)."), pkcs11_strerror(rv)); goto free_display_pubkey; } /* Fill in all the optional temp variables. */ i = 10; copy_attr_to_string(&(attrs[i++]), &label, &label_len); copy_attr_to_string(&(attrs[i++]), &id, &id_len); copy_attr_to_string(&(attrs[i++]), &subject, &subject_len); copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len); copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len); /* Get the key size for the object. */ key_size = get_key_size(sess, obj, key_type); /* Display the object ... */ /* ... the label and what it is (and key size in bits) ... */ (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"), counter, label_len, label_len > 0 ? (char *)label : gettext(""), key_size, keytype_str(key_type), class_str(CKO_PUBLIC_KEY)); /* ... the id ... */ if (id_len == (CK_ULONG)-1 || id_len == 0) (void) fprintf(stdout, gettext("\tId: --\n")); else { hex_id_len = 3 * id_len + 1; if ((hex_id = malloc(hex_id_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_pubkey; } octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id); free(hex_id); } /* ... the subject name ... */ if (subject_len == (CK_ULONG)-1 || subject_len == 0) (void) fprintf(stdout, gettext("\tSubject: --\n")); else { hex_subject_len = 2 * subject_len + 1; /* best guesstimate */ if ((hex_subject = malloc(hex_subject_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_pubkey; } rdnseq_to_str(subject, subject_len, hex_subject, hex_subject_len); (void) fprintf(stdout, gettext("\tSubject: %.*s\n"), hex_subject_len, hex_subject); free(hex_subject); } /* ... the start date ... */ if (start_date_len == (CK_ULONG)-1 || start_date_len == 0) (void) fprintf(stdout, gettext("\tStart Date: --\n")); else (void) fprintf(stdout, gettext( "\tStart Date: %02.2s/%02.2s/%04.4s\n"), start_date->month, start_date->day, start_date->year); /* ... the end date ... */ if (end_date_len == (CK_ULONG)-1 || end_date_len == 0) (void) fprintf(stdout, gettext("\tEnd Date: --\n")); else (void) fprintf(stdout, gettext( "\tEnd Date: %02.2s/%02.2s/%04.4s\n"), end_date->month, end_date->day, end_date->year); /* ... and its capabilities */ (void) fprintf(stdout, "\t(%s, %s, %s", private == B_TRUE ? gettext("private") : gettext("public"), modifiable == B_TRUE ? gettext("modifiable") : gettext("not modifiable"), trusted == B_TRUE ? gettext("trusted") : gettext("untrusted")); for (i = 4; i <= 9; i++) { if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0 && *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE) (void) fprintf(stdout, ", %s", attr_str(attrs[i].type)); } (void) fprintf(stdout, ")\n"); free_display_pubkey: for (i = 4; i < n_attrs; i++) if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0) free(attrs[i].pValue); return (rv); } /* * Display secret key. */ static CK_RV display_seckey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter) { CK_RV rv = CKR_OK; static CK_BBOOL private; static CK_BBOOL modifiable; static CK_KEY_TYPE key_type; static CK_ULONG key_size; CK_BYTE *label = NULL; CK_ULONG label_len = 0; CK_BYTE *id = NULL; CK_ULONG id_len = 0; CK_DATE *start_date = NULL; CK_ULONG start_date_len = 0; CK_DATE *end_date = NULL; CK_ULONG end_date_len = 0; CK_ATTRIBUTE attrs[19] = { /* 0 to 2 */ { CKA_PRIVATE, &private, sizeof (private) }, { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) }, { CKA_KEY_TYPE, &key_type, sizeof (key_type) }, /* 3 to 14 */ { CKA_DERIVE, NULL, 0 }, { CKA_LOCAL, NULL, 0 }, { CKA_ENCRYPT, NULL, 0 }, { CKA_DECRYPT, NULL, 0 }, { CKA_SIGN, NULL, 0 }, { CKA_VERIFY, NULL, 0 }, { CKA_WRAP, NULL, 0 }, { CKA_UNWRAP, NULL, 0 }, { CKA_SENSITIVE, NULL, 0 }, { CKA_ALWAYS_SENSITIVE, NULL, 0 }, { CKA_EXTRACTABLE, NULL, 0 }, { CKA_NEVER_EXTRACTABLE, 0 }, /* 15 to 18 */ { CKA_LABEL, NULL, 0 }, /* optional */ { CKA_ID, NULL, 0 }, /* optional */ { CKA_START_DATE, NULL, 0 }, /* optional */ { CKA_END_DATE, NULL, 0 } /* optional */ /* not displaying CKA_KEY_GEN_MECHANISM */ }; CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); int i; char *hex_id = NULL; int hex_id_len = 0; cryptodebug("inside display_seckey"); /* Get the sizes of the attributes we need. */ cryptodebug("calling C_GetAttributeValue for size info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get secret key attribute sizes (%s)."), pkcs11_strerror(rv)); return (rv); } /* Allocate memory for each variable-length attribute. */ for (i = 3; i < n_attrs; i++) { if (attrs[i].ulValueLen == (CK_ULONG)-1 || attrs[i].ulValueLen == 0) { cryptodebug("display_seckey: *** should not happen"); attrs[i].ulValueLen = 0; continue; } if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_seckey; } } /* Now really get the attributes. */ cryptodebug("calling C_GetAttributeValue for attribute info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get secret key attributes (%s)."), pkcs11_strerror(rv)); goto free_display_seckey; } /* Fill in all the optional temp variables. */ i = 15; copy_attr_to_string(&(attrs[i++]), &label, &label_len); copy_attr_to_string(&(attrs[i++]), &id, &id_len); copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len); copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len); /* Get the key size for the object. */ key_size = get_key_size(sess, obj, key_type); /* Display the object ... */ /* ... the label and what it is (and key size in bytes) ... */ (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"), counter, label_len, label_len > 0 ? (char *)label : gettext(""), key_size, keytype_str(key_type), class_str(CKO_SECRET_KEY)); /* ... the id ... */ if (id_len == (CK_ULONG)-1 || id_len == 0) (void) fprintf(stdout, gettext("\tId: --\n")); else { hex_id_len = 3 * id_len + 1; if ((hex_id = malloc(hex_id_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_seckey; } octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id); free(hex_id); } /* ... the start date ... */ if (start_date_len == (CK_ULONG)-1 || start_date_len == 0) (void) fprintf(stdout, gettext("\tStart Date: --\n")); else (void) fprintf(stdout, gettext( "\tStart Date: %02.2s/%02.2s/%04.4s\n"), start_date->month, start_date->day, start_date->year); /* ... the end date ... */ if (end_date_len == (CK_ULONG)-1 || end_date_len == 0) (void) fprintf(stdout, gettext("\tEnd Date: --\n")); else (void) fprintf(stdout, gettext( "\tEnd Date: %02.2s/%02.2s/%04.4s\n"), end_date->month, end_date->day, end_date->year); /* ... and its capabilities */ (void) fprintf(stdout, "\t(%s, %s", private == B_TRUE ? gettext("private") : gettext("public"), modifiable == B_TRUE ? gettext("modifiable") : gettext("not modifiable")); for (i = 3; i <= 14; i++) { if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0 && *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE) (void) fprintf(stdout, ", %s", attr_str(attrs[i].type)); } (void) fprintf(stdout, ")\n"); free_display_seckey: for (i = 3; i < n_attrs; i++) if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0) free(attrs[i].pValue); return (rv); } /* * Display certificate. */ static CK_RV display_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter) { CK_RV rv = CKR_OK; static CK_BBOOL private; static CK_BBOOL modifiable; static CK_BBOOL trusted; CK_BYTE *subject = NULL; CK_ULONG subject_len = 0; CK_BYTE *value = NULL; CK_ULONG value_len = 0; CK_BYTE *label = NULL; CK_ULONG label_len = 0; CK_BYTE *id = NULL; CK_ULONG id_len = 0; CK_BYTE *issuer = NULL; CK_ULONG issuer_len = 0; CK_BYTE *serial = NULL; CK_ULONG serial_len = 0; CK_ATTRIBUTE attrs[9] = { { CKA_PRIVATE, &private, sizeof (private) }, { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) }, { CKA_TRUSTED, &trusted, sizeof (trusted) }, { CKA_SUBJECT, NULL, 0 }, /* required */ { CKA_VALUE, NULL, 0 }, /* required */ { CKA_LABEL, NULL, 0 }, /* optional */ { CKA_ID, NULL, 0 }, /* optional */ { CKA_ISSUER, NULL, 0 }, /* optional */ { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */ }; CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE); int i; char *hex_id = NULL; int hex_id_len = 0; char *hex_subject = NULL; int hex_subject_len = 0; char *hex_issuer = NULL; int hex_issuer_len = 0; char *hex_serial = NULL; int hex_serial_len = NULL; uint32_t serial_value = 0; char *hex_value = NULL; int hex_value_len = 0; cryptodebug("inside display_cert"); /* Get the sizes of the attributes we need. */ cryptodebug("calling C_GetAttributeValue for size info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get certificate attribute sizes (%s)."), pkcs11_strerror(rv)); return (rv); } /* Allocate memory for each variable-length attribute. */ for (i = 3; i < n_attrs; i++) { if (attrs[i].ulValueLen == (CK_ULONG)-1 || attrs[i].ulValueLen == 0) { cryptodebug("display_cert: *** should not happen"); attrs[i].ulValueLen = 0; continue; } if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } } /* Now really get the attributes. */ cryptodebug("calling C_GetAttributeValue for attribute info"); if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get certificate attributes (%s)."), pkcs11_strerror(rv)); goto free_display_cert; } /* * Fill in all the temp variables. Subject and value are required. * The rest are optional. */ i = 3; copy_attr_to_string(&(attrs[i++]), &subject, &subject_len); copy_attr_to_string(&(attrs[i++]), &value, &value_len); copy_attr_to_string(&(attrs[i++]), &label, &label_len); copy_attr_to_string(&(attrs[i++]), &id, &id_len); copy_attr_to_string(&(attrs[i++]), &issuer, &issuer_len); copy_attr_to_string(&(attrs[i++]), &serial, &serial_len); /* Display the object ... */ /* ... the label and what it is ... */ (void) fprintf(stdout, gettext("%d. \"%.*s\" (%s %s)\n"), counter, label_len, label_len > 0 ? (char *)label : gettext(""), "X.509", class_str(CKO_CERTIFICATE)); /* ... its capabilities ... */ (void) fprintf(stdout, gettext("\t(%s, %s, %s)\n"), private == B_TRUE ? gettext("private") : gettext("public"), modifiable == B_TRUE ? gettext("modifiable") : gettext("not modifiable"), trusted == B_TRUE ? gettext("trusted") : gettext("untrusted")); /* ... the id ... */ if (id_len == (CK_ULONG)-1 || id_len == 0) (void) fprintf(stdout, gettext("\tId: --\n")); else { hex_id_len = 3 * id_len + 1; if ((hex_id = malloc(hex_id_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id); free(hex_id); } /* ... the subject name ... */ if (subject_len == (CK_ULONG)-1 || subject_len == 0) (void) fprintf(stdout, gettext("\tSubject: --\n")); else { hex_subject_len = 2 * subject_len + 1; /* best guesstimate */ if ((hex_subject = malloc(hex_subject_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } rdnseq_to_str(subject, subject_len, hex_subject, hex_subject_len); (void) fprintf(stdout, gettext("\tSubject: %.*s\n"), hex_subject_len, hex_subject); free(hex_subject); } /* ... the issuer name ... */ if (issuer_len == (CK_ULONG)-1 || issuer_len == 0) (void) fprintf(stdout, gettext("\tIssuer: --\n")); else { hex_issuer_len = 2 * issuer_len + 1; /* best guesstimate */ if ((hex_issuer = malloc(hex_issuer_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } rdnseq_to_str(issuer, issuer_len, hex_issuer, hex_issuer_len); (void) fprintf(stdout, gettext("\tIssuer: %.*s\n"), hex_issuer_len, hex_issuer); free(hex_issuer); } /* ... the serial number ... */ if (serial_len == (CK_ULONG)-1 || serial_len == 0) (void) fprintf(stdout, gettext("\tSerial: --\n")); else { hex_serial_len = 3 * serial_len + 1; if ((hex_serial = malloc(hex_serial_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } octetify(serial, serial_len, hex_serial, hex_serial_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); if (serial_len > 4) (void) fprintf(stdout, gettext("\tSerial: %s\n"), hex_serial); else { for (i = 0; i < serial_len; i++) { serial_value <<= 8; serial_value |= (serial[i] & 0xff); } (void) fprintf(stdout, gettext("\tSerial: %s (%d)\n"), hex_serial, serial_value); } free(hex_serial); } /* ... and the value */ if (value_len == (CK_ULONG)-1 || value_len == 0) (void) fprintf(stdout, gettext("\tValue: --\n")); else { hex_value_len = 3 * value_len + 1; if ((hex_value = malloc(hex_value_len)) == NULL) { cryptoerror(LOG_STDERR, "%s.", strerror(errno)); rv = CKR_HOST_MEMORY; goto free_display_cert; } octetify(value, value_len, hex_value, hex_value_len, B_FALSE, B_FALSE, 60, "\n\t\t", ""); (void) fprintf(stdout, gettext("\tValue: %s\n"), hex_value); free(hex_value); } free_display_cert: for (i = 3; i < n_attrs; i++) if (attrs[i].ulValueLen != (CK_ULONG)-1 && attrs[i].ulValueLen != 0) free(attrs[i].pValue); return (rv); } /* * List token object. */ int pk_list(int argc, char *argv[]) { int opt; extern int optind_av; extern char *optarg_av; char *token_spec = NULL; char *token_name = NULL; char *manuf_id = NULL; char *serial_no = NULL; char *type_spec = NULL; char full_name[FULL_NAME_LEN]; boolean_t public_objs = B_FALSE; boolean_t private_objs = B_FALSE; CK_BYTE *list_label = NULL; int obj_type = 0x00; CK_SLOT_ID slot_id; CK_FLAGS pin_state; CK_UTF8CHAR_PTR pin = NULL; CK_ULONG pinlen = 0; CK_SESSION_HANDLE sess; CK_OBJECT_HANDLE *objs; CK_ULONG num_objs; CK_RV rv = CKR_OK; int i; static CK_OBJECT_CLASS objclass; CK_ATTRIBUTE class_attr = { CKA_CLASS, &objclass, sizeof (objclass) }; cryptodebug("inside pk_list"); /* Parse command line options. Do NOT i18n/l10n. */ while ((opt = getopt_av(argc, argv, "T:(token)y:(objtype)l:(label)")) != EOF) { switch (opt) { case 'T': /* token specifier */ if (token_spec) return (PK_ERR_USAGE); token_spec = optarg_av; break; case 'y': /* object type: public, private, both */ if (type_spec) return (PK_ERR_USAGE); type_spec = optarg_av; break; case 'l': /* object with specific label */ if (list_label) return (PK_ERR_USAGE); list_label = (CK_BYTE *)optarg_av; break; default: return (PK_ERR_USAGE); break; } } /* If no token is specified, default is to use softtoken. */ if (token_spec == NULL) { token_name = SOFT_TOKEN_LABEL; manuf_id = SOFT_MANUFACTURER_ID; serial_no = SOFT_TOKEN_SERIAL; } else { /* * Parse token specifier into token_name, manuf_id, serial_no. * Token_name is required; manuf_id and serial_no are optional. */ if (parse_token_spec(token_spec, &token_name, &manuf_id, &serial_no) < 0) return (PK_ERR_USAGE); } /* If no object type specified, default is public objects. */ if (!type_spec) { public_objs = B_TRUE; } else { /* * Otherwise, the object type must be "public", "private", * or "both". */ if (strcmp(type_spec, "private") == 0) { private_objs = B_TRUE; } else if (strcmp(type_spec, "public") == 0) { public_objs = B_TRUE; } else if (strcmp(type_spec, "both") == 0) { private_objs = B_TRUE; public_objs = B_TRUE; } else return (PK_ERR_USAGE); } if (private_objs) obj_type |= PK_PRIVATE_OBJ; if (public_objs) obj_type |= PK_PUBLIC_OBJ; /* No additional args allowed. */ argc -= optind_av; argv += optind_av; if (argc) return (PK_ERR_USAGE); /* Done parsing command line options. */ full_token_name(token_name, manuf_id, serial_no, full_name); /* Find the slot with token. */ if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, &pin_state)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to find token %s (%s)."), full_name, pkcs11_strerror(rv)); return (PK_ERR_PK11); } /* If private objects are to be listed, user must be logged in. */ if (private_objs) { /* Get the user's PIN. */ if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, &pinlen)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to get token passphrase (%s)."), pkcs11_strerror(rv)); quick_finish(NULL); return (PK_ERR_PK11); } /* Logging in user R/O into the token is sufficient. */ cryptodebug("logging in with readonly session"); if ((rv = quick_start(slot_id, 0, pin, pinlen, &sess)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to log into token (%s)."), pkcs11_strerror(rv)); quick_finish(sess); return (PK_ERR_PK11); } /* Otherwise, just create a session. */ } else { cryptodebug("opening a readonly session"); if ((rv = open_sess(slot_id, 0, &sess)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext("Unable to open token session (%s)."), pkcs11_strerror(rv)); quick_finish(sess); return (PK_ERR_PK11); } } /* Find the object(s) with the given label and/or type. */ if ((rv = find_objs(sess, obj_type, list_label, &objs, &num_objs)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to find token objects (%s)."), pkcs11_strerror(rv)); quick_finish(sess); return (PK_ERR_PK11); } if (num_objs == 0) { cryptoerror(LOG_STDERR, gettext("No objects found.")); quick_finish(sess); return (0); } /* List the objects found. */ for (i = 0; i < num_objs; i++) { /* Get object class first, then decide what is next. */ cryptodebug("calling C_GetAttributeValue for object class"); if ((rv = C_GetAttributeValue(sess, objs[i], &class_attr, 1)) != CKR_OK) { cryptoerror(LOG_STDERR, gettext( "Unable to get object #%d class attribute (%s)."), i+1, pkcs11_strerror(rv)); continue; } /* Display based on the type of object. */ switch (objclass) { case CKO_CERTIFICATE: if ((rv = display_cert(sess, objs[i], i+1)) != CKR_OK) cryptoerror(LOG_STDERR, gettext("Unable to display certificate.")); break; case CKO_PUBLIC_KEY: if ((rv = display_pubkey(sess, objs[i], i+1)) != CKR_OK) cryptoerror(LOG_STDERR, gettext("Unable to display public key.")); break; case CKO_PRIVATE_KEY: if ((rv = display_prikey(sess, objs[i], i+1)) != CKR_OK) cryptoerror(LOG_STDERR, gettext("Unable to display private key.")); break; case CKO_SECRET_KEY: if ((rv = display_seckey(sess, objs[i], i+1)) != CKR_OK) cryptoerror(LOG_STDERR, gettext("Unable to display secret key.")); break; case CKO_DATA: cryptoerror(LOG_STDERR, gettext("Data object display not implemented.")); break; default: cryptoerror(LOG_STDERR, gettext( "Unknown token object class (0x%02x)."), objclass); break; } } /* Clean up. */ quick_finish(sess); return (0); }