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