2 * Parse a cert, dump contents.
7 #include <Security/oidscert.h>
8 #include <Security/x509defs.h>
9 #include <Security/oidsattr.h>
10 #include <Security/cssmapple.h>
12 #include "printCert.h"
13 #include "oidParser.h"
15 #include <Security/certextensions.h>
17 static char *months
[] = {
18 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
19 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
23 * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to a
26 static uint32
DER_ToInt(const CSSM_DATA
*DER_Data
)
31 while(i
< DER_Data
->Length
) {
32 rtn
|= DER_Data
->Data
[i
];
33 if(++i
== DER_Data
->Length
) {
41 static void printTime(const CSSM_X509_TIME
*cssmTime
)
45 /* ignore cssmTime->timeType for now */
46 if(appTimeStringToTm((char *)cssmTime
->time
.Data
, cssmTime
->time
.Length
, &tm
)) {
47 printf("***Bad time string format***\n");
51 printf("***Bad time string format***\n");
54 printf("%02d:%02d:%02d %s %d, %04d\n",
55 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
,
56 months
[tm
.tm_mon
], tm
.tm_mday
, tm
.tm_year
+ 1900);
60 static void printDataAsHex(
62 unsigned maxToPrint
= 0) // optional, 0 means print it all
66 uint32 len
= d
->Length
;
69 if((maxToPrint
!= 0) && (len
> maxToPrint
)) {
73 for(i
=0; i
<len
; i
++) {
74 printf("%02X ", ((unsigned char *)cp
)[i
]);
85 * Identify CSSM_BER_TAG with a C string.
87 static char *tagTypeString(
90 static char unknownType
[80];
94 return "BER_TAG_UNKNOWN";
96 return "BER_TAG_BOOLEAN";
98 return "BER_TAG_INTEGER";
99 case BER_TAG_BIT_STRING
:
100 return "BER_TAG_BIT_STRING";
101 case BER_TAG_OCTET_STRING
:
102 return "BER_TAG_OCTET_STRING";
104 return "BER_TAG_NULL";
106 return "BER_TAG_OID";
107 case BER_TAG_SEQUENCE
:
108 return "BER_TAG_SEQUENCE";
110 return "BER_TAG_SET";
111 case BER_TAG_PRINTABLE_STRING
:
112 return "BER_TAG_PRINTABLE_STRING";
113 case BER_TAG_T61_STRING
:
114 return "BER_TAG_T61_STRING";
115 case BER_TAG_IA5_STRING
:
116 return "BER_TAG_IA5_STRING";
117 case BER_TAG_UTC_TIME
:
118 return "BER_TAG_UTC_TIME";
119 case BER_TAG_GENERALIZED_TIME
:
120 return "BER_TAG_GENERALIZED_TIME";
122 sprintf(unknownType
, "Other type (0x%x)", tagType
);
128 * Print an OID, assumed to be in BER encoded "Intel" format
129 * Length is inferred from oid->Length
132 static void printOid(OidParser
&parser
, const CSSM_DATA
*oid
)
134 char strBuf
[OID_PARSER_STRING_SIZE
];
140 if((oid
->Length
== 0) || (oid
->Data
== NULL
)) {
144 parser
.oidParse(oid
->Data
, oid
->Length
, strBuf
);
145 printf("%s\n", strBuf
);
149 * Used to print generic blobs which we don't really understand.
150 * The bytesToPrint argument is usually thing->Length; it's here because snacc
151 * peports lengths of bit strings in BITS. Caller knows this and
152 * modifies bytesToPrint accordingly. In any case, bytesToPrint is the
153 * max number of valid bytes in *thing->Data.
155 #define BLOB_LENGTH_PRINT 3
157 static void printBlobBytes(
159 char *quanta
, // e.g., "bytes', "bits"
161 const CSSM_DATA
*thing
)
164 uint32 toPrint
= bytesToPrint
;
166 if(toPrint
> BLOB_LENGTH_PRINT
) {
167 toPrint
= BLOB_LENGTH_PRINT
;
169 printf("%s; Length %u %s; data = ",
170 blobType
, (unsigned)thing
->Length
, quanta
);
171 for(dex
=0; dex
<toPrint
; dex
++) {
172 printf("0x%x ", thing
->Data
[dex
]);
173 if(dex
== (toPrint
- 1)) {
177 if(dex
< bytesToPrint
) {
186 * Print an IA5String or Printable string. Null terminator is not assumed.
187 * Trailing newline is printed.
189 static void printString(
190 const CSSM_DATA
*str
)
193 char *cp
= (char *)str
->Data
;
194 for(i
=0; i
<str
->Length
; i
++) {
200 static void printDerThing(
201 CSSM_BER_TAG tagType
,
202 const CSSM_DATA
*thing
,
206 case BER_TAG_INTEGER
:
207 printf("%u\n", (unsigned)DER_ToInt(thing
));
209 case BER_TAG_BOOLEAN
:
210 if(thing
->Length
!= 1) {
211 printf("***malformed BER_TAG_BOOLEAN: length %d data ",
212 (unsigned)thing
->Length
);
214 printf("%u\n", (unsigned)DER_ToInt(thing
));
216 case BER_TAG_PRINTABLE_STRING
:
217 case BER_TAG_IA5_STRING
:
218 case BER_TAG_T61_STRING
: // mostly printable....
221 case BER_TAG_OCTET_STRING
:
222 printBlobBytes("Byte string", "bytes", thing
->Length
, thing
);
224 case BER_TAG_BIT_STRING
:
225 printBlobBytes("Bit string", "bits", (thing
->Length
+ 7) / 8, thing
);
227 case BER_TAG_SEQUENCE
:
228 printBlobBytes("Sequence", "bytes", thing
->Length
, thing
);
231 printBlobBytes("Set", "bytes", thing
->Length
, thing
);
235 printOid(parser
, thing
);
238 printf("not displayed (tagType = %s; length %u)\n",
239 tagTypeString(tagType
), (unsigned)thing
->Length
);
245 static void printSigAlg(
246 CSSM_X509_ALGORITHM_IDENTIFIER
*sigAlg
,
249 printOid(parser
, &sigAlg
->algorithm
);
250 if(sigAlg
->parameters
.Data
!= NULL
) {
251 printf(" alg params : ");
252 printDataAsHex(&sigAlg
->parameters
, 8);
256 /* compare two OIDs, return CSSM_TRUE if identical */
257 static CSSM_BOOL
compareOids(
258 const CSSM_OID
*oid1
,
259 const CSSM_OID
*oid2
)
261 if((oid1
== NULL
) || (oid2
== NULL
)) {
264 if(oid1
->Length
!= oid2
->Length
) {
267 if(memcmp(oid1
->Data
, oid2
->Data
, oid1
->Length
)) {
275 static CSSM_RETURN
printName(
276 const CSSM_X509_NAME_PTR x509Name
,
279 CSSM_X509_TYPE_VALUE_PAIR
*ptvp
;
280 CSSM_X509_RDN_PTR rdnp
;
285 for(rdnDex
=0; rdnDex
<x509Name
->numberOfRDNs
; rdnDex
++) {
286 rdnp
= &x509Name
->RelativeDistinguishedName
[rdnDex
];
287 for(pairDex
=0; pairDex
<rdnp
->numberOfPairs
; pairDex
++) {
288 ptvp
= &rdnp
->AttributeTypeAndValue
[pairDex
];
289 if(compareOids(&ptvp
->type
, &CSSMOID_CountryName
)) {
290 fieldName
= "Country ";
292 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationName
)) {
295 else if(compareOids(&ptvp
->type
, &CSSMOID_LocalityName
)) {
296 fieldName
= "Locality ";
298 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationalUnitName
)) {
299 fieldName
= "OrgUnit ";
301 else if(compareOids(&ptvp
->type
, &CSSMOID_CommonName
)) {
302 fieldName
= "Common Name ";
304 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
305 fieldName
= "Surname ";
307 else if(compareOids(&ptvp
->type
, &CSSMOID_Title
)) {
308 fieldName
= "Title ";
310 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
311 fieldName
= "Surname ";
313 else if(compareOids(&ptvp
->type
, &CSSMOID_StateProvinceName
)) {
314 fieldName
= "State ";
316 else if(compareOids(&ptvp
->type
, &CSSMOID_CollectiveStateProvinceName
)) {
317 fieldName
= "Coll. State ";
319 else if(compareOids(&ptvp
->type
, &CSSMOID_EmailAddress
)) {
320 /* deprecated, used by Thawte */
321 fieldName
= "Email addrs ";
324 fieldName
= "Other name ";
326 printf(" %s : ", fieldName
);
327 printDerThing(ptvp
->valueType
, &ptvp
->value
, parser
);
328 } /* for each type/value pair */
334 static void printKeyHeader(
335 const CSSM_KEYHEADER
&hdr
)
337 printf(" Algorithm : ");
338 switch(hdr
.AlgorithmId
) {
349 printf("Unknown(%d(d), 0x%x)\n", (unsigned)hdr
.AlgorithmId
,
350 (unsigned)hdr
.AlgorithmId
);
352 printf(" Key Size : %u bits\n", (unsigned)hdr
.LogicalKeySizeInBits
);
353 printf(" Key Use : ");
354 CSSM_KEYUSE usage
= hdr
.KeyUsage
;
355 if(usage
& CSSM_KEYUSE_ANY
) {
356 printf("CSSM_KEYUSE_ANY ");
358 if(usage
& CSSM_KEYUSE_ENCRYPT
) {
359 printf("CSSM_KEYUSE_ENCRYPT ");
361 if(usage
& CSSM_KEYUSE_DECRYPT
) {
362 printf("CSSM_KEYUSE_DECRYPT ");
364 if(usage
& CSSM_KEYUSE_SIGN
) {
365 printf("CSSM_KEYUSE_SIGN ");
367 if(usage
& CSSM_KEYUSE_VERIFY
) {
368 printf("CSSM_KEYUSE_VERIFY ");
370 if(usage
& CSSM_KEYUSE_SIGN_RECOVER
) {
371 printf("CSSM_KEYUSE_SIGN_RECOVER ");
373 if(usage
& CSSM_KEYUSE_VERIFY_RECOVER
) {
374 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
376 if(usage
& CSSM_KEYUSE_WRAP
) {
377 printf("CSSM_KEYUSE_WRAP ");
379 if(usage
& CSSM_KEYUSE_UNWRAP
) {
380 printf("CSSM_KEYUSE_UNWRAP ");
382 if(usage
& CSSM_KEYUSE_DERIVE
) {
383 printf("CSSM_KEYUSE_DERIVE ");
390 * Print contents of a CE_GeneralNames as best we can.
392 static void printGeneralNames(
393 CE_GeneralNames
*generalNames
,
397 CE_GeneralName
*name
;
399 for(i
=0; i
<generalNames
->numNames
; i
++) {
400 name
= &generalNames
->generalName
[i
];
401 switch(name
->nameType
) {
403 printf(" RFC822Name : ");
404 printString(&name
->name
);
407 printf(" DNSName : ");
408 printString(&name
->name
);
412 printString(&name
->name
);
415 printf(" IP Address : ");
416 for(unsigned i
=0; i
<name
->name
.Length
; i
++) {
417 printf("%d", name
->name
.Data
[i
]);
418 if(i
< (name
->name
.Length
- 1)) {
424 case GNT_RegisteredID
:
425 printf(" RegisteredID : ");
426 printOid(parser
, &name
->name
);
428 case GNT_X400Address
:
429 /* ORAddress, a very complicated struct - punt */
430 printf(" X400Address : ");
431 printBlobBytes("Sequence", "bytes", name
->name
.Length
, &name
->name
);
433 case GNT_DirectoryName
:
434 /* encoded Name (i.e. CSSM_X509_NAME) */
435 printf(" Dir Name : ");
436 printBlobBytes("Byte string", "bytes", name
->name
.Length
, &name
->name
);
438 case GNT_EdiPartyName
:
439 /* sequence EDIPartyName */
440 printf(" EdiPartyName : ");
441 printBlobBytes("Sequence", "bytes", name
->name
.Length
, &name
->name
);
444 printf(" OtherName : ");
445 printOid(parser
, &name
->name
);
451 static int printExtensionCommon(
452 const CSSM_DATA
&value
,
454 bool expectParsed
= true)
456 if(value
.Length
!= sizeof(CSSM_X509_EXTENSION
)) {
457 printf("***malformed CSSM_FIELD (1)\n");
460 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
461 printf("Extension struct : "); printOid(parser
, &cssmExt
->extnId
);
462 printf(" Critical : %s\n", cssmExt
->critical
? "TRUE" : "FALSE");
463 switch(cssmExt
->format
) {
464 case CSSM_X509_DATAFORMAT_ENCODED
:
466 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n");
469 if((cssmExt
->BERvalue
.Data
== NULL
) ||
470 (cssmExt
->value
.parsedValue
!= NULL
)) {
471 printf("***Malformed CSSM_X509_EXTENSION (1)\n");
475 case CSSM_X509_DATAFORMAT_PARSED
:
477 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
480 if((cssmExt
->BERvalue
.Data
!= NULL
) ||
481 (cssmExt
->value
.parsedValue
== NULL
)) {
482 printf("***Malformed CSSM_X509_EXTENSION (2)\n");
487 printf("***Unknown CSSM_X509_EXTENSION.format\n");
493 static void printKeyUsage(
494 const CSSM_DATA
&value
)
497 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
499 usage
= *((CE_KeyUsage
*)cssmExt
->value
.parsedValue
);
501 if(usage
& CE_KU_DigitalSignature
) {
502 printf("DigitalSignature ");
504 if(usage
& CE_KU_NonRepudiation
) {
505 printf("NonRepudiation ");
507 if(usage
& CE_KU_KeyEncipherment
) {
508 printf("KeyEncipherment ");
510 if(usage
& CE_KU_DataEncipherment
) {
511 printf("DataEncipherment ");
513 if(usage
& CE_KU_KeyAgreement
) {
514 printf("KeyAgreement ");
516 if(usage
& CE_KU_KeyCertSign
) {
517 printf("KeyCertSign ");
519 if(usage
& CE_KU_CRLSign
) {
522 if(usage
& CE_KU_EncipherOnly
) {
523 printf("EncipherOnly ");
525 if(usage
& CE_KU_DecipherOnly
) {
526 printf("DecipherOnly ");
532 static void printBasicConstraints(
533 const CSSM_DATA
&value
)
535 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
536 CE_BasicConstraints
*bc
= (CE_BasicConstraints
*)cssmExt
->value
.parsedValue
;
537 printf(" CA : %s\n", bc
->cA
? "TRUE" : "FALSE");
538 if(bc
->pathLenConstraintPresent
) {
539 printf(" pathLenConstr : %u\n",
540 (unsigned)bc
->pathLenConstraint
);
544 static void printExtKeyUsage(
545 const CSSM_DATA
&value
,
548 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
549 CE_ExtendedKeyUsage
*eku
= (CE_ExtendedKeyUsage
*)cssmExt
->value
.parsedValue
;
551 for(oidDex
=0; oidDex
<eku
->numPurposes
; oidDex
++) {
552 printf(" purpose %2d : ", oidDex
);
553 printOid(parser
, &eku
->purposes
[oidDex
]);
557 static void printAuthorityKeyId(
558 const CSSM_DATA
&value
,
561 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
562 CE_AuthorityKeyID
*akid
= (CE_AuthorityKeyID
*)cssmExt
->value
.parsedValue
;
563 if(akid
->keyIdentifierPresent
) {
564 printf(" keyIdentifier : "); printDataAsHex(&akid
->keyIdentifier
, 8);
566 if(akid
->generalNamesPresent
) {
567 printGeneralNames(akid
->generalNames
, parser
);
569 if(akid
->serialNumberPresent
) {
570 printf(" serialNumber : "); printDataAsHex(&akid
->serialNumber
, 8);
574 static void printSubjectAltName(
575 const CSSM_DATA
&value
,
578 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
579 CE_GeneralNames
*san
= (CE_GeneralNames
*)cssmExt
->value
.parsedValue
;
580 printGeneralNames(san
, parser
);
583 static void printCertPolicies(
584 const CSSM_DATA
&value
,
587 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
588 CE_CertPolicies
*cdsaObj
= (CE_CertPolicies
*)cssmExt
->value
.parsedValue
;
589 for(unsigned polDex
=0; polDex
<cdsaObj
->numPolicies
; polDex
++) {
590 CE_PolicyInformation
*cPolInfo
= &cdsaObj
->policies
[polDex
];
591 printf(" Policy %2d : ID ", polDex
);
592 printOid(parser
, &cPolInfo
->certPolicyId
);
593 for(unsigned qualDex
=0; qualDex
<cPolInfo
->numPolicyQualifiers
; qualDex
++) {
594 CE_PolicyQualifierInfo
*cQualInfo
= &cPolInfo
->policyQualifiers
[qualDex
];
595 printf(" Qual %2d : ID ", qualDex
);
596 printOid(parser
, &cQualInfo
->policyQualifierId
);
597 if(cuCompareCssmData(&cQualInfo
->policyQualifierId
,
600 printString(&cQualInfo
->qualifier
);
603 printf(" unparsed : ");
604 printDataAsHex(&cQualInfo
->qualifier
, 8);
610 static void printNetscapeCertType(
611 const CSSM_DATA
&value
)
613 CE_NetscapeCertType certType
;
614 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
616 certType
= *((CE_NetscapeCertType
*)cssmExt
->value
.parsedValue
);
617 printf(" certType : ");
618 if(certType
& CE_NCT_SSL_Client
) {
619 printf("SSL_Client ");
621 if(certType
& CE_NCT_SSL_Server
) {
622 printf("SSL_Server ");
624 if(certType
& CE_NCT_SMIME
) {
627 if(certType
& CE_NCT_ObjSign
) {
628 printf("ObjectSign ");
630 if(certType
& CE_NCT_Reserved
) {
633 if(certType
& CE_NCT_SSL_CA
) {
636 if(certType
& CE_NCT_SMIME_CA
) {
639 if(certType
& CE_NCT_ObjSignCA
) {
640 printf("ObjSignCA ");
645 /* print one field */
647 const CSSM_FIELD
&field
,
651 const CSSM_DATA
*thisData
= &field
.FieldValue
;
652 const CSSM_OID
*thisOid
= &field
.FieldOid
;
654 if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Version
)) {
656 printf("Version : %u\n",
657 (unsigned)DER_ToInt(thisData
));
660 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SerialNumber
)) {
661 printf("Serial Number : "); printDataAsHex(thisData
, 0);
663 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerNameCStruct
)) {
664 printf("Issuer Name :\n");
665 CSSM_X509_NAME_PTR name
= (CSSM_X509_NAME_PTR
)thisData
->Data
;
666 if((name
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_NAME
))) {
667 printf(" ***malformed CSSM_X509_NAME\n");
670 printName(name
, parser
);
673 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectNameCStruct
)) {
674 printf("Subject Name :\n");
675 CSSM_X509_NAME_PTR name
= (CSSM_X509_NAME_PTR
)thisData
->Data
;
676 if((name
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_NAME
))) {
677 printf(" ***malformed CSSM_X509_NAME\n");
680 printName(name
, parser
);
683 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1ValidityNotBefore
)) {
684 CSSM_X509_TIME
*cssmTime
= (CSSM_X509_TIME
*)thisData
->Data
;
685 if((cssmTime
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_TIME
))) {
686 printf(" ***malformed CSSM_X509_TIME\n");
689 printf("Not Before : "); printString(&cssmTime
->time
);
694 printf("Not Before : ");
698 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1ValidityNotAfter
)) {
699 CSSM_X509_TIME
*cssmTime
= (CSSM_X509_TIME
*)thisData
->Data
;
700 if((cssmTime
== NULL
) || (thisData
->Length
!= sizeof(CSSM_X509_TIME
))) {
701 printf(" ***malformed CSSM_X509_TIME\n");
704 printf("Not After : "); printString(&cssmTime
->time
);
709 printf("Not After : ");
713 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SignatureAlgorithmTBS
)) {
715 /* normally skip, it's the same as TBS sig alg */
716 printf("TBS Sig Algorithm : ");
717 CSSM_X509_ALGORITHM_IDENTIFIER
*algId
=
718 (CSSM_X509_ALGORITHM_IDENTIFIER
*)thisData
->Data
;
719 if((algId
== NULL
) ||
720 (thisData
->Length
!= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
))) {
721 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n");
724 printSigAlg(algId
, parser
);
728 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SignatureAlgorithm
)) {
729 printf("Cert Sig Algorithm : ");
730 CSSM_X509_ALGORITHM_IDENTIFIER
*algId
=
731 (CSSM_X509_ALGORITHM_IDENTIFIER
*)thisData
->Data
;
732 if((algId
== NULL
) ||
733 (thisData
->Length
!= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
))) {
734 printf(" ***malformed CSSM_X509_ALGORITHM_IDENTIFIER\n");
737 printSigAlg(algId
, parser
);
740 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateIssuerUniqueId
)) {
742 printf("Issuer UniqueId : ");
743 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
746 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateSubjectUniqueId
)) {
748 printf("Subject UniqueId : ");
749 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
752 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectPublicKeyCStruct
)) {
753 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*pubKeyInfo
=
754 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
*)thisData
->Data
;
755 printf("Pub Key Algorithm : ");
756 if((pubKeyInfo
== NULL
) ||
757 (thisData
->Length
!= sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
))) {
758 printf(" ***malformed CSSM_X509_SUBJECT_PUBLIC_KEY_INFO\n");
761 printSigAlg(&pubKeyInfo
->algorithm
, parser
);
762 printf("Pub key Bytes : Length %u bytes : ",
763 (unsigned)pubKeyInfo
->subjectPublicKey
.Length
);
764 printDataAsHex(&pubKeyInfo
->subjectPublicKey
, 8);
767 else if(cuCompareCssmData(thisOid
, &CSSMOID_CSSMKeyStruct
)) {
768 CSSM_KEY_PTR cssmKey
= (CSSM_KEY_PTR
)thisData
->Data
;
769 printf("CSSM Key :\n");
770 if((cssmKey
== NULL
) ||
771 (thisData
->Length
!= sizeof(CSSM_KEY
))) {
772 printf(" ***malformed CSSM_KEY\n");
775 printKeyHeader(cssmKey
->KeyHeader
);
778 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Signature
)) {
779 printf("Signature : %u bytes : ",
780 (unsigned)thisData
->Length
);
781 printDataAsHex(thisData
, 8);
783 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V3CertificateExtensionCStruct
)) {
784 if(printExtensionCommon(*thisData
, parser
, false)) {
787 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)thisData
->Data
;
788 printf(" Unparsed data : "); printDataAsHex(&cssmExt
->BERvalue
, 8);
790 else if(cuCompareCssmData(thisOid
, &CSSMOID_KeyUsage
)) {
791 if(printExtensionCommon(*thisData
, parser
)) {
794 printKeyUsage(*thisData
);
796 else if(cuCompareCssmData(thisOid
, &CSSMOID_BasicConstraints
)) {
797 if(printExtensionCommon(*thisData
, parser
)) {
800 printBasicConstraints(*thisData
);
802 else if(cuCompareCssmData(thisOid
, &CSSMOID_ExtendedKeyUsage
)) {
803 if(printExtensionCommon(*thisData
, parser
)) {
806 printExtKeyUsage(*thisData
, parser
);
808 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectKeyIdentifier
)) {
809 if(printExtensionCommon(*thisData
, parser
)) {
812 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)thisData
->Data
;
813 CSSM_DATA_PTR cdata
= (CSSM_DATA_PTR
)cssmExt
->value
.parsedValue
;
814 if((cdata
== NULL
) || (cdata
->Data
== NULL
)) {
815 printf("****Malformed extension (no parsedValue)\n");
818 printf(" Subject KeyID : "); printDataAsHex(cdata
, 8);
821 else if(cuCompareCssmData(thisOid
, &CSSMOID_AuthorityKeyIdentifier
)) {
822 if(printExtensionCommon(*thisData
, parser
)) {
825 printAuthorityKeyId(*thisData
, parser
);
827 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectAltName
)) {
828 if(printExtensionCommon(*thisData
, parser
)) {
831 printSubjectAltName(*thisData
, parser
);
833 else if(cuCompareCssmData(thisOid
, &CSSMOID_CertificatePolicies
)) {
834 if(printExtensionCommon(*thisData
, parser
)) {
837 printCertPolicies(*thisData
, parser
);
839 else if(cuCompareCssmData(thisOid
, &CSSMOID_NetscapeCertType
)) {
840 if(printExtensionCommon(*thisData
, parser
)) {
843 printNetscapeCertType(*thisData
);
845 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerName
)) {
847 printf("Normalized Issuer : ");
848 printDataAsHex(thisData
, 8);
851 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectName
)) {
853 printf("Normalized Subject : ");
854 printDataAsHex(thisData
, 8);
858 printf("other field: : "); printOid(parser
, thisOid
);
862 /* connect to CSSM/CL lazily, once */
863 static CSSM_CL_HANDLE clHand
= 0;
866 const unsigned char *certData
,
870 CSSM_FIELD_PTR fieldPtr
; // mallocd by CL
877 clHand
= cuClStartup();
879 printf("***Error connecting to CSSM cert module; aborting cert display\n");
883 cert
.Data
= (uint8
*)certData
;
884 cert
.Length
= certLen
;
886 CSSM_RETURN crtn
= CSSM_CL_CertGetAllFields(clHand
,
891 cuPrintError("CSSM_CL_CertGetAllFields", crtn
);
895 for(i
=0; i
<numFields
; i
++) {
896 printCertField(fieldPtr
[i
], parser
, verbose
);
899 crtn
= CSSM_CL_FreeFields(clHand
, numFields
, &fieldPtr
);
901 cuPrintError("CSSM_CL_FreeFields", crtn
);
907 void printCertShutdown()
910 CSSM_ModuleDetach(clHand
);