1/* 2 * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18/* 19 * cuPrintCert.cpp - Parse a cert or CRL, dump contents. 20 */ 21#include "cuCdsaUtils.h" 22#include <stdio.h> 23#include <stdlib.h> 24#include <Security/oidscert.h> 25#include <Security/oidscrl.h> 26#include <Security/x509defs.h> 27#include <Security/oidsattr.h> 28#include <Security/oidsalg.h> 29#include <Security/cssmapple.h> 30#include <string.h> 31#include "cuPrintCert.h" 32#include "cuOidParser.h" 33#include "cuTimeStr.h" 34#include <Security/certextensions.h> 35#include <Security/SecAsn1Coder.h> 36#include <Security/keyTemplates.h> 37 38static const char *months[] = { 39 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 40 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 41}; 42 43static void printTimeStr(const CSSM_DATA *cssmTime) 44{ 45 struct tm tm; 46 47 /* ignore cssmTime->timeType for now */ 48 if(cuTimeStringToTm((char *)cssmTime->Data, (unsigned int)cssmTime->Length, &tm)) { 49 printf("***Bad time string format***\n"); 50 return; 51 } 52 if(tm.tm_mon > 11) { 53 printf("***Bad time string format***\n"); 54 return; 55 } 56 printf("%02d:%02d:%02d %s %d, %04d\n", 57 tm.tm_hour, tm.tm_min, tm.tm_sec, 58 months[tm.tm_mon], tm.tm_mday, tm.tm_year + 1900); 59 60} 61 62 63static void printTime(const CSSM_X509_TIME *cssmTime) 64{ 65 /* ignore cssmTime->timeType for now */ 66 printTimeStr(&cssmTime->time); 67} 68 69static void printDataAsHex( 70 const CSSM_DATA *d, 71 unsigned maxToPrint = 0) // optional, 0 means print it all 72{ 73 unsigned i; 74 bool more = false; 75 uint32 len = (uint32)d->Length; 76 uint8 *cp = d->Data; 77 78 if((maxToPrint != 0) && (len > maxToPrint)) { 79 len = maxToPrint; 80 more = true; 81 } 82 for(i=0; i<len; i++) { 83 printf("%02X ", ((unsigned char *)cp)[i]); 84 } 85 if(more) { 86 printf("...\n"); 87 } 88 else { 89 printf("\n"); 90 } 91} 92 93/* 94 * Identify CSSM_BER_TAG with a C string. 95 */ 96static const char *tagTypeString( 97 CSSM_BER_TAG tagType) 98{ 99 static char unknownType[80]; 100 101 switch(tagType) { 102 case BER_TAG_UNKNOWN: 103 return "BER_TAG_UNKNOWN"; 104 case BER_TAG_BOOLEAN: 105 return "BER_TAG_BOOLEAN"; 106 case BER_TAG_INTEGER: 107 return "BER_TAG_INTEGER"; 108 case BER_TAG_BIT_STRING: 109 return "BER_TAG_BIT_STRING"; 110 case BER_TAG_OCTET_STRING: 111 return "BER_TAG_OCTET_STRING"; 112 case BER_TAG_NULL: 113 return "BER_TAG_NULL"; 114 case BER_TAG_OID: 115 return "BER_TAG_OID"; 116 case BER_TAG_SEQUENCE: 117 return "BER_TAG_SEQUENCE"; 118 case BER_TAG_SET: 119 return "BER_TAG_SET"; 120 case BER_TAG_PRINTABLE_STRING: 121 return "BER_TAG_PRINTABLE_STRING"; 122 case BER_TAG_T61_STRING: 123 return "BER_TAG_T61_STRING"; 124 case BER_TAG_IA5_STRING: 125 return "BER_TAG_IA5_STRING"; 126 case BER_TAG_UTC_TIME: 127 return "BER_TAG_UTC_TIME"; 128 case BER_TAG_GENERALIZED_TIME: 129 return "BER_TAG_GENERALIZED_TIME"; 130 default: 131 sprintf(unknownType, "Other type (0x%x)", tagType); 132 return unknownType; 133 } 134} 135 136/* 137 * Print an OID, assumed to be in BER encoded "Intel" format 138 * Length is inferred from oid->Length 139 * Tag is implied 140 */ 141static void printOid(OidParser &parser, const CSSM_DATA *oid) 142{ 143 char strBuf[OID_PARSER_STRING_SIZE]; 144 145 if(oid == NULL) { 146 printf("NULL\n"); 147 return; 148 } 149 if((oid->Length == 0) || (oid->Data == NULL)) { 150 printf("EMPTY\n"); 151 return; 152 } 153 parser.oidParse(oid->Data, (unsigned int)oid->Length, strBuf); 154 printf("%s\n", strBuf); 155} 156 157/* 158 * Used to print generic blobs which we don't really understand. 159 * The bytesToPrint argument is usually thing->Length; it's here because snacc 160 * peports lengths of bit strings in BITS. Caller knows this and 161 * modifies bytesToPrint accordingly. In any case, bytesToPrint is the 162 * max number of valid bytes in *thing->Data. 163 */ 164#define BLOB_LENGTH_PRINT 3 165 166static void printBlobBytes( 167 const char *blobType, 168 const char *quanta, // e.g., "bytes', "bits" 169 uint32 bytesToPrint, 170 const CSSM_DATA *thing) 171{ 172 uint32 dex; 173 uint32 toPrint = bytesToPrint; 174 175 if(toPrint > BLOB_LENGTH_PRINT) { 176 toPrint = BLOB_LENGTH_PRINT; 177 } 178 printf("%s; Length %u %s; data = ", 179 blobType, (unsigned)thing->Length, quanta); 180 for(dex=0; dex<toPrint; dex++) { 181 printf("0x%x ", thing->Data[dex]); 182 if(dex == (toPrint - 1)) { 183 break; 184 } 185 } 186 if(dex < bytesToPrint) { 187 printf(" ...\n"); 188 } 189 else { 190 printf("\n"); 191 } 192} 193 194/* 195 * Print an IA5String or Printable string. Null terminator is not assumed. 196 * Trailing newline is printed. 197 */ 198static void printString( 199 const CSSM_DATA *str) 200{ 201 unsigned i; 202 char *cp = (char *)str->Data; 203 for(i=0; i<str->Length; i++) { 204 printf("%c", *cp++); 205 } 206 printf("\n"); 207} 208 209static void printDerThing( 210 CSSM_BER_TAG tagType, 211 const CSSM_DATA *thing, 212 OidParser &parser) 213{ 214 switch(tagType) { 215 case BER_TAG_INTEGER: 216 printf("%d\n", cuDER_ToInt(thing)); 217 return; 218 case BER_TAG_BOOLEAN: 219 if(thing->Length != 1) { 220 printf("***malformed BER_TAG_BOOLEAN: length %u data ", 221 (unsigned)thing->Length); 222 } 223 printf("%u\n", cuDER_ToInt(thing)); 224 return; 225 case BER_TAG_PRINTABLE_STRING: 226 case BER_TAG_IA5_STRING: 227 case BER_TAG_T61_STRING: 228 case BER_TAG_PKIX_UTF8_STRING: // mostly printable.... 229 printString(thing); 230 return; 231 case BER_TAG_OCTET_STRING: 232 printBlobBytes("Byte string", "bytes", (uint32)thing->Length, thing); 233 return; 234 case BER_TAG_BIT_STRING: 235 printBlobBytes("Bit string", "bits", (uint32)(thing->Length + 7) / 8, thing); 236 return; 237 case BER_TAG_SEQUENCE: 238 printBlobBytes("Sequence", "bytes", (uint32)thing->Length, thing); 239 return; 240 case BER_TAG_SET: 241 printBlobBytes("Set", "bytes", (uint32)thing->Length, thing); 242 return; 243 case BER_TAG_OID: 244 printf("OID = "); 245 printOid(parser, thing); 246 break; 247 default: 248 printf("not displayed (tagType = %s; length %u)\n", 249 tagTypeString(tagType), (unsigned)thing->Length); 250 break; 251 252 } 253} 254 255/* compare two OIDs, return CSSM_TRUE if identical */ 256static CSSM_BOOL compareOids( 257 const CSSM_OID *oid1, 258 const CSSM_OID *oid2) 259{ 260 if((oid1 == NULL) || (oid2 == NULL)) { 261 return CSSM_FALSE; 262 } 263 if(oid1->Length != oid2->Length) { 264 return CSSM_FALSE; 265 } 266 if(memcmp(oid1->Data, oid2->Data, oid1->Length)) { 267 return CSSM_FALSE; 268 } 269 else { 270 return CSSM_TRUE; 271 } 272} 273 274/* 275 * Following a CSSMOID_ECDSA_WithSpecified algorithm is another encoded 276 * CSSM_X509_ALGORITHM_IDENTIFIER containing the digest algorithm OID. 277 * Decode and print the OID. 278 */ 279static void printECDSA_SigAlgParams( 280 const CSSM_DATA *params, 281 OidParser &parser) 282{ 283 SecAsn1CoderRef coder = NULL; 284 if(SecAsn1CoderCreate(&coder)) { 285 printf("***Error in SecAsn1CoderCreate()\n"); 286 return; 287 } 288 CSSM_X509_ALGORITHM_IDENTIFIER algParams; 289 memset(&algParams, 0, sizeof(algParams)); 290 if(SecAsn1DecodeData(coder, params, kSecAsn1AlgorithmIDTemplate, 291 &algParams)) { 292 printf("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); 293 goto errOut; 294 } 295 printOid(parser, &algParams.algorithm); 296errOut: 297 SecAsn1CoderRelease(coder); 298} 299 300static void printSigAlg( 301 const CSSM_X509_ALGORITHM_IDENTIFIER *sigAlg, 302 OidParser &parser) 303{ 304 printOid(parser, &sigAlg->algorithm); 305 if(sigAlg->parameters.Data != NULL) { 306 printf(" alg params : "); 307 if(compareOids(&sigAlg->algorithm, &CSSMOID_ecPublicKey) && 308 (sigAlg->parameters.Data[0] == BER_TAG_OID) && 309 (sigAlg->parameters.Length > 2)) { 310 /* 311 * An OID accompanying an ECDSA public key. The OID is an ECDSA curve. 312 * Do a quickie DER-decode of the OID - it's here in encoded form 313 * because this field is an ASN_ANY - and print the resulting OID. 314 */ 315 CSSM_OID curveOid = {sigAlg->parameters.Length-2, sigAlg->parameters.Data+2}; 316 printOid(parser, &curveOid); 317 } 318 else if(compareOids(&sigAlg->algorithm, &CSSMOID_ECDSA_WithSpecified)) { 319 /* 320 * The accompanying params specify the digest algorithm. 321 */ 322 printECDSA_SigAlgParams(&sigAlg->parameters, parser); 323 } 324 else { 325 /* All others - ASN_ANY - punt */ 326 printDataAsHex(&sigAlg->parameters, 8); 327 } 328 } 329} 330 331static void printRdn( 332 const CSSM_X509_RDN *rdnp, 333 OidParser &parser) 334{ 335 CSSM_X509_TYPE_VALUE_PAIR *ptvp; 336 unsigned pairDex; 337 const char *fieldName; 338 339 for(pairDex=0; pairDex<rdnp->numberOfPairs; pairDex++) { 340 ptvp = &rdnp->AttributeTypeAndValue[pairDex]; 341 if(compareOids(&ptvp->type, &CSSMOID_CountryName)) { 342 fieldName = "Country "; 343 } 344 else if(compareOids(&ptvp->type, &CSSMOID_OrganizationName)) { 345 fieldName = "Org "; 346 } 347 else if(compareOids(&ptvp->type, &CSSMOID_LocalityName)) { 348 fieldName = "Locality "; 349 } 350 else if(compareOids(&ptvp->type, &CSSMOID_OrganizationalUnitName)) { 351 fieldName = "OrgUnit "; 352 } 353 else if(compareOids(&ptvp->type, &CSSMOID_CommonName)) { 354 fieldName = "Common Name "; 355 } 356 else if(compareOids(&ptvp->type, &CSSMOID_Surname)) { 357 fieldName = "Surname "; 358 } 359 else if(compareOids(&ptvp->type, &CSSMOID_Title)) { 360 fieldName = "Title "; 361 } 362 else if(compareOids(&ptvp->type, &CSSMOID_Surname)) { 363 fieldName = "Surname "; 364 } 365 else if(compareOids(&ptvp->type, &CSSMOID_StateProvinceName)) { 366 fieldName = "State "; 367 } 368 else if(compareOids(&ptvp->type, &CSSMOID_CollectiveStateProvinceName)) { 369 fieldName = "Coll. State "; 370 } 371 else if(compareOids(&ptvp->type, &CSSMOID_EmailAddress)) { 372 /* deprecated, used by Thawte */ 373 fieldName = "Email addrs "; 374 } 375 else if(compareOids(&ptvp->type, &CSSMOID_Description)) { 376 fieldName = "Description "; 377 } 378 else { 379 fieldName = "Other name "; 380 } 381 printf(" %s : ", fieldName); 382 printDerThing(ptvp->valueType, &ptvp->value, parser); 383 } /* for each type/value pair */ 384} 385 386static CSSM_RETURN printName( 387 const CSSM_X509_NAME *x509Name, 388 OidParser &parser) 389{ 390 CSSM_X509_RDN_PTR rdnp; 391 unsigned rdnDex; 392 393 for(rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) { 394 rdnp = &x509Name->RelativeDistinguishedName[rdnDex]; 395 printRdn(rdnp, parser); 396 } 397 398 return CSSM_OK; 399} 400 401static void printKeyHeader( 402 const CSSM_KEYHEADER &hdr) 403{ 404 printf(" Algorithm : "); 405 switch(hdr.AlgorithmId) { 406 case CSSM_ALGID_RSA: 407 printf("RSA\n"); 408 break; 409 case CSSM_ALGID_DSA: 410 printf("DSA\n"); 411 break; 412 case CSSM_ALGID_FEE: 413 printf("FEE\n"); 414 break; 415 case CSSM_ALGID_DH: 416 printf("Diffie-Hellman\n"); 417 break; 418 case CSSM_ALGID_ECDSA: 419 printf("ECDSA\n"); 420 break; 421 default: 422 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr.AlgorithmId, 423 (unsigned)hdr.AlgorithmId); 424 } 425 printf(" Key Size : %u bits\n", (unsigned)hdr.LogicalKeySizeInBits); 426 printf(" Key Use : "); 427 CSSM_KEYUSE usage = hdr.KeyUsage; 428 if(usage & CSSM_KEYUSE_ANY) { 429 printf("CSSM_KEYUSE_ANY "); 430 } 431 if(usage & CSSM_KEYUSE_ENCRYPT) { 432 printf("CSSM_KEYUSE_ENCRYPT "); 433 } 434 if(usage & CSSM_KEYUSE_DECRYPT) { 435 printf("CSSM_KEYUSE_DECRYPT "); 436 } 437 if(usage & CSSM_KEYUSE_SIGN) { 438 printf("CSSM_KEYUSE_SIGN "); 439 } 440 if(usage & CSSM_KEYUSE_VERIFY) { 441 printf("CSSM_KEYUSE_VERIFY "); 442 } 443 if(usage & CSSM_KEYUSE_SIGN_RECOVER) { 444 printf("CSSM_KEYUSE_SIGN_RECOVER "); 445 } 446 if(usage & CSSM_KEYUSE_VERIFY_RECOVER) { 447 printf("CSSM_KEYUSE_VERIFY_RECOVER "); 448 } 449 if(usage & CSSM_KEYUSE_WRAP) { 450 printf("CSSM_KEYUSE_WRAP "); 451 } 452 if(usage & CSSM_KEYUSE_UNWRAP) { 453 printf("CSSM_KEYUSE_UNWRAP "); 454 } 455 if(usage & CSSM_KEYUSE_DERIVE) { 456 printf("CSSM_KEYUSE_DERIVE "); 457 } 458 printf("\n"); 459 460} 461 462/* 463 * Print contents of a CE_GeneralName as best we can. 464 */ 465static void printGeneralName( 466 const CE_GeneralName *name, 467 OidParser &parser) 468{ 469 switch(name->nameType) { 470 case GNT_RFC822Name: 471 printf(" RFC822Name : "); 472 printString(&name->name); 473 break; 474 case GNT_DNSName: 475 printf(" DNSName : "); 476 printString(&name->name); 477 break; 478 case GNT_URI: 479 printf(" URI : "); 480 printString(&name->name); 481 break; 482 case GNT_IPAddress: 483 printf(" IP Address : "); 484 for(unsigned i=0; i<name->name.Length; i++) { 485 printf("%d", name->name.Data[i]); 486 if(i < (name->name.Length - 1)) { 487 printf("."); 488 } 489 } 490 printf("\n"); 491 break; 492 case GNT_RegisteredID: 493 printf(" RegisteredID : "); 494 printOid(parser, &name->name); 495 break; 496 case GNT_X400Address: 497 /* ORAddress, a very complicated struct - punt */ 498 printf(" X400Address : "); 499 printBlobBytes("Sequence", "bytes", (uint32)name->name.Length, &name->name); 500 break; 501 case GNT_DirectoryName: 502 if(!name->berEncoded) { 503 /* CL parsed it for us into an CSSM_X509_NAME */ 504 if(name->name.Length != sizeof(CSSM_X509_NAME)) { 505 printf("***MALFORMED GNT_DirectoryName\n"); 506 break; 507 } 508 const CSSM_X509_NAME *x509Name = 509 (const CSSM_X509_NAME *)name->name.Data; 510 printf(" Dir Name :\n"); 511 printName(x509Name, parser); 512 } 513 else { 514 /* encoded Name (i.e. CSSM_X509_NAME) */ 515 printf(" Dir Name : "); 516 printBlobBytes("Byte string", "bytes", 517 (uint32)name->name.Length, &name->name); 518 } 519 break; 520 case GNT_EdiPartyName: 521 /* sequence EDIPartyName */ 522 printf(" EdiPartyName : "); 523 printBlobBytes("Sequence", "bytes", (uint32)name->name.Length, &name->name); 524 break; 525 case GNT_OtherName: 526 { 527 printf(" OtherName :\n"); 528 if(name->name.Length != sizeof(CE_OtherName)) { 529 printf("***Malformed CE_OtherName\n"); 530 break; 531 } 532 CE_OtherName *other = (CE_OtherName *)name->name.Data; 533 printf(" typeID : "); 534 printOid(parser, &other->typeId); 535 printf(" value : "); 536 printDataAsHex(&other->value, 0); 537 break; 538 } 539 } 540} 541 542 543/* 544 * Print contents of a CE_GeneralNames as best we can. 545 */ 546static void printGeneralNames( 547 const CE_GeneralNames *generalNames, 548 OidParser &parser) 549{ 550 unsigned i; 551 CE_GeneralName *name; 552 553 for(i=0; i<generalNames->numNames; i++) { 554 name = &generalNames->generalName[i]; 555 printGeneralName(name, parser); 556 } 557} 558 559static int printCdsaExtensionCommon( 560 const CSSM_X509_EXTENSION *cssmExt, 561 OidParser &parser, 562 bool expectParsed, 563 CSSM_BOOL verbose, 564 bool extraIndent = false) 565{ 566 if(extraIndent) { 567 printf(" Extension : "); printOid(parser, &cssmExt->extnId); 568 printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE"); 569 } 570 else { 571 printf("Extension struct : "); printOid(parser, &cssmExt->extnId); 572 printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE"); 573 } 574 575 /* currently (since Radar 3593624), these are both always valid */ 576 #if 0 577 /* this prevents printing pre-encoded extensions in clxutils/extenTest */ 578 if((cssmExt->BERvalue.Data == NULL) || 579 (cssmExt->value.parsedValue == NULL)) { /* actually, one of three variants */ 580 printf("***Malformed CSSM_X509_EXTENSION (1)\n"); 581 return 1; 582 } 583 #endif 584 switch(cssmExt->format) { 585 case CSSM_X509_DATAFORMAT_ENCODED: 586 if(expectParsed) { 587 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n"); 588 return 1; 589 } 590 break; 591 case CSSM_X509_DATAFORMAT_PARSED: 592 if(!expectParsed) { 593 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n"); 594 return 1; 595 } 596 break; 597 case CSSM_X509_DATAFORMAT_PAIR: 598 /* unsupported */ 599 printf("Bad CSSM_X509_EXTENSION format:FORMAT_PAIR\n"); 600 return 1; 601 default: 602 printf("***Unknown CSSM_X509_EXTENSION.format\n"); 603 return 1; 604 } 605 return 0; 606} 607 608static int printExtensionCommon( 609 const CSSM_DATA &value, 610 OidParser &parser, 611 CSSM_BOOL verbose, 612 bool expectParsed = true) 613{ 614 if(value.Length != sizeof(CSSM_X509_EXTENSION)) { 615 printf("***malformed CSSM_FIELD (1)\n"); 616 return 1; 617 } 618 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 619 return printCdsaExtensionCommon(cssmExt, parser, expectParsed, verbose); 620} 621 622 623static void printKeyUsage( 624 const CSSM_DATA &value) 625{ 626 CE_KeyUsage usage; 627 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 628 629 usage = *((CE_KeyUsage *)cssmExt->value.parsedValue); 630 printf(" usage : "); 631 if(usage & CE_KU_DigitalSignature) { 632 printf("DigitalSignature "); 633 } 634 if(usage & CE_KU_NonRepudiation) { 635 printf("NonRepudiation "); 636 } 637 if(usage & CE_KU_KeyEncipherment) { 638 printf("KeyEncipherment "); 639 } 640 if(usage & CE_KU_DataEncipherment) { 641 printf("DataEncipherment "); 642 } 643 if(usage & CE_KU_KeyAgreement) { 644 printf("KeyAgreement "); 645 } 646 if(usage & CE_KU_KeyCertSign) { 647 printf("KeyCertSign "); 648 } 649 if(usage & CE_KU_CRLSign) { 650 printf("CRLSign "); 651 } 652 if(usage & CE_KU_EncipherOnly) { 653 printf("EncipherOnly "); 654 } 655 if(usage & CE_KU_DecipherOnly) { 656 printf("DecipherOnly "); 657 } 658 printf("\n"); 659 660} 661 662static void printBasicConstraints( 663 const CSSM_DATA &value) 664{ 665 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 666 CE_BasicConstraints *bc = (CE_BasicConstraints *)cssmExt->value.parsedValue; 667 printf(" CA : %s\n", bc->cA ? "TRUE" : "FALSE"); 668 if(bc->pathLenConstraintPresent) { 669 printf(" pathLenConstr : %u\n", (unsigned)bc->pathLenConstraint); 670 } 671} 672 673static void printExtKeyUsage( 674 const CSSM_DATA &value, 675 OidParser &parser) 676{ 677 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 678 CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue; 679 unsigned oidDex; 680 for(oidDex=0; oidDex<eku->numPurposes; oidDex++) { 681 printf(" purpose %2d : ", oidDex); 682 printOid(parser, &eku->purposes[oidDex]); 683 } 684} 685 686static void printCssmAuthorityKeyId( 687 const CE_AuthorityKeyID *akid, 688 OidParser &parser) 689{ 690 if(akid->keyIdentifierPresent) { 691 printf(" Auth KeyID : "); 692 printDataAsHex(&akid->keyIdentifier, 6938); 694 } 695 if(akid->generalNamesPresent) { 696 printGeneralNames(akid->generalNames, parser); 697 } 698 if(akid->serialNumberPresent) { 699 printf(" serialNumber : "); 700 printDataAsHex(&akid->serialNumber, 8); 701 } 702} 703 704static void printAuthorityKeyId( 705 const CSSM_DATA &value, 706 OidParser &parser) 707{ 708 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 709 CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)cssmExt->value.parsedValue; 710 printCssmAuthorityKeyId(akid, parser); 711} 712 713static void printSubjectIssuerAltName( 714 const CSSM_DATA &value, 715 OidParser &parser) 716{ 717 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 718 CE_GeneralNames *san = (CE_GeneralNames *)cssmExt->value.parsedValue; 719 printGeneralNames(san, parser); 720} 721 722static void printDistPointName( 723 const CE_DistributionPointName *dpn, 724 OidParser &parser) 725{ 726 switch(dpn->nameType) { 727 case CE_CDNT_FullName: 728 printGeneralNames(dpn->dpn.fullName, parser); 729 break; 730 case CE_CDNT_NameRelativeToCrlIssuer: 731 printRdn(dpn->dpn.rdn, parser); 732 break; 733 default: 734 printf("***BOGUS CE_DistributionPointName.nameType\n"); 735 break; 736 } 737} 738 739static void printDistPoint( 740 const CE_CRLDistributionPoint *dp, 741 OidParser &parser) 742{ 743 if(dp->distPointName) { 744 printf(" Dist pt Name :\n"); 745 printDistPointName(dp->distPointName, parser); 746 } 747 printf(" reasonsPresent : %s\n", dp->reasonsPresent ? "TRUE" : "FALSE"); 748 if(dp->reasonsPresent) { 749 /* FIXME - parse */ 750 printf(" reasons : 0x%X\n", dp->reasons); 751 } 752 if(dp->crlIssuer) { 753 printf(" CRLIssuer :\n"); 754 printGeneralNames(dp->crlIssuer, parser); 755 } 756} 757 758static void printDistributionPoints( 759 const CSSM_DATA &value, 760 OidParser &parser) 761{ 762 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 763 CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; 764 765 for(unsigned dex=0; dex<dps->numDistPoints; dex++) { 766 printf(" Dist pt %d :\n", dex); 767 printDistPoint(&dps->distPoints[dex], parser); 768 } 769} 770 771static void printValueOrNotPresent( 772 CSSM_BOOL present, 773 CSSM_BOOL value) 774{ 775 if(!present) { 776 printf("<Not Present>\n"); 777 } 778 else if(value) { 779 printf("TRUE\n"); 780 } 781 else { 782 printf("FALSE"); 783 } 784} 785 786static void printIssuingDistributionPoint( 787 const CE_IssuingDistributionPoint *idp, 788 OidParser &parser) 789{ 790 if(idp->distPointName) { 791 printf(" Dist pt :\n"); 792 printDistPointName(idp->distPointName, parser); 793 } 794 printf(" Only user certs : "); 795 printValueOrNotPresent(idp->onlyUserCertsPresent, idp->onlyUserCerts); 796 printf(" Only CA certs : "); 797 printValueOrNotPresent(idp->onlyCACertsPresent, idp->onlyCACerts); 798 printf(" Only some reason: "); 799 printValueOrNotPresent(idp->onlySomeReasonsPresent, idp->onlySomeReasons); 800 printf(" Indirectl CRL : "); 801 printValueOrNotPresent(idp->indirectCrlPresent, idp->indirectCrl); 802} 803 804static void printCertPolicies( 805 const CSSM_DATA &value, 806 OidParser &parser) 807{ 808 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 809 CE_CertPolicies *cdsaObj = (CE_CertPolicies *)cssmExt->value.parsedValue; 810 for(unsigned polDex=0; polDex<cdsaObj->numPolicies; polDex++) { 811 CE_PolicyInformation *cPolInfo = &cdsaObj->policies[polDex]; 812 printf(" Policy %2d : ID ", polDex); 813 printOid(parser, &cPolInfo->certPolicyId); 814 for(unsigned qualDex=0; qualDex<cPolInfo->numPolicyQualifiers; qualDex++) { 815 CE_PolicyQualifierInfo *cQualInfo = &cPolInfo->policyQualifiers[qualDex]; 816 printf(" Qual %2d : ID ", qualDex); 817 printOid(parser, &cQualInfo->policyQualifierId); 818 if(cuCompareCssmData(&cQualInfo->policyQualifierId, 819 &CSSMOID_QT_CPS)) { 820 printf(" CPS : "); 821 printString(&cQualInfo->qualifier); 822 } 823 else { 824 printf(" unparsed : "); 825 printDataAsHex(&cQualInfo->qualifier, 8); 826 } 827 } 828 } 829} 830 831static void printNetscapeCertType( 832 const CSSM_DATA &value) 833{ 834 CE_NetscapeCertType certType; 835 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 836 837 certType = *((CE_NetscapeCertType *)cssmExt->value.parsedValue); 838 printf(" certType : "); 839 if(certType & CE_NCT_SSL_Client) { 840 printf("SSL_Client "); 841 } 842 if(certType & CE_NCT_SSL_Server) { 843 printf("SSL_Server "); 844 } 845 if(certType & CE_NCT_SMIME) { 846 printf("S/MIME "); 847 } 848 if(certType & CE_NCT_ObjSign) { 849 printf("ObjectSign "); 850 } 851 if(certType & CE_NCT_Reserved) { 852 printf("Reserved "); 853 } 854 if(certType & CE_NCT_SSL_CA) { 855 printf("SSL_CA "); 856 } 857 if(certType & CE_NCT_SMIME_CA) { 858 printf("SMIME_CA "); 859 } 860 if(certType & CE_NCT_ObjSignCA) { 861 printf("ObjSignCA "); 862 } 863 printf("\n"); 864} 865 866static void printAuthorityInfoAccess( 867 const CSSM_DATA &value, 868 OidParser &parser) 869{ 870 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 871 CE_AuthorityInfoAccess *info = (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue; 872 873 printf(" numDescriptions : %lu\n", (unsigned long)info->numAccessDescriptions); 874 for(unsigned dex=0; dex<info->numAccessDescriptions; dex++) { 875 printf(" description %u : \n", dex); 876 printf(" accessMethod : "); 877 CE_AccessDescription *descr = &info->accessDescriptions[dex]; 878 printOid(parser, &descr->accessMethod); 879 printGeneralName(&descr->accessLocation, parser); 880 } 881} 882 883static void printQualCertStatements( 884 const CSSM_DATA &value, 885 OidParser &parser) 886{ 887 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data; 888 CE_QC_Statements *qcss = (CE_QC_Statements *)cssmExt->value.parsedValue; 889 890 printf(" numQCStatements : %lu\n", (unsigned long)qcss->numQCStatements); 891 for(unsigned dex=0; dex<qcss->numQCStatements; dex++) { 892 CE_QC_Statement *qcs = &qcss->qcStatements[dex]; 893 894 printf(" statement %u : \n", dex); 895 printf(" statementId : "); 896 printOid(parser, &qcs->statementId); 897 if(qcs->semanticsInfo) { 898 printf(" semanticsInfo :\n"); 899 CE_SemanticsInformation *si = qcs->semanticsInfo; 900 if(si->semanticsIdentifier) { 901 printf(" semanticsId : "); 902 printOid(parser, si->semanticsIdentifier); 903 } 904 if(si->nameRegistrationAuthorities) { 905 printf(" nameRegAuth :\n"); 906 printGeneralNames(si->nameRegistrationAuthorities, parser); 907 } 908 } 909 if(qcs->otherInfo) { 910 printf(" otherInfo : "); printDataAsHex(qcs->otherInfo, 8); 911 } 912 } 913} 914 915/* print one field */ 916void printCertField( 917 const CSSM_FIELD &field, 918 OidParser &parser, 919 CSSM_BOOL verbose) 920{ 921 const CSSM_DATA *thisData = &field.FieldValue; 922 const CSSM_OID *thisOid = &field.FieldOid; 923 924 if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Version)) { 925 if(verbose) { 926 printf("Version : %u\n", cuDER_ToInt(thisData)); 927 } 928 } 929 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SerialNumber)) { 930 printf("Serial Number : "); printDataAsHex(thisData, 0); 931 } 932 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerNameCStruct)) { 933 printf("Issuer Name :\n"); 934 CSSM_X509_NAME_PTR name = (CSSM_X509_NAME_PTR)thisData->Data; 935 if((name == NULL) || (thisData->Length != sizeof(CSSM_X509_NAME))) { 936 printf(" ***malformed CSSM_X509_NAME\n"); 937 } 938 else { 939 printName(name, parser); 940 } 941 } 942 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectNameCStruct)) { 943 printf("Subject Name :\n"); 944 CSSM_X509_NAME_PTR name = (CSSM_X509_NAME_PTR)thisData->Data; 945 if((name == NULL) || (thisData->Length != sizeof(CSSM_X509_NAME))) { 946 printf(" ***malformed CSSM_X509_NAME\n"); 947 } 948 else { 949 printName(name, parser); 950 } 951 } 952 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1ValidityNotBefore)) { 953 CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)thisData->Data; 954 if((cssmTime == NULL) || (thisData->Length != sizeof(CSSM_X509_TIME))) { 955 printf(" ***malformed CSSM_X509_TIME\n"); 956 } 957 else if(verbose) { 958 printf("Not Before : "); printString(&cssmTime->time); 959 printf(" : "); 960 printTime(cssmTime); 961 } 962 else { 963 printf("Not Before : "); 964 printTime(cssmTime); 965 } 966 } 967 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1ValidityNotAfter)) { 968 CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)thisData->Data; 969 if((cssmTime == NULL) || (thisData->Length != sizeof(CSSM_X509_TIME))) { 970 printf(" ***malformed CSSM_X509_TIME\n"); 971 } 972 else if(verbose) { 973 printf("Not After : "); printString(&cssmTime->time); 974 printf(" : "); 975 printTime(cssmTime); 976 } 977 else { 978 printf("Not After : "); 979 printTime(cssmTime); 980 } 981 } 982 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SignatureAlgorithmTBS)) { 983 if(verbose) { 984 /* normally skip, it's the same as TBS sig alg */ 985 printf("TBS Sig Algorithm : "); 986 CSSM_X509_ALGORITHM_IDENTIFIER *algId = 987 (CSSM_X509_ALGORITHM_IDENTIFIER *)thisData->Data; 988 if((algId == NULL) || 989 (thisData->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { 990 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n"); 991 } 992 else { 993 printSigAlg(algId, parser); 994 } 995 } 996 } 997 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SignatureAlgorithm)) { 998 printf("Cert Sig Algorithm : "); 999 CSSM_X509_ALGORITHM_IDENTIFIER *algId = 1000 (CSSM_X509_ALGORITHM_IDENTIFIER *)thisData->Data; 1001 if((algId == NULL) || 1002 (thisData->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { 1003 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n"); 1004 } 1005 else { 1006 printSigAlg(algId, parser); 1007 } 1008 } 1009 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateIssuerUniqueId)) { 1010 if(verbose) { 1011 printf("Issuer UniqueId : "); 1012 printDerThing(BER_TAG_BIT_STRING, thisData, parser); 1013 } 1014 } 1015 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateSubjectUniqueId)) { 1016 if(verbose) { 1017 printf("Subject UniqueId : "); 1018 printDerThing(BER_TAG_BIT_STRING, thisData, parser); 1019 } 1020 } 1021 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectPublicKeyCStruct)) { 1022 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *pubKeyInfo = 1023 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)thisData->Data; 1024 printf("Pub Key Algorithm : "); 1025 if((pubKeyInfo == NULL) || 1026 (thisData->Length != sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO))) { 1027 printf(" ***malformed CSSM_X509_SUBJECT_PUBLIC_KEY_INFO\n"); 1028 } 1029 else { 1030 printSigAlg(&pubKeyInfo->algorithm, parser); 1031 printf("Pub key Bytes : Length %u bytes : ", 1032 (unsigned)pubKeyInfo->subjectPublicKey.Length); 1033 printDataAsHex(&pubKeyInfo->subjectPublicKey, 8); 1034 } 1035 } 1036 else if(cuCompareCssmData(thisOid, &CSSMOID_CSSMKeyStruct)) { 1037 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)thisData->Data; 1038 printf("CSSM Key :\n"); 1039 if((cssmKey == NULL) || 1040 (thisData->Length != sizeof(CSSM_KEY))) { 1041 printf(" ***malformed CSSM_KEY\n"); 1042 } 1043 else { 1044 printKeyHeader(cssmKey->KeyHeader); 1045 if(verbose) { 1046 printf(" Key Blob : "); 1047 printDataAsHex(&cssmKey->KeyData, 8); 1048 } 1049 } 1050 } 1051 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Signature)) { 1052 printf("Signature : %u bytes : ", (unsigned)thisData->Length); 1053 printDataAsHex(thisData, 8); 1054 } 1055 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V3CertificateExtensionCStruct)) { 1056 if(printExtensionCommon(*thisData, parser, verbose, false)) { 1057 return; 1058 } 1059 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)thisData->Data; 1060 printf(" Unparsed data : "); printDataAsHex(&cssmExt->BERvalue, 8); 1061 } 1062 else if(cuCompareCssmData(thisOid, &CSSMOID_KeyUsage)) { 1063 if(printExtensionCommon(*thisData, parser, verbose)) { 1064 return; 1065 } 1066 printKeyUsage(*thisData); 1067 } 1068 else if(cuCompareCssmData(thisOid, &CSSMOID_BasicConstraints)) { 1069 if(printExtensionCommon(*thisData, parser, verbose)) { 1070 return; 1071 } 1072 printBasicConstraints(*thisData); 1073 } 1074 else if(cuCompareCssmData(thisOid, &CSSMOID_ExtendedKeyUsage)) { 1075 if(printExtensionCommon(*thisData, parser, verbose)) { 1076 return; 1077 } 1078 printExtKeyUsage(*thisData, parser); 1079 } 1080 else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectKeyIdentifier)) { 1081 if(printExtensionCommon(*thisData, parser, verbose)) { 1082 return; 1083 } 1084 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)thisData->Data; 1085 CSSM_DATA_PTR cdata = (CSSM_DATA_PTR)cssmExt->value.parsedValue; 1086 if((cdata == NULL) || (cdata->Data == NULL)) { 1087 printf("****Malformed extension (no parsedValue)\n"); 1088 } 1089 else { 1090 printf(" Subject KeyID : "); printDataAsHex(cdata, 8); 1091 } 1092 } 1093 else if(cuCompareCssmData(thisOid, &CSSMOID_AuthorityKeyIdentifier)) { 1094 if(printExtensionCommon(*thisData, parser, verbose)) { 1095 return; 1096 } 1097 printAuthorityKeyId(*thisData, parser); 1098 } 1099 else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectAltName)) { 1100 if(printExtensionCommon(*thisData, parser, verbose)) { 1101 return; 1102 } 1103 printSubjectIssuerAltName(*thisData, parser); 1104 } 1105 else if(cuCompareCssmData(thisOid, &CSSMOID_IssuerAltName)) { 1106 if(printExtensionCommon(*thisData, parser, verbose)) { 1107 return; 1108 } 1109 printSubjectIssuerAltName(*thisData, parser); 1110 } 1111 else if(cuCompareCssmData(thisOid, &CSSMOID_CertificatePolicies)) { 1112 if(printExtensionCommon(*thisData, parser, verbose)) { 1113 return; 1114 } 1115 printCertPolicies(*thisData, parser); 1116 } 1117 else if(cuCompareCssmData(thisOid, &CSSMOID_NetscapeCertType)) { 1118 if(printExtensionCommon(*thisData, parser, verbose)) { 1119 return; 1120 } 1121 printNetscapeCertType(*thisData); 1122 } 1123 else if(cuCompareCssmData(thisOid, &CSSMOID_CrlDistributionPoints)) { 1124 if(printExtensionCommon(*thisData, parser, verbose)) { 1125 return; 1126 } 1127 printDistributionPoints(*thisData, parser); 1128 } 1129 else if(cuCompareCssmData(thisOid, &CSSMOID_AuthorityInfoAccess)) { 1130 if(printExtensionCommon(*thisData, parser, verbose)) { 1131 return; 1132 } 1133 printAuthorityInfoAccess(*thisData, parser); 1134 } 1135 else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectInfoAccess)) { 1136 if(printExtensionCommon(*thisData, parser, verbose)) { 1137 return; 1138 } 1139 printAuthorityInfoAccess(*thisData, parser); 1140 } 1141 else if(cuCompareCssmData(thisOid, &CSSMOID_QC_Statements)) { 1142 if(printExtensionCommon(*thisData, parser, verbose)) { 1143 return; 1144 } 1145 printQualCertStatements(*thisData, parser); 1146 } 1147 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerName)) { 1148 if(verbose) { 1149 printf("Normalized Issuer : "); 1150 printDataAsHex(thisData, 8); 1151 } 1152 } 1153 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectName)) { 1154 if(verbose) { 1155 printf("Normalized Subject : "); 1156 printDataAsHex(thisData, 8); 1157 } 1158 } 1159 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerNameStd)) { 1160 if(verbose) { 1161 printf("DER-encoded issuer : "); 1162 printDataAsHex(thisData, 8); 1163 } 1164 } 1165 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectNameStd)) { 1166 if(verbose) { 1167 printf("DER-encoded subject: "); 1168 printDataAsHex(thisData, 8); 1169 } 1170 } 1171 else { 1172 printf("Other field: : "); printOid(parser, thisOid); 1173 } 1174} 1175 1176static 1177void printCrlExten( 1178 const CSSM_X509_EXTENSION *exten, 1179 CSSM_BOOL verbose, 1180 OidParser &parser) 1181{ 1182 const CSSM_OID *oid = &exten->extnId; 1183 const void *thisData = exten->value.parsedValue; 1184 1185 if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) { 1186 if(printCdsaExtensionCommon(exten, parser, false, verbose)) { 1187 return; 1188 } 1189 printf(" Unparsed data : "); printDataAsHex(&exten->BERvalue, 8); 1190 } 1191 else if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { 1192 printf("***Badly formatted CSSM_X509_EXTENSION\n"); 1193 return; 1194 } 1195 else if(cuCompareCssmData(oid, &CSSMOID_AuthorityKeyIdentifier)) { 1196 if(printCdsaExtensionCommon(exten, parser, true, verbose)) { 1197 return; 1198 } 1199 printCssmAuthorityKeyId((CE_AuthorityKeyID *)thisData, parser); 1200 } 1201 else if(cuCompareCssmData(oid, &CSSMOID_IssuerAltName)) { 1202 if(printCdsaExtensionCommon(exten, parser, true, verbose)) { 1203 return; 1204 } 1205 printGeneralNames((CE_GeneralNames *)thisData, parser); 1206 } 1207 else if(cuCompareCssmData(oid, &CSSMOID_CrlNumber)) { 1208 if(printCdsaExtensionCommon(exten, parser, true, verbose)) { 1209 return; 1210 } 1211 printf(" CRL Number : %u\n", *((unsigned *)thisData)); 1212 } 1213 else if(cuCompareCssmData(oid, &CSSMOID_DeltaCrlIndicator)) { 1214 if(printCdsaExtensionCommon(exten, parser, true, verbose)) { 1215 return; 1216 } 1217 printf(" Delta CRL Base : %u\n", *((unsigned *)thisData)); 1218 } 1219 else if(cuCompareCssmData(oid, &CSSMOID_IssuingDistributionPoint)) { 1220 if(printCdsaExtensionCommon(exten, parser, true, verbose)) { 1221 return; 1222 } 1223 printIssuingDistributionPoint((CE_IssuingDistributionPoint *)thisData, 1224 parser); 1225 } 1226 else { 1227 /* should never happen - we're out of sync with the CL */ 1228 printf("UNKNOWN EXTENSION : "); printOid(parser, oid); 1229 } 1230} 1231 1232 1233static 1234void printCrlEntryExten( 1235 const CSSM_X509_EXTENSION *exten, 1236 CSSM_BOOL verbose, 1237 OidParser &parser) 1238{ 1239 const CSSM_OID *oid = &exten->extnId; 1240 const void *thisData = exten->value.parsedValue; 1241 1242 if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) { 1243 if(printCdsaExtensionCommon(exten, parser, false, verbose, true)) { 1244 return; 1245 } 1246 printf(" Unparsed data: "); printDataAsHex(&exten->BERvalue, 8); 1247 } 1248 else if(exten->format != CSSM_X509_DATAFORMAT_PARSED) { 1249 printf("***Badly formatted CSSM_X509_EXTENSION\n"); 1250 return; 1251 } 1252 else if(cuCompareCssmData(oid, &CSSMOID_CrlReason)) { 1253 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { 1254 return; 1255 } 1256 CE_CrlReason *cr = (CE_CrlReason *)thisData; 1257 const char *reason = "UNKNOWN"; 1258 switch(*cr) { 1259 case CE_CR_Unspecified: 1260 reason = "CE_CR_Unspecified"; break; 1261 case CE_CR_KeyCompromise: 1262 reason = "CE_CR_KeyCompromise"; break; 1263 case CE_CR_CACompromise: 1264 reason = "CE_CR_CACompromise"; break; 1265 case CE_CR_AffiliationChanged: 1266 reason = "CE_CR_AffiliationChanged"; break; 1267 case CE_CR_Superseded: 1268 reason = "CE_CR_Superseded"; break; 1269 case CE_CR_CessationOfOperation: 1270 reason = "CE_CR_CessationOfOperation"; break; 1271 case CE_CR_CertificateHold: 1272 reason = "CE_CR_CertificateHold"; break; 1273 case CE_CR_RemoveFromCRL: 1274 reason = "CE_CR_RemoveFromCRL"; break; 1275 default: 1276 break; 1277 } 1278 printf(" CRL Reason : %s\n", reason); 1279 } 1280 else if(cuCompareCssmData(oid, &CSSMOID_HoldInstructionCode)) { 1281 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { 1282 return; 1283 } 1284 printf(" Hold Instr : "); 1285 printOid(parser, (CSSM_OID_PTR)thisData); 1286 } 1287 else if(cuCompareCssmData(oid, &CSSMOID_InvalidityDate)) { 1288 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { 1289 return; 1290 } 1291 printf(" Invalid Date : "); 1292 printTimeStr((CSSM_DATA_PTR)thisData); 1293 } 1294 else if(cuCompareCssmData(oid, &CSSMOID_CertIssuer)) { 1295 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) { 1296 return; 1297 } 1298 printGeneralNames((CE_GeneralNames *)thisData, parser); 1299 } 1300 else { 1301 /* should never happen - we're out of sync with the CL */ 1302 printf("UNKNOWN EXTENSION : "); printOid(parser, oid); 1303 } 1304} 1305 1306static 1307void printCrlFields( 1308 const CSSM_X509_SIGNED_CRL *signedCrl, 1309 CSSM_BOOL verbose, 1310 OidParser &parser) 1311{ 1312 unsigned i; 1313 const CSSM_X509_TBS_CERTLIST *tbsCrl = &signedCrl->tbsCertList; 1314 1315 if(tbsCrl->version.Data) { 1316 printf("Version : %d\n", cuDER_ToInt(&tbsCrl->version)); 1317 } 1318 1319 printf("TBS Sig Algorithm : "); 1320 const CSSM_X509_ALGORITHM_IDENTIFIER *algId = &tbsCrl->signature; 1321 printSigAlg(algId, parser); 1322 1323 printf("Issuer Name :\n"); 1324 printName(&tbsCrl->issuer, parser); 1325 1326 printf("This Update : "); 1327 printTime(&tbsCrl->thisUpdate); 1328 printf("Next Update : "); 1329 if(tbsCrl->nextUpdate.time.Data) { 1330 printTime(&tbsCrl->nextUpdate); 1331 } 1332 else { 1333 printf("<not present>\n"); 1334 } 1335 1336 CSSM_X509_REVOKED_CERT_LIST_PTR certList = tbsCrl->revokedCertificates; 1337 if(certList) { 1338 if(verbose) { 1339 printf("Num Revoked Certs : %d\n", 1340 (int)certList->numberOfRevokedCertEntries); 1341 for(i=0; i<certList->numberOfRevokedCertEntries; i++) { 1342 CSSM_X509_REVOKED_CERT_ENTRY_PTR entry; 1343 entry = &certList->revokedCertEntry[i]; 1344 printf("Revoked Cert %d :\n", (int)i); 1345 printf(" Serial number : "); 1346 printDataAsHex(&entry->certificateSerialNumber, 0); 1347 printf(" Revocation time : "); 1348 printTime(&entry->revocationDate); 1349 const CSSM_X509_EXTENSIONS *cssmExtens = &entry->extensions; 1350 uint32 numExtens = cssmExtens->numberOfExtensions; 1351 if(numExtens == 0) { 1352 continue; 1353 } 1354 printf(" Num Extensions : %u\n", (unsigned)numExtens); 1355 for(unsigned dex=0; dex<numExtens; dex++) { 1356 printCrlEntryExten(&cssmExtens->extensions[dex], verbose, 1357 parser); 1358 } 1359 } 1360 } 1361 else { 1362 printf("Num Revoked Certs : %d (use verbose option to see)\n", 1363 (int)certList->numberOfRevokedCertEntries); 1364 } 1365 } 1366 1367 const CSSM_X509_EXTENSIONS *crlExtens = &tbsCrl->extensions; 1368 if(crlExtens->numberOfExtensions) { 1369 printf("Num CRL Extensions : %d\n", 1370 (int)crlExtens->numberOfExtensions); 1371 for(i=0; i<crlExtens->numberOfExtensions; i++) { 1372 printCrlExten(&crlExtens->extensions[i], verbose, parser); 1373 } 1374 } 1375 1376 const CSSM_X509_SIGNATURE *sig = &signedCrl->signature; 1377 if(sig->encrypted.Data) { 1378 printf("Signature : %u bytes : ", (unsigned)sig->encrypted.Length); 1379 printDataAsHex(&sig->encrypted, 8); 1380 } 1381} 1382 1383 1384/* connect to CSSM/CL lazily, once */ 1385static CSSM_CL_HANDLE clHand = 0; 1386 1387int printCert( 1388 const unsigned char *certData, 1389 unsigned certLen, 1390 CSSM_BOOL verbose) 1391{ 1392 CSSM_FIELD_PTR fieldPtr; // mallocd by CL 1393 uint32 i; 1394 uint32 numFields; 1395 OidParser parser; 1396 CSSM_DATA cert; 1397 1398 if(clHand == 0) { 1399 clHand = cuClStartup(); 1400 if(clHand == 0) { 1401 printf("***Error connecting to CSSM cert module; aborting cert " 1402 "display\n"); 1403 return 0; 1404 } 1405 } 1406 cert.Data = (uint8 *)certData; 1407 cert.Length = certLen; 1408 1409 CSSM_RETURN crtn = CSSM_CL_CertGetAllFields(clHand, 1410 &cert, 1411 &numFields, 1412 &fieldPtr); 1413 if(crtn) { 1414 cuPrintError("CSSM_CL_CertGetAllFields", crtn); 1415 return crtn; 1416 } 1417 1418 for(i=0; i<numFields; i++) { 1419 printCertField(fieldPtr[i], parser, verbose); 1420 } 1421 1422 crtn = CSSM_CL_FreeFields(clHand, numFields, &fieldPtr); 1423 if(crtn) { 1424 cuPrintError("CSSM_CL_FreeFields", crtn); 1425 return crtn; 1426 } 1427 return 0; 1428} 1429 1430/* parse CRL */ 1431/* This one's easier, we just get one field - the whole parsed CRL */ 1432int printCrl( 1433 const unsigned char *crlData, 1434 unsigned crlLen, 1435 CSSM_BOOL verbose) 1436{ 1437 CSSM_DATA_PTR value; // mallocd by CL 1438 uint32 numFields; 1439 OidParser parser; 1440 CSSM_DATA crl; 1441 CSSM_HANDLE result; 1442 1443 if(clHand == 0) { 1444 clHand = cuClStartup(); 1445 if(clHand == 0) { 1446 printf("***Error connecting to CSSM cert module; aborting CRL" 1447 "display\n"); 1448 return 0; 1449 } 1450 } 1451 crl.Data = (uint8 *)crlData; 1452 crl.Length = crlLen; 1453 1454 CSSM_RETURN crtn = CSSM_CL_CrlGetFirstFieldValue(clHand, 1455 &crl, 1456 &CSSMOID_X509V2CRLSignedCrlCStruct, 1457 &result, 1458 &numFields, 1459 &value); 1460 if(crtn) { 1461 cuPrintError("CSSM_CL_CrlGetFirstFieldValue", crtn); 1462 return crtn; 1463 } 1464 if(numFields != 1) { 1465 printf("***CSSM_CL_CrlGetFirstFieldValue: numFields error\n"); 1466 printf(" expected 1, got %d\n", (int)numFields); 1467 return 1; 1468 } 1469 crtn = CSSM_CL_CrlAbortQuery(clHand, result); 1470 if(crtn) { 1471 cuPrintError("CSSM_CL_CertAbortQuery", crtn); 1472 return crtn; 1473 } 1474 1475 if(value == NULL) { 1476 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n"); 1477 return 1; 1478 } 1479 if((value->Data == NULL) || 1480 (value->Length != sizeof(CSSM_X509_SIGNED_CRL))) { 1481 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n"); 1482 return 1; 1483 } 1484 const CSSM_X509_SIGNED_CRL *signedCrl = 1485 (const CSSM_X509_SIGNED_CRL *)value->Data; 1486 printCrlFields(signedCrl, verbose, parser); 1487 1488 crtn = CSSM_CL_FreeFieldValue(clHand, 1489 &CSSMOID_X509V2CRLSignedCrlCStruct, 1490 value); 1491 if(crtn) { 1492 cuPrintError("CSSM_CL_FreeFieldValue", crtn); 1493 return crtn; 1494 } 1495 return 0; 1496} 1497 1498 1499void printCertShutdown() 1500{ 1501 if(clHand != 0) { 1502 CSSM_ModuleDetach(clHand); 1503 } 1504} 1505