2 * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
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
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.
19 * cuPrintCert.cpp - Parse a cert or CRL, dump contents.
21 #include "cuCdsaUtils.h"
24 #include <Security/oidscert.h>
25 #include <Security/oidscrl.h>
26 #include <Security/x509defs.h>
27 #include <Security/oidsattr.h>
28 #include <Security/cssmapple.h>
30 #include "cuPrintCert.h"
31 #include "cuOidParser.h"
32 #include "cuTimeStr.h"
33 #include <Security/certextensions.h>
35 static char *months
[] = {
36 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
37 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
40 static void printTimeStr(const CSSM_DATA
*cssmTime
)
44 /* ignore cssmTime->timeType for now */
45 if(cuTimeStringToTm((char *)cssmTime
->Data
, cssmTime
->Length
, &tm
)) {
46 printf("***Bad time string format***\n");
50 printf("***Bad time string format***\n");
53 printf("%02d:%02d:%02d %s %d, %04d\n",
54 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
,
55 months
[tm
.tm_mon
], tm
.tm_mday
, tm
.tm_year
+ 1900);
60 static void printTime(const CSSM_X509_TIME
*cssmTime
)
62 /* ignore cssmTime->timeType for now */
63 printTimeStr(&cssmTime
->time
);
66 static void printDataAsHex(
68 unsigned maxToPrint
= 0) // optional, 0 means print it all
72 uint32 len
= d
->Length
;
75 if((maxToPrint
!= 0) && (len
> maxToPrint
)) {
79 for(i
=0; i
<len
; i
++) {
80 printf("%02X ", ((unsigned char *)cp
)[i
]);
91 * Identify CSSM_BER_TAG with a C string.
93 static char *tagTypeString(
96 static char unknownType
[80];
100 return "BER_TAG_UNKNOWN";
101 case BER_TAG_BOOLEAN
:
102 return "BER_TAG_BOOLEAN";
103 case BER_TAG_INTEGER
:
104 return "BER_TAG_INTEGER";
105 case BER_TAG_BIT_STRING
:
106 return "BER_TAG_BIT_STRING";
107 case BER_TAG_OCTET_STRING
:
108 return "BER_TAG_OCTET_STRING";
110 return "BER_TAG_NULL";
112 return "BER_TAG_OID";
113 case BER_TAG_SEQUENCE
:
114 return "BER_TAG_SEQUENCE";
116 return "BER_TAG_SET";
117 case BER_TAG_PRINTABLE_STRING
:
118 return "BER_TAG_PRINTABLE_STRING";
119 case BER_TAG_T61_STRING
:
120 return "BER_TAG_T61_STRING";
121 case BER_TAG_IA5_STRING
:
122 return "BER_TAG_IA5_STRING";
123 case BER_TAG_UTC_TIME
:
124 return "BER_TAG_UTC_TIME";
125 case BER_TAG_GENERALIZED_TIME
:
126 return "BER_TAG_GENERALIZED_TIME";
128 sprintf(unknownType
, "Other type (0x%x)", tagType
);
134 * Print an OID, assumed to be in BER encoded "Intel" format
135 * Length is inferred from oid->Length
138 static void printOid(OidParser
&parser
, const CSSM_DATA
*oid
)
140 char strBuf
[OID_PARSER_STRING_SIZE
];
146 if((oid
->Length
== 0) || (oid
->Data
== NULL
)) {
150 parser
.oidParse(oid
->Data
, oid
->Length
, strBuf
);
151 printf("%s\n", strBuf
);
155 * Used to print generic blobs which we don't really understand.
156 * The bytesToPrint argument is usually thing->Length; it's here because snacc
157 * peports lengths of bit strings in BITS. Caller knows this and
158 * modifies bytesToPrint accordingly. In any case, bytesToPrint is the
159 * max number of valid bytes in *thing->Data.
161 #define BLOB_LENGTH_PRINT 3
163 static void printBlobBytes(
165 char *quanta
, // e.g., "bytes', "bits"
167 const CSSM_DATA
*thing
)
170 uint32 toPrint
= bytesToPrint
;
172 if(toPrint
> BLOB_LENGTH_PRINT
) {
173 toPrint
= BLOB_LENGTH_PRINT
;
175 printf("%s; Length %u %s; data = ",
176 blobType
, (unsigned)thing
->Length
, quanta
);
177 for(dex
=0; dex
<toPrint
; dex
++) {
178 printf("0x%x ", thing
->Data
[dex
]);
179 if(dex
== (toPrint
- 1)) {
183 if(dex
< bytesToPrint
) {
192 * Print an IA5String or Printable string. Null terminator is not assumed.
193 * Trailing newline is printed.
195 static void printString(
196 const CSSM_DATA
*str
)
199 char *cp
= (char *)str
->Data
;
200 for(i
=0; i
<str
->Length
; i
++) {
206 static void printDerThing(
207 CSSM_BER_TAG tagType
,
208 const CSSM_DATA
*thing
,
212 case BER_TAG_INTEGER
:
213 printf("%d\n", cuDER_ToInt(thing
));
215 case BER_TAG_BOOLEAN
:
216 if(thing
->Length
!= 1) {
217 printf("***malformed BER_TAG_BOOLEAN: length %u data ",
218 (unsigned)thing
->Length
);
220 printf("%u\n", cuDER_ToInt(thing
));
222 case BER_TAG_PRINTABLE_STRING
:
223 case BER_TAG_IA5_STRING
:
224 case BER_TAG_T61_STRING
: // mostly printable....
227 case BER_TAG_OCTET_STRING
:
228 printBlobBytes("Byte string", "bytes", thing
->Length
, thing
);
230 case BER_TAG_BIT_STRING
:
231 printBlobBytes("Bit string", "bits", (thing
->Length
+ 7) / 8, thing
);
233 case BER_TAG_SEQUENCE
:
234 printBlobBytes("Sequence", "bytes", thing
->Length
, thing
);
237 printBlobBytes("Set", "bytes", thing
->Length
, thing
);
241 printOid(parser
, thing
);
244 printf("not displayed (tagType = %s; length %u)\n",
245 tagTypeString(tagType
), (unsigned)thing
->Length
);
251 static void printSigAlg(
252 const CSSM_X509_ALGORITHM_IDENTIFIER
*sigAlg
,
255 printOid(parser
, &sigAlg
->algorithm
);
256 if(sigAlg
->parameters
.Data
!= NULL
) {
257 printf(" alg params : ");
258 printDataAsHex(&sigAlg
->parameters
, 8);
262 /* compare two OIDs, return CSSM_TRUE if identical */
263 static CSSM_BOOL
compareOids(
264 const CSSM_OID
*oid1
,
265 const CSSM_OID
*oid2
)
267 if((oid1
== NULL
) || (oid2
== NULL
)) {
270 if(oid1
->Length
!= oid2
->Length
) {
273 if(memcmp(oid1
->Data
, oid2
->Data
, oid1
->Length
)) {
281 static void printRdn(
282 const CSSM_X509_RDN
*rdnp
,
285 CSSM_X509_TYPE_VALUE_PAIR
*ptvp
;
289 for(pairDex
=0; pairDex
<rdnp
->numberOfPairs
; pairDex
++) {
290 ptvp
= &rdnp
->AttributeTypeAndValue
[pairDex
];
291 if(compareOids(&ptvp
->type
, &CSSMOID_CountryName
)) {
292 fieldName
= "Country ";
294 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationName
)) {
297 else if(compareOids(&ptvp
->type
, &CSSMOID_LocalityName
)) {
298 fieldName
= "Locality ";
300 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationalUnitName
)) {
301 fieldName
= "OrgUnit ";
303 else if(compareOids(&ptvp
->type
, &CSSMOID_CommonName
)) {
304 fieldName
= "Common Name ";
306 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
307 fieldName
= "Surname ";
309 else if(compareOids(&ptvp
->type
, &CSSMOID_Title
)) {
310 fieldName
= "Title ";
312 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
313 fieldName
= "Surname ";
315 else if(compareOids(&ptvp
->type
, &CSSMOID_StateProvinceName
)) {
316 fieldName
= "State ";
318 else if(compareOids(&ptvp
->type
, &CSSMOID_CollectiveStateProvinceName
)) {
319 fieldName
= "Coll. State ";
321 else if(compareOids(&ptvp
->type
, &CSSMOID_EmailAddress
)) {
322 /* deprecated, used by Thawte */
323 fieldName
= "Email addrs ";
326 fieldName
= "Other name ";
328 printf(" %s : ", fieldName
);
329 printDerThing(ptvp
->valueType
, &ptvp
->value
, parser
);
330 } /* for each type/value pair */
333 static CSSM_RETURN
printName(
334 const CSSM_X509_NAME
*x509Name
,
337 CSSM_X509_RDN_PTR rdnp
;
340 for(rdnDex
=0; rdnDex
<x509Name
->numberOfRDNs
; rdnDex
++) {
341 rdnp
= &x509Name
->RelativeDistinguishedName
[rdnDex
];
342 printRdn(rdnp
, parser
);
348 static void printKeyHeader(
349 const CSSM_KEYHEADER
&hdr
)
351 printf(" Algorithm : ");
352 switch(hdr
.AlgorithmId
) {
363 printf("Diffie-Hellman\n");
366 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr
.AlgorithmId
,
367 (unsigned)hdr
.AlgorithmId
);
369 printf(" Key Size : %u bits\n", (unsigned)hdr
.LogicalKeySizeInBits
);
370 printf(" Key Use : ");
371 CSSM_KEYUSE usage
= hdr
.KeyUsage
;
372 if(usage
& CSSM_KEYUSE_ANY
) {
373 printf("CSSM_KEYUSE_ANY ");
375 if(usage
& CSSM_KEYUSE_ENCRYPT
) {
376 printf("CSSM_KEYUSE_ENCRYPT ");
378 if(usage
& CSSM_KEYUSE_DECRYPT
) {
379 printf("CSSM_KEYUSE_DECRYPT ");
381 if(usage
& CSSM_KEYUSE_SIGN
) {
382 printf("CSSM_KEYUSE_SIGN ");
384 if(usage
& CSSM_KEYUSE_VERIFY
) {
385 printf("CSSM_KEYUSE_VERIFY ");
387 if(usage
& CSSM_KEYUSE_SIGN_RECOVER
) {
388 printf("CSSM_KEYUSE_SIGN_RECOVER ");
390 if(usage
& CSSM_KEYUSE_VERIFY_RECOVER
) {
391 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
393 if(usage
& CSSM_KEYUSE_WRAP
) {
394 printf("CSSM_KEYUSE_WRAP ");
396 if(usage
& CSSM_KEYUSE_UNWRAP
) {
397 printf("CSSM_KEYUSE_UNWRAP ");
399 if(usage
& CSSM_KEYUSE_DERIVE
) {
400 printf("CSSM_KEYUSE_DERIVE ");
407 * Print contents of a CE_GeneralNames as best we can.
409 static void printGeneralNames(
410 const CE_GeneralNames
*generalNames
,
414 CE_GeneralName
*name
;
416 for(i
=0; i
<generalNames
->numNames
; i
++) {
417 name
= &generalNames
->generalName
[i
];
418 switch(name
->nameType
) {
420 printf(" RFC822Name : ");
421 printString(&name
->name
);
424 printf(" DNSName : ");
425 printString(&name
->name
);
429 printString(&name
->name
);
432 printf(" IP Address : ");
433 for(unsigned i
=0; i
<name
->name
.Length
; i
++) {
434 printf("%d", name
->name
.Data
[i
]);
435 if(i
< (name
->name
.Length
- 1)) {
441 case GNT_RegisteredID
:
442 printf(" RegisteredID : ");
443 printOid(parser
, &name
->name
);
445 case GNT_X400Address
:
446 /* ORAddress, a very complicated struct - punt */
447 printf(" X400Address : ");
448 printBlobBytes("Sequence", "bytes", name
->name
.Length
, &name
->name
);
450 case GNT_DirectoryName
:
451 if(!name
->berEncoded
) {
452 /* CL parsed it for us into an CSSM_X509_NAME */
453 if(name
->name
.Length
!= sizeof(CSSM_X509_NAME
)) {
454 printf("***MALFORMED GNT_DirectoryName\n");
457 const CSSM_X509_NAME
*x509Name
=
458 (const CSSM_X509_NAME
*)name
->name
.Data
;
459 printf(" Dir Name :\n");
460 printName(x509Name
, parser
);
463 /* encoded Name (i.e. CSSM_X509_NAME) */
464 printf(" Dir Name : ");
465 printBlobBytes("Byte string", "bytes",
466 name
->name
.Length
, &name
->name
);
469 case GNT_EdiPartyName
:
470 /* sequence EDIPartyName */
471 printf(" EdiPartyName : ");
472 printBlobBytes("Sequence", "bytes", name
->name
.Length
, &name
->name
);
476 printf(" OtherName :\n");
477 if(name
->name
.Length
!= sizeof(CE_OtherName
)) {
478 printf("***Malformed CE_OtherName\n");
481 CE_OtherName
*other
= (CE_OtherName
*)name
->name
.Data
;
482 printf(" typeID : ");
483 printOid(parser
, &other
->typeId
);
485 printDataAsHex(&other
->value
, 0);
492 static int printCdsaExtensionCommon(
493 const CSSM_X509_EXTENSION
*cssmExt
,
497 bool extraIndent
= false)
500 printf(" Extension : "); printOid(parser
, &cssmExt
->extnId
);
501 printf(" Critical : %s\n", cssmExt
->critical
? "TRUE" : "FALSE");
504 printf("Extension struct : "); printOid(parser
, &cssmExt
->extnId
);
505 printf(" Critical : %s\n", cssmExt
->critical
? "TRUE" : "FALSE");
507 switch(cssmExt
->format
) {
508 case CSSM_X509_DATAFORMAT_ENCODED
:
510 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n");
513 if((cssmExt
->BERvalue
.Data
== NULL
) ||
514 (cssmExt
->value
.parsedValue
!= NULL
)) {
515 printf("***Malformed CSSM_X509_EXTENSION (1)\n");
519 case CSSM_X509_DATAFORMAT_PARSED
:
521 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
524 if((cssmExt
->BERvalue
.Data
!= NULL
) ||
525 (cssmExt
->value
.parsedValue
== NULL
)) {
526 printf("***Malformed CSSM_X509_EXTENSION (2)\n");
530 case CSSM_X509_DATAFORMAT_PAIR
:
531 /* both parsed and encoded forms present */
533 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
536 if((cssmExt
->BERvalue
.Data
== NULL
) ||
537 (cssmExt
->value
.parsedValue
== NULL
)) {
538 printf("***Malformed CSSM_X509_EXTENSION (3)\n");
542 /* also print some of the encoded form */
544 printf(" Unparsed data : ");
547 printf(" Unparsed data : ");
549 printDataAsHex(&cssmExt
->BERvalue
, 8);
553 printf("***Unknown CSSM_X509_EXTENSION.format\n");
559 static int printExtensionCommon(
560 const CSSM_DATA
&value
,
563 bool expectParsed
= true)
565 if(value
.Length
!= sizeof(CSSM_X509_EXTENSION
)) {
566 printf("***malformed CSSM_FIELD (1)\n");
569 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
570 return printCdsaExtensionCommon(cssmExt
, parser
, expectParsed
, verbose
);
574 static void printKeyUsage(
575 const CSSM_DATA
&value
)
578 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
580 usage
= *((CE_KeyUsage
*)cssmExt
->value
.parsedValue
);
582 if(usage
& CE_KU_DigitalSignature
) {
583 printf("DigitalSignature ");
585 if(usage
& CE_KU_NonRepudiation
) {
586 printf("NonRepudiation ");
588 if(usage
& CE_KU_KeyEncipherment
) {
589 printf("KeyEncipherment ");
591 if(usage
& CE_KU_DataEncipherment
) {
592 printf("DataEncipherment ");
594 if(usage
& CE_KU_KeyAgreement
) {
595 printf("KeyAgreement ");
597 if(usage
& CE_KU_KeyCertSign
) {
598 printf("KeyCertSign ");
600 if(usage
& CE_KU_CRLSign
) {
603 if(usage
& CE_KU_EncipherOnly
) {
604 printf("EncipherOnly ");
606 if(usage
& CE_KU_DecipherOnly
) {
607 printf("DecipherOnly ");
613 static void printBasicConstraints(
614 const CSSM_DATA
&value
)
616 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
617 CE_BasicConstraints
*bc
= (CE_BasicConstraints
*)cssmExt
->value
.parsedValue
;
618 printf(" CA : %s\n", bc
->cA
? "TRUE" : "FALSE");
619 if(bc
->pathLenConstraintPresent
) {
620 printf(" pathLenConstr : %u\n", (unsigned)bc
->pathLenConstraint
);
624 static void printExtKeyUsage(
625 const CSSM_DATA
&value
,
628 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
629 CE_ExtendedKeyUsage
*eku
= (CE_ExtendedKeyUsage
*)cssmExt
->value
.parsedValue
;
631 for(oidDex
=0; oidDex
<eku
->numPurposes
; oidDex
++) {
632 printf(" purpose %2d : ", oidDex
);
633 printOid(parser
, &eku
->purposes
[oidDex
]);
637 static void printCssmAuthorityKeyId(
638 const CE_AuthorityKeyID
*akid
,
641 if(akid
->keyIdentifierPresent
) {
642 printf(" Auth KeyID : ");
643 printDataAsHex(&akid
->keyIdentifier
,
646 if(akid
->generalNamesPresent
) {
647 printGeneralNames(akid
->generalNames
, parser
);
649 if(akid
->serialNumberPresent
) {
650 printf(" serialNumber : ");
651 printDataAsHex(&akid
->serialNumber
, 8);
655 static void printAuthorityKeyId(
656 const CSSM_DATA
&value
,
659 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
660 CE_AuthorityKeyID
*akid
= (CE_AuthorityKeyID
*)cssmExt
->value
.parsedValue
;
661 printCssmAuthorityKeyId(akid
, parser
);
664 static void printSubjectIssuerAltName(
665 const CSSM_DATA
&value
,
668 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
669 CE_GeneralNames
*san
= (CE_GeneralNames
*)cssmExt
->value
.parsedValue
;
670 printGeneralNames(san
, parser
);
673 static void printDistPointName(
674 const CE_DistributionPointName
*dpn
,
677 switch(dpn
->nameType
) {
678 case CE_CDNT_FullName
:
679 printGeneralNames(dpn
->fullName
, parser
);
681 case CE_CDNT_NameRelativeToCrlIssuer
:
682 printRdn(dpn
->rdn
, parser
);
685 printf("***BOGUS CE_DistributionPointName.nameType\n");
690 static void printDistPoint(
691 const CE_CRLDistributionPoint
*dp
,
694 if(dp
->distPointName
) {
695 printf(" Dist pt Name :\n");
696 printDistPointName(dp
->distPointName
, parser
);
698 printf(" reasonsPresent : %s\n", dp
->reasonsPresent
? "TRUE" : "FALSE");
699 if(dp
->reasonsPresent
) {
701 printf(" reasons : 0x%X\n", dp
->reasons
);
704 printf(" CRLIssuer :\n");
705 printGeneralNames(dp
->crlIssuer
, parser
);
709 static void printDistributionPoints(
710 const CSSM_DATA
&value
,
713 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
714 CE_CRLDistPointsSyntax
*dps
= (CE_CRLDistPointsSyntax
*)cssmExt
->value
.parsedValue
;
716 for(unsigned dex
=0; dex
<dps
->numDistPoints
; dex
++) {
717 printf(" Dist pt %d :\n", dex
);
718 printDistPoint(&dps
->distPoints
[dex
], parser
);
722 static void printValueOrNotPresent(
727 printf("<Not Present>\n");
737 static void printIssuingDistributionPoint(
738 const CE_IssuingDistributionPoint
*idp
,
741 if(idp
->distPointName
) {
742 printf(" Dist pt :\n");
743 printDistPointName(idp
->distPointName
, parser
);
745 printf(" Only user certs : ");
746 printValueOrNotPresent(idp
->onlyUserCertsPresent
, idp
->onlyUserCerts
);
747 printf(" Only CA certs : ");
748 printValueOrNotPresent(idp
->onlyCACertsPresent
, idp
->onlyCACerts
);
749 printf(" Only some reason: ");
750 printValueOrNotPresent(idp
->onlySomeReasonsPresent
, idp
->onlySomeReasons
);
751 printf(" Indirectl CRL : ");
752 printValueOrNotPresent(idp
->indirectCrlPresent
, idp
->indirectCrl
);
755 static void printCertPolicies(
756 const CSSM_DATA
&value
,
759 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
760 CE_CertPolicies
*cdsaObj
= (CE_CertPolicies
*)cssmExt
->value
.parsedValue
;
761 for(unsigned polDex
=0; polDex
<cdsaObj
->numPolicies
; polDex
++) {
762 CE_PolicyInformation
*cPolInfo
= &cdsaObj
->policies
[polDex
];
763 printf(" Policy %2d : ID ", polDex
);
764 printOid(parser
, &cPolInfo
->certPolicyId
);
765 for(unsigned qualDex
=0; qualDex
<cPolInfo
->numPolicyQualifiers
; qualDex
++) {
766 CE_PolicyQualifierInfo
*cQualInfo
= &cPolInfo
->policyQualifiers
[qualDex
];
767 printf(" Qual %2d : ID ", qualDex
);
768 printOid(parser
, &cQualInfo
->policyQualifierId
);
769 if(cuCompareCssmData(&cQualInfo
->policyQualifierId
,
772 printString(&cQualInfo
->qualifier
);
775 printf(" unparsed : ");
776 printDataAsHex(&cQualInfo
->qualifier
, 8);
782 static void printNetscapeCertType(
783 const CSSM_DATA
&value
)
785 CE_NetscapeCertType certType
;
786 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
788 certType
= *((CE_NetscapeCertType
*)cssmExt
->value
.parsedValue
);
789 printf(" certType : ");
790 if(certType
& CE_NCT_SSL_Client
) {
791 printf("SSL_Client ");
793 if(certType
& CE_NCT_SSL_Server
) {
794 printf("SSL_Server ");
796 if(certType
& CE_NCT_SMIME
) {
799 if(certType
& CE_NCT_ObjSign
) {
800 printf("ObjectSign ");
802 if(certType
& CE_NCT_Reserved
) {
805 if(certType
& CE_NCT_SSL_CA
) {
808 if(certType
& CE_NCT_SMIME_CA
) {
811 if(certType
& CE_NCT_ObjSignCA
) {
812 printf("ObjSignCA ");
817 /* print one field */
819 const CSSM_FIELD
&field
,
823 const CSSM_DATA
*thisData
= &field
.FieldValue
;
824 const CSSM_OID
*thisOid
= &field
.FieldOid
;
826 if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Version
)) {
828 printf("Version : %u\n", cuDER_ToInt(thisData
));
831 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SerialNumber
)) {
832 printf("Serial Number : "); printDataAsHex(thisData
, 0);
834 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerNameCStruct
)) {
835 printf("Issuer Name :\n");
836 CSSM_X509_NAME_PTR name
= (CSSM_X509_NAME_PTR
)thisData
->Data
;
837 if((name
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_NAME
))) {
838 printf(" ***malformed CSSM_X509_NAME\n");
841 printName(name
, parser
);
844 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectNameCStruct
)) {
845 printf("Subject Name :\n");
846 CSSM_X509_NAME_PTR name
= (CSSM_X509_NAME_PTR
)thisData
->Data
;
847 if((name
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_NAME
))) {
848 printf(" ***malformed CSSM_X509_NAME\n");
851 printName(name
, parser
);
854 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1ValidityNotBefore
)) {
855 CSSM_X509_TIME
*cssmTime
= (CSSM_X509_TIME
*)thisData
->Data
;
856 if((cssmTime
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_TIME
))) {
857 printf(" ***malformed CSSM_X509_TIME\n");
860 printf("Not Before : "); printString(&cssmTime
->time
);
865 printf("Not Before : ");
869 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1ValidityNotAfter
)) {
870 CSSM_X509_TIME
*cssmTime
= (CSSM_X509_TIME
*)thisData
->Data
;
871 if((cssmTime
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_TIME
))) {
872 printf(" ***malformed CSSM_X509_TIME\n");
875 printf("Not After : "); printString(&cssmTime
->time
);
880 printf("Not After : ");
884 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SignatureAlgorithmTBS
)) {
886 /* normally skip, it's the same as TBS sig alg */
887 printf("TBS Sig Algorithm : ");
888 CSSM_X509_ALGORITHM_IDENTIFIER
*algId
=
889 (CSSM_X509_ALGORITHM_IDENTIFIER
*)thisData
->Data
;
890 if((algId
== NULL
) ||
891 (thisData
->Length
!= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
))) {
892 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n");
895 printSigAlg(algId
, parser
);
899 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SignatureAlgorithm
)) {
900 printf("Cert Sig Algorithm : ");
901 CSSM_X509_ALGORITHM_IDENTIFIER
*algId
=
902 (CSSM_X509_ALGORITHM_IDENTIFIER
*)thisData
->Data
;
903 if((algId
== NULL
) ||
904 (thisData
->Length
!= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
))) {
905 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n");
908 printSigAlg(algId
, parser
);
911 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateIssuerUniqueId
)) {
913 printf("Issuer UniqueId : ");
914 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
917 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateSubjectUniqueId
)) {
919 printf("Subject UniqueId : ");
920 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
923 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectPublicKeyCStruct
)) {
924 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*pubKeyInfo
=
925 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)thisData
->Data
;
926 printf("Pub Key Algorithm : ");
927 if((pubKeyInfo
== NULL
) ||
928 (thisData
->Length
!= sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
))) {
929 printf(" ***malformed CSSM_X509_SUBJECT_PUBLIC_KEY_INFO\n");
932 printSigAlg(&pubKeyInfo
->algorithm
, parser
);
933 printf("Pub key Bytes : Length %u bytes : ",
934 (unsigned)pubKeyInfo
->subjectPublicKey
.Length
);
935 printDataAsHex(&pubKeyInfo
->subjectPublicKey
, 8);
938 else if(cuCompareCssmData(thisOid
, &CSSMOID_CSSMKeyStruct
)) {
939 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)thisData
->Data
;
940 printf("CSSM Key :\n");
941 if((cssmKey
== NULL
) ||
942 (thisData
->Length
!= sizeof(CSSM_KEY
))) {
943 printf(" ***malformed CSSM_KEY\n");
946 printKeyHeader(cssmKey
->KeyHeader
);
948 printf(" Key Blob : ");
949 printDataAsHex(&cssmKey
->KeyData
, 8);
953 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Signature
)) {
954 printf("Signature : %u bytes : ", (unsigned)thisData
->Length
);
955 printDataAsHex(thisData
, 8);
957 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V3CertificateExtensionCStruct
)) {
958 if(printExtensionCommon(*thisData
, parser
, verbose
, false)) {
961 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)thisData
->Data
;
962 printf(" Unparsed data : "); printDataAsHex(&cssmExt
->BERvalue
, 8);
964 else if(cuCompareCssmData(thisOid
, &CSSMOID_KeyUsage
)) {
965 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
968 printKeyUsage(*thisData
);
970 else if(cuCompareCssmData(thisOid
, &CSSMOID_BasicConstraints
)) {
971 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
974 printBasicConstraints(*thisData
);
976 else if(cuCompareCssmData(thisOid
, &CSSMOID_ExtendedKeyUsage
)) {
977 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
980 printExtKeyUsage(*thisData
, parser
);
982 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectKeyIdentifier
)) {
983 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
986 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)thisData
->Data
;
987 CSSM_DATA_PTR cdata
= (CSSM_DATA_PTR
)cssmExt
->value
.parsedValue
;
988 if((cdata
== NULL
) || (cdata
->Data
== NULL
)) {
989 printf("****Malformed extension (no parsedValue)\n");
992 printf(" Subject KeyID : "); printDataAsHex(cdata
, 8);
995 else if(cuCompareCssmData(thisOid
, &CSSMOID_AuthorityKeyIdentifier
)) {
996 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
999 printAuthorityKeyId(*thisData
, parser
);
1001 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectAltName
)) {
1002 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1005 printSubjectIssuerAltName(*thisData
, parser
);
1007 else if(cuCompareCssmData(thisOid
, &CSSMOID_IssuerAltName
)) {
1008 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1011 printSubjectIssuerAltName(*thisData
, parser
);
1013 else if(cuCompareCssmData(thisOid
, &CSSMOID_CertificatePolicies
)) {
1014 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1017 printCertPolicies(*thisData
, parser
);
1019 else if(cuCompareCssmData(thisOid
, &CSSMOID_NetscapeCertType
)) {
1020 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1023 printNetscapeCertType(*thisData
);
1025 else if(cuCompareCssmData(thisOid
, &CSSMOID_CrlDistributionPoints
)) {
1026 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1029 printDistributionPoints(*thisData
, parser
);
1031 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerName
)) {
1033 printf("Normalized Issuer : ");
1034 printDataAsHex(thisData
, 8);
1037 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectName
)) {
1039 printf("Normalized Subject : ");
1040 printDataAsHex(thisData
, 8);
1044 printf("Other field: : "); printOid(parser
, thisOid
);
1049 const CSSM_X509_EXTENSION
*exten
,
1053 const CSSM_OID
*oid
= &exten
->extnId
;
1054 const void *thisData
= exten
->value
.parsedValue
;
1056 if(exten
->format
== CSSM_X509_DATAFORMAT_ENCODED
) {
1057 if(printCdsaExtensionCommon(exten
, parser
, false, verbose
)) {
1060 printf(" Unparsed data : "); printDataAsHex(&exten
->BERvalue
, 8);
1062 else if(exten
->format
!= CSSM_X509_DATAFORMAT_PAIR
) {
1063 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1066 else if(cuCompareCssmData(oid
, &CSSMOID_AuthorityKeyIdentifier
)) {
1067 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1070 printCssmAuthorityKeyId((CE_AuthorityKeyID
*)thisData
, parser
);
1072 else if(cuCompareCssmData(oid
, &CSSMOID_IssuerAltName
)) {
1073 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1076 printGeneralNames((CE_GeneralNames
*)thisData
, parser
);
1078 else if(cuCompareCssmData(oid
, &CSSMOID_CrlNumber
)) {
1079 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1082 printf(" CRL Number : %u\n", *((unsigned *)thisData
));
1084 else if(cuCompareCssmData(oid
, &CSSMOID_DeltaCrlIndicator
)) {
1085 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1088 printf(" Delta CRL Base : %u\n", *((unsigned *)thisData
));
1090 else if(cuCompareCssmData(oid
, &CSSMOID_IssuingDistributionPoint
)) {
1091 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1094 printIssuingDistributionPoint((CE_IssuingDistributionPoint
*)thisData
,
1098 /* should never happen - we're out of sync with the CL */
1099 printf("UNKNOWN EXTENSION : "); printOid(parser
, oid
);
1103 void printCrlEntryExten(
1104 const CSSM_X509_EXTENSION
*exten
,
1108 const CSSM_OID
*oid
= &exten
->extnId
;
1109 const void *thisData
= exten
->value
.parsedValue
;
1111 if(exten
->format
== CSSM_X509_DATAFORMAT_ENCODED
) {
1112 if(printCdsaExtensionCommon(exten
, parser
, false, verbose
, true)) {
1115 printf(" Unparsed data: "); printDataAsHex(&exten
->BERvalue
, 8);
1117 else if(exten
->format
!= CSSM_X509_DATAFORMAT_PAIR
) {
1118 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1121 else if(cuCompareCssmData(oid
, &CSSMOID_CrlReason
)) {
1122 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1125 CE_CrlReason
*cr
= (CE_CrlReason
*)thisData
;
1126 char *reason
= "UNKNOWN";
1128 case CE_CR_Unspecified
:
1129 reason
= "CE_CR_Unspecified"; break;
1130 case CE_CR_KeyCompromise
:
1131 reason
= "CE_CR_KeyCompromise"; break;
1132 case CE_CR_CACompromise
:
1133 reason
= "CE_CR_CACompromise"; break;
1134 case CE_CR_AffiliationChanged
:
1135 reason
= "CE_CR_AffiliationChanged"; break;
1136 case CE_CR_Superseded
:
1137 reason
= "CE_CR_Superseded"; break;
1138 case CE_CR_CessationOfOperation
:
1139 reason
= "CE_CR_CessationOfOperation"; break;
1140 case CE_CR_CertificateHold
:
1141 reason
= "CE_CR_CertificateHold"; break;
1142 case CE_CR_RemoveFromCRL
:
1143 reason
= "CE_CR_RemoveFromCRL"; break;
1147 printf(" CRL Reason : %s\n", reason
);
1149 else if(cuCompareCssmData(oid
, &CSSMOID_HoldInstructionCode
)) {
1150 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1153 printf(" Hold Instr : ");
1154 printOid(parser
, (CSSM_OID_PTR
)thisData
);
1156 else if(cuCompareCssmData(oid
, &CSSMOID_InvalidityDate
)) {
1157 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1160 printf(" Invalid Date : ");
1161 printTimeStr((CSSM_DATA_PTR
)thisData
);
1163 else if(cuCompareCssmData(oid
, &CSSMOID_CertIssuer
)) {
1164 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1167 printGeneralNames((CE_GeneralNames
*)thisData
, parser
);
1170 /* should never happen - we're out of sync with the CL */
1171 printf("UNKNOWN EXTENSION : "); printOid(parser
, oid
);
1175 void printCrlFields(
1176 const CSSM_X509_SIGNED_CRL
*signedCrl
,
1181 const CSSM_X509_TBS_CERTLIST
*tbsCrl
= &signedCrl
->tbsCertList
;
1183 if(tbsCrl
->version
.Data
) {
1184 printf("Version : %d\n", cuDER_ToInt(&tbsCrl
->version
));
1187 printf("TBS Sig Algorithm : ");
1188 const CSSM_X509_ALGORITHM_IDENTIFIER
*algId
= &tbsCrl
->signature
;
1189 printSigAlg(algId
, parser
);
1191 printf("Issuer Name :\n");
1192 printName(&tbsCrl
->issuer
, parser
);
1194 printf("This Update : ");
1195 printTime(&tbsCrl
->thisUpdate
);
1196 printf("Next Update : ");
1197 if(tbsCrl
->nextUpdate
.time
.Data
) {
1198 printTime(&tbsCrl
->nextUpdate
);
1201 printf("<not present>\n");
1204 CSSM_X509_REVOKED_CERT_LIST_PTR certList
= tbsCrl
->revokedCertificates
;
1207 printf("Num Revoked Certs : %d\n",
1208 (int)certList
->numberOfRevokedCertEntries
);
1209 for(i
=0; i
<certList
->numberOfRevokedCertEntries
; i
++) {
1210 CSSM_X509_REVOKED_CERT_ENTRY_PTR entry
;
1211 entry
= &certList
->revokedCertEntry
[i
];
1212 printf("Revoked Cert %d :\n", (int)i
);
1213 printf(" Serial number : ");
1214 printDataAsHex(&entry
->certificateSerialNumber
, 0);
1215 printf(" Revocation time : ");
1216 printTime(&entry
->revocationDate
);
1217 const CSSM_X509_EXTENSIONS
*cssmExtens
= &entry
->extensions
;
1218 uint32 numExtens
= cssmExtens
->numberOfExtensions
;
1219 if(numExtens
== 0) {
1222 printf(" Num Extensions : %u\n", (unsigned)numExtens
);
1223 for(unsigned dex
=0; dex
<numExtens
; dex
++) {
1224 printCrlEntryExten(&cssmExtens
->extensions
[dex
], verbose
,
1230 printf("Num Revoked Certs : %d (use verbose option to see)\n",
1231 (int)certList
->numberOfRevokedCertEntries
);
1235 const CSSM_X509_EXTENSIONS
*crlExtens
= &tbsCrl
->extensions
;
1236 if(crlExtens
->numberOfExtensions
) {
1237 printf("Num CRL Extensions : %d\n",
1238 (int)crlExtens
->numberOfExtensions
);
1239 for(i
=0; i
<crlExtens
->numberOfExtensions
; i
++) {
1240 printCrlExten(&crlExtens
->extensions
[i
], verbose
, parser
);
1244 const CSSM_X509_SIGNATURE
*sig
= &signedCrl
->signature
;
1245 if(sig
->encrypted
.Data
) {
1246 printf("Signature : %u bytes : ", (unsigned)sig
->encrypted
.Length
);
1247 printDataAsHex(&sig
->encrypted
, 8);
1252 /* connect to CSSM/CL lazily, once */
1253 static CSSM_CL_HANDLE clHand
= 0;
1256 const unsigned char *certData
,
1260 CSSM_FIELD_PTR fieldPtr
; // mallocd by CL
1267 clHand
= cuClStartup();
1269 printf("***Error connecting to CSSM cert module; aborting cert "
1274 cert
.Data
= (uint8
*)certData
;
1275 cert
.Length
= certLen
;
1277 CSSM_RETURN crtn
= CSSM_CL_CertGetAllFields(clHand
,
1282 cuPrintError("CSSM_CL_CertGetAllFields", crtn
);
1286 for(i
=0; i
<numFields
; i
++) {
1287 printCertField(fieldPtr
[i
], parser
, verbose
);
1290 crtn
= CSSM_CL_FreeFields(clHand
, numFields
, &fieldPtr
);
1292 cuPrintError("CSSM_CL_FreeFields", crtn
);
1299 /* This one's easier, we just get one field - the whole parsed CRL */
1301 const unsigned char *crlData
,
1305 CSSM_DATA_PTR value
; // mallocd by CL
1312 clHand
= cuClStartup();
1314 printf("***Error connecting to CSSM cert module; aborting CRL"
1319 crl
.Data
= (uint8
*)crlData
;
1320 crl
.Length
= crlLen
;
1322 CSSM_RETURN crtn
= CSSM_CL_CrlGetFirstFieldValue(clHand
,
1324 &CSSMOID_X509V2CRLSignedCrlCStruct
,
1329 cuPrintError("CSSM_CL_CrlGetFirstFieldValue", crtn
);
1332 if(numFields
!= 1) {
1333 printf("***CSSM_CL_CrlGetFirstFieldValue: numFields error\n");
1334 printf(" expected 1, got %d\n", (int)numFields
);
1337 crtn
= CSSM_CL_CrlAbortQuery(clHand
, result
);
1339 cuPrintError("CSSM_CL_CertAbortQuery", crtn
);
1344 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n");
1347 if((value
->Data
== NULL
) ||
1348 (value
->Length
!= sizeof(CSSM_X509_SIGNED_CRL
))) {
1349 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n");
1352 const CSSM_X509_SIGNED_CRL
*signedCrl
=
1353 (const CSSM_X509_SIGNED_CRL
*)value
->Data
;
1354 printCrlFields(signedCrl
, verbose
, parser
);
1356 crtn
= CSSM_CL_FreeFieldValue(clHand
,
1357 &CSSMOID_X509V2CRLSignedCrlCStruct
,
1360 cuPrintError("CSSM_CL_FreeFieldValue", crtn
);
1367 void printCertShutdown()
1370 CSSM_ModuleDetach(clHand
);