2 * Copyright (c) 2002,2011-2012,2014 Apple 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/oidsalg.h>
29 #include <Security/cssmapple.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>
38 static const char *months
[] = {
39 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
40 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
43 static void printTimeStr(const CSSM_DATA
*cssmTime
)
47 /* ignore cssmTime->timeType for now */
48 if(cuTimeStringToTm((char *)cssmTime
->Data
, (unsigned int)cssmTime
->Length
, &tm
)) {
49 printf("***Bad time string format***\n");
53 printf("***Bad time string format***\n");
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);
63 static void printTime(const CSSM_X509_TIME
*cssmTime
)
65 /* ignore cssmTime->timeType for now */
66 printTimeStr(&cssmTime
->time
);
69 static void printDataAsHex(
71 unsigned maxToPrint
= 0) // optional, 0 means print it all
75 uint32 len
= (uint32
)d
->Length
;
78 if((maxToPrint
!= 0) && (len
> maxToPrint
)) {
82 for(i
=0; i
<len
; i
++) {
83 printf("%02X ", ((unsigned char *)cp
)[i
]);
94 * Identify CSSM_BER_TAG with a C string.
96 static const char *tagTypeString(
99 static char unknownType
[80];
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";
113 return "BER_TAG_NULL";
115 return "BER_TAG_OID";
116 case BER_TAG_SEQUENCE
:
117 return "BER_TAG_SEQUENCE";
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";
131 sprintf(unknownType
, "Other type (0x%x)", tagType
);
137 * Print an OID, assumed to be in BER encoded "Intel" format
138 * Length is inferred from oid->Length
141 static void printOid(OidParser
&parser
, const CSSM_DATA
*oid
)
143 char strBuf
[OID_PARSER_STRING_SIZE
];
149 if((oid
->Length
== 0) || (oid
->Data
== NULL
)) {
153 parser
.oidParse(oid
->Data
, (unsigned int)oid
->Length
, strBuf
);
154 printf("%s\n", strBuf
);
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.
164 #define BLOB_LENGTH_PRINT 3
166 static void printBlobBytes(
167 const char *blobType
,
168 const char *quanta
, // e.g., "bytes', "bits"
170 const CSSM_DATA
*thing
)
173 uint32 toPrint
= bytesToPrint
;
175 if(toPrint
> BLOB_LENGTH_PRINT
) {
176 toPrint
= BLOB_LENGTH_PRINT
;
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)) {
186 if(dex
< bytesToPrint
) {
195 * Print an IA5String or Printable string. Null terminator is not assumed.
196 * Trailing newline is printed.
198 static void printString(
199 const CSSM_DATA
*str
)
202 char *cp
= (char *)str
->Data
;
203 for(i
=0; i
<str
->Length
; i
++) {
209 static void printDerThing(
210 CSSM_BER_TAG tagType
,
211 const CSSM_DATA
*thing
,
215 case BER_TAG_INTEGER
:
216 printf("%d\n", cuDER_ToInt(thing
));
218 case BER_TAG_BOOLEAN
:
219 if(thing
->Length
!= 1) {
220 printf("***malformed BER_TAG_BOOLEAN: length %u data ",
221 (unsigned)thing
->Length
);
223 printf("%u\n", cuDER_ToInt(thing
));
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....
231 case BER_TAG_OCTET_STRING
:
232 printBlobBytes("Byte string", "bytes", (uint32
)thing
->Length
, thing
);
234 case BER_TAG_BIT_STRING
:
235 printBlobBytes("Bit string", "bits", (uint32
)(thing
->Length
+ 7) / 8, thing
);
237 case BER_TAG_SEQUENCE
:
238 printBlobBytes("Sequence", "bytes", (uint32
)thing
->Length
, thing
);
241 printBlobBytes("Set", "bytes", (uint32
)thing
->Length
, thing
);
245 printOid(parser
, thing
);
248 printf("not displayed (tagType = %s; length %u)\n",
249 tagTypeString(tagType
), (unsigned)thing
->Length
);
255 /* compare two OIDs, return CSSM_TRUE if identical */
256 static CSSM_BOOL
compareOids(
257 const CSSM_OID
*oid1
,
258 const CSSM_OID
*oid2
)
260 if((oid1
== NULL
) || (oid2
== NULL
)) {
263 if(oid1
->Length
!= oid2
->Length
) {
266 if(memcmp(oid1
->Data
, oid2
->Data
, oid1
->Length
)) {
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.
279 static void printECDSA_SigAlgParams(
280 const CSSM_DATA
*params
,
283 SecAsn1CoderRef coder
= NULL
;
284 if(SecAsn1CoderCreate(&coder
)) {
285 printf("***Error in SecAsn1CoderCreate()\n");
288 CSSM_X509_ALGORITHM_IDENTIFIER algParams
;
289 memset(&algParams
, 0, sizeof(algParams
));
290 if(SecAsn1DecodeData(coder
, params
, kSecAsn1AlgorithmIDTemplate
,
292 printf("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
295 printOid(parser
, &algParams
.algorithm
);
297 SecAsn1CoderRelease(coder
);
300 static void printSigAlg(
301 const CSSM_X509_ALGORITHM_IDENTIFIER
*sigAlg
,
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)) {
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.
315 CSSM_OID curveOid
= {sigAlg
->parameters
.Length
-2, sigAlg
->parameters
.Data
+2};
316 printOid(parser
, &curveOid
);
318 else if(compareOids(&sigAlg
->algorithm
, &CSSMOID_ECDSA_WithSpecified
)) {
320 * The accompanying params specify the digest algorithm.
322 printECDSA_SigAlgParams(&sigAlg
->parameters
, parser
);
325 /* All others - ASN_ANY - punt */
326 printDataAsHex(&sigAlg
->parameters
, 8);
331 static void printRdn(
332 const CSSM_X509_RDN
*rdnp
,
335 CSSM_X509_TYPE_VALUE_PAIR
*ptvp
;
337 const char *fieldName
;
339 for(pairDex
=0; pairDex
<rdnp
->numberOfPairs
; pairDex
++) {
340 ptvp
= &rdnp
->AttributeTypeAndValue
[pairDex
];
341 if(compareOids(&ptvp
->type
, &CSSMOID_CountryName
)) {
342 fieldName
= "Country ";
344 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationName
)) {
347 else if(compareOids(&ptvp
->type
, &CSSMOID_LocalityName
)) {
348 fieldName
= "Locality ";
350 else if(compareOids(&ptvp
->type
, &CSSMOID_OrganizationalUnitName
)) {
351 fieldName
= "OrgUnit ";
353 else if(compareOids(&ptvp
->type
, &CSSMOID_CommonName
)) {
354 fieldName
= "Common Name ";
356 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
357 fieldName
= "Surname ";
359 else if(compareOids(&ptvp
->type
, &CSSMOID_Title
)) {
360 fieldName
= "Title ";
362 else if(compareOids(&ptvp
->type
, &CSSMOID_Surname
)) {
363 fieldName
= "Surname ";
365 else if(compareOids(&ptvp
->type
, &CSSMOID_StateProvinceName
)) {
366 fieldName
= "State ";
368 else if(compareOids(&ptvp
->type
, &CSSMOID_CollectiveStateProvinceName
)) {
369 fieldName
= "Coll. State ";
371 else if(compareOids(&ptvp
->type
, &CSSMOID_EmailAddress
)) {
372 /* deprecated, used by Thawte */
373 fieldName
= "Email addrs ";
375 else if(compareOids(&ptvp
->type
, &CSSMOID_Description
)) {
376 fieldName
= "Description ";
379 fieldName
= "Other name ";
381 printf(" %s : ", fieldName
);
382 printDerThing(ptvp
->valueType
, &ptvp
->value
, parser
);
383 } /* for each type/value pair */
386 static CSSM_RETURN
printName(
387 const CSSM_X509_NAME
*x509Name
,
390 CSSM_X509_RDN_PTR rdnp
;
393 for(rdnDex
=0; rdnDex
<x509Name
->numberOfRDNs
; rdnDex
++) {
394 rdnp
= &x509Name
->RelativeDistinguishedName
[rdnDex
];
395 printRdn(rdnp
, parser
);
401 static void printKeyHeader(
402 const CSSM_KEYHEADER
&hdr
)
404 printf(" Algorithm : ");
405 switch(hdr
.AlgorithmId
) {
416 printf("Diffie-Hellman\n");
418 case CSSM_ALGID_ECDSA
:
422 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr
.AlgorithmId
,
423 (unsigned)hdr
.AlgorithmId
);
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 ");
431 if(usage
& CSSM_KEYUSE_ENCRYPT
) {
432 printf("CSSM_KEYUSE_ENCRYPT ");
434 if(usage
& CSSM_KEYUSE_DECRYPT
) {
435 printf("CSSM_KEYUSE_DECRYPT ");
437 if(usage
& CSSM_KEYUSE_SIGN
) {
438 printf("CSSM_KEYUSE_SIGN ");
440 if(usage
& CSSM_KEYUSE_VERIFY
) {
441 printf("CSSM_KEYUSE_VERIFY ");
443 if(usage
& CSSM_KEYUSE_SIGN_RECOVER
) {
444 printf("CSSM_KEYUSE_SIGN_RECOVER ");
446 if(usage
& CSSM_KEYUSE_VERIFY_RECOVER
) {
447 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
449 if(usage
& CSSM_KEYUSE_WRAP
) {
450 printf("CSSM_KEYUSE_WRAP ");
452 if(usage
& CSSM_KEYUSE_UNWRAP
) {
453 printf("CSSM_KEYUSE_UNWRAP ");
455 if(usage
& CSSM_KEYUSE_DERIVE
) {
456 printf("CSSM_KEYUSE_DERIVE ");
463 * Print contents of a CE_GeneralName as best we can.
465 static void printGeneralName(
466 const CE_GeneralName
*name
,
469 switch(name
->nameType
) {
471 printf(" RFC822Name : ");
472 printString(&name
->name
);
475 printf(" DNSName : ");
476 printString(&name
->name
);
480 printString(&name
->name
);
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)) {
492 case GNT_RegisteredID
:
493 printf(" RegisteredID : ");
494 printOid(parser
, &name
->name
);
496 case GNT_X400Address
:
497 /* ORAddress, a very complicated struct - punt */
498 printf(" X400Address : ");
499 printBlobBytes("Sequence", "bytes", (uint32
)name
->name
.Length
, &name
->name
);
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");
508 const CSSM_X509_NAME
*x509Name
=
509 (const CSSM_X509_NAME
*)name
->name
.Data
;
510 printf(" Dir Name :\n");
511 printName(x509Name
, parser
);
514 /* encoded Name (i.e. CSSM_X509_NAME) */
515 printf(" Dir Name : ");
516 printBlobBytes("Byte string", "bytes",
517 (uint32
)name
->name
.Length
, &name
->name
);
520 case GNT_EdiPartyName
:
521 /* sequence EDIPartyName */
522 printf(" EdiPartyName : ");
523 printBlobBytes("Sequence", "bytes", (uint32
)name
->name
.Length
, &name
->name
);
527 printf(" OtherName :\n");
528 if(name
->name
.Length
!= sizeof(CE_OtherName
)) {
529 printf("***Malformed CE_OtherName\n");
532 CE_OtherName
*other
= (CE_OtherName
*)name
->name
.Data
;
533 printf(" typeID : ");
534 printOid(parser
, &other
->typeId
);
536 printDataAsHex(&other
->value
, 0);
544 * Print contents of a CE_GeneralNames as best we can.
546 static void printGeneralNames(
547 const CE_GeneralNames
*generalNames
,
551 CE_GeneralName
*name
;
553 for(i
=0; i
<generalNames
->numNames
; i
++) {
554 name
= &generalNames
->generalName
[i
];
555 printGeneralName(name
, parser
);
559 static int printCdsaExtensionCommon(
560 const CSSM_X509_EXTENSION
*cssmExt
,
564 bool extraIndent
= false)
567 printf(" Extension : "); printOid(parser
, &cssmExt
->extnId
);
568 printf(" Critical : %s\n", cssmExt
->critical
? "TRUE" : "FALSE");
571 printf("Extension struct : "); printOid(parser
, &cssmExt
->extnId
);
572 printf(" Critical : %s\n", cssmExt
->critical
? "TRUE" : "FALSE");
575 /* currently (since Radar 3593624), these are both always valid */
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");
584 switch(cssmExt
->format
) {
585 case CSSM_X509_DATAFORMAT_ENCODED
:
587 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n");
591 case CSSM_X509_DATAFORMAT_PARSED
:
593 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
597 case CSSM_X509_DATAFORMAT_PAIR
:
599 printf("Bad CSSM_X509_EXTENSION format:FORMAT_PAIR\n");
602 printf("***Unknown CSSM_X509_EXTENSION.format\n");
608 static int printExtensionCommon(
609 const CSSM_DATA
&value
,
612 bool expectParsed
= true)
614 if(value
.Length
!= sizeof(CSSM_X509_EXTENSION
)) {
615 printf("***malformed CSSM_FIELD (1)\n");
618 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
619 return printCdsaExtensionCommon(cssmExt
, parser
, expectParsed
, verbose
);
623 static void printKeyUsage(
624 const CSSM_DATA
&value
)
627 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
629 usage
= *((CE_KeyUsage
*)cssmExt
->value
.parsedValue
);
631 if(usage
& CE_KU_DigitalSignature
) {
632 printf("DigitalSignature ");
634 if(usage
& CE_KU_NonRepudiation
) {
635 printf("NonRepudiation ");
637 if(usage
& CE_KU_KeyEncipherment
) {
638 printf("KeyEncipherment ");
640 if(usage
& CE_KU_DataEncipherment
) {
641 printf("DataEncipherment ");
643 if(usage
& CE_KU_KeyAgreement
) {
644 printf("KeyAgreement ");
646 if(usage
& CE_KU_KeyCertSign
) {
647 printf("KeyCertSign ");
649 if(usage
& CE_KU_CRLSign
) {
652 if(usage
& CE_KU_EncipherOnly
) {
653 printf("EncipherOnly ");
655 if(usage
& CE_KU_DecipherOnly
) {
656 printf("DecipherOnly ");
662 static void printBasicConstraints(
663 const CSSM_DATA
&value
)
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
);
673 static void printExtKeyUsage(
674 const CSSM_DATA
&value
,
677 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
678 CE_ExtendedKeyUsage
*eku
= (CE_ExtendedKeyUsage
*)cssmExt
->value
.parsedValue
;
680 for(oidDex
=0; oidDex
<eku
->numPurposes
; oidDex
++) {
681 printf(" purpose %2d : ", oidDex
);
682 printOid(parser
, &eku
->purposes
[oidDex
]);
686 static void printCssmAuthorityKeyId(
687 const CE_AuthorityKeyID
*akid
,
690 if(akid
->keyIdentifierPresent
) {
691 printf(" Auth KeyID : ");
692 printDataAsHex(&akid
->keyIdentifier
,
695 if(akid
->generalNamesPresent
) {
696 printGeneralNames(akid
->generalNames
, parser
);
698 if(akid
->serialNumberPresent
) {
699 printf(" serialNumber : ");
700 printDataAsHex(&akid
->serialNumber
, 8);
704 static void printAuthorityKeyId(
705 const CSSM_DATA
&value
,
708 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
709 CE_AuthorityKeyID
*akid
= (CE_AuthorityKeyID
*)cssmExt
->value
.parsedValue
;
710 printCssmAuthorityKeyId(akid
, parser
);
713 static void printSubjectIssuerAltName(
714 const CSSM_DATA
&value
,
717 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
718 CE_GeneralNames
*san
= (CE_GeneralNames
*)cssmExt
->value
.parsedValue
;
719 printGeneralNames(san
, parser
);
722 static void printDistPointName(
723 const CE_DistributionPointName
*dpn
,
726 switch(dpn
->nameType
) {
727 case CE_CDNT_FullName
:
728 printGeneralNames(dpn
->dpn
.fullName
, parser
);
730 case CE_CDNT_NameRelativeToCrlIssuer
:
731 printRdn(dpn
->dpn
.rdn
, parser
);
734 printf("***BOGUS CE_DistributionPointName.nameType\n");
739 static void printDistPoint(
740 const CE_CRLDistributionPoint
*dp
,
743 if(dp
->distPointName
) {
744 printf(" Dist pt Name :\n");
745 printDistPointName(dp
->distPointName
, parser
);
747 printf(" reasonsPresent : %s\n", dp
->reasonsPresent
? "TRUE" : "FALSE");
748 if(dp
->reasonsPresent
) {
750 printf(" reasons : 0x%X\n", dp
->reasons
);
753 printf(" CRLIssuer :\n");
754 printGeneralNames(dp
->crlIssuer
, parser
);
758 static void printDistributionPoints(
759 const CSSM_DATA
&value
,
762 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
763 CE_CRLDistPointsSyntax
*dps
= (CE_CRLDistPointsSyntax
*)cssmExt
->value
.parsedValue
;
765 for(unsigned dex
=0; dex
<dps
->numDistPoints
; dex
++) {
766 printf(" Dist pt %d :\n", dex
);
767 printDistPoint(&dps
->distPoints
[dex
], parser
);
771 static void printValueOrNotPresent(
776 printf("<Not Present>\n");
786 static void printIssuingDistributionPoint(
787 const CE_IssuingDistributionPoint
*idp
,
790 if(idp
->distPointName
) {
791 printf(" Dist pt :\n");
792 printDistPointName(idp
->distPointName
, parser
);
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
);
804 static void printCertPolicies(
805 const CSSM_DATA
&value
,
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
,
821 printString(&cQualInfo
->qualifier
);
824 printf(" unparsed : ");
825 printDataAsHex(&cQualInfo
->qualifier
, 8);
831 static void printNetscapeCertType(
832 const CSSM_DATA
&value
)
834 CE_NetscapeCertType certType
;
835 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
837 certType
= *((CE_NetscapeCertType
*)cssmExt
->value
.parsedValue
);
838 printf(" certType : ");
839 if(certType
& CE_NCT_SSL_Client
) {
840 printf("SSL_Client ");
842 if(certType
& CE_NCT_SSL_Server
) {
843 printf("SSL_Server ");
845 if(certType
& CE_NCT_SMIME
) {
848 if(certType
& CE_NCT_ObjSign
) {
849 printf("ObjectSign ");
851 if(certType
& CE_NCT_Reserved
) {
854 if(certType
& CE_NCT_SSL_CA
) {
857 if(certType
& CE_NCT_SMIME_CA
) {
860 if(certType
& CE_NCT_ObjSignCA
) {
861 printf("ObjSignCA ");
866 static void printAuthorityInfoAccess(
867 const CSSM_DATA
&value
,
870 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
871 CE_AuthorityInfoAccess
*info
= (CE_AuthorityInfoAccess
*)cssmExt
->value
.parsedValue
;
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
);
883 static void printQualCertStatements(
884 const CSSM_DATA
&value
,
887 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)value
.Data
;
888 CE_QC_Statements
*qcss
= (CE_QC_Statements
*)cssmExt
->value
.parsedValue
;
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
];
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
);
904 if(si
->nameRegistrationAuthorities
) {
905 printf(" nameRegAuth :\n");
906 printGeneralNames(si
->nameRegistrationAuthorities
, parser
);
910 printf(" otherInfo : "); printDataAsHex(qcs
->otherInfo
, 8);
915 /* print one field */
917 const CSSM_FIELD
&field
,
921 const CSSM_DATA
*thisData
= &field
.FieldValue
;
922 const CSSM_OID
*thisOid
= &field
.FieldOid
;
924 if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Version
)) {
926 printf("Version : %u\n", cuDER_ToInt(thisData
));
929 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SerialNumber
)) {
930 printf("Serial Number : "); printDataAsHex(thisData
, 0);
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");
939 printName(name
, parser
);
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");
949 printName(name
, parser
);
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");
958 printf("Not Before : "); printString(&cssmTime
->time
);
963 printf("Not Before : ");
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");
973 printf("Not After : "); printString(&cssmTime
->time
);
978 printf("Not After : ");
982 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SignatureAlgorithmTBS
)) {
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");
993 printSigAlg(algId
, parser
);
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");
1006 printSigAlg(algId
, parser
);
1009 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateIssuerUniqueId
)) {
1011 printf("Issuer UniqueId : ");
1012 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
1015 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1CertificateSubjectUniqueId
)) {
1017 printf("Subject UniqueId : ");
1018 printDerThing(BER_TAG_BIT_STRING
, thisData
, parser
);
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");
1030 printSigAlg(&pubKeyInfo
->algorithm
, parser
);
1031 printf("Pub key Bytes : Length %u bytes : ",
1032 (unsigned)pubKeyInfo
->subjectPublicKey
.Length
);
1033 printDataAsHex(&pubKeyInfo
->subjectPublicKey
, 8);
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");
1044 printKeyHeader(cssmKey
->KeyHeader
);
1046 printf(" Key Blob : ");
1047 printDataAsHex(&cssmKey
->KeyData
, 8);
1051 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1Signature
)) {
1052 printf("Signature : %u bytes : ", (unsigned)thisData
->Length
);
1053 printDataAsHex(thisData
, 8);
1055 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V3CertificateExtensionCStruct
)) {
1056 if(printExtensionCommon(*thisData
, parser
, verbose
, false)) {
1059 CSSM_X509_EXTENSION
*cssmExt
= (CSSM_X509_EXTENSION
*)thisData
->Data
;
1060 printf(" Unparsed data : "); printDataAsHex(&cssmExt
->BERvalue
, 8);
1062 else if(cuCompareCssmData(thisOid
, &CSSMOID_KeyUsage
)) {
1063 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1066 printKeyUsage(*thisData
);
1068 else if(cuCompareCssmData(thisOid
, &CSSMOID_BasicConstraints
)) {
1069 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1072 printBasicConstraints(*thisData
);
1074 else if(cuCompareCssmData(thisOid
, &CSSMOID_ExtendedKeyUsage
)) {
1075 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1078 printExtKeyUsage(*thisData
, parser
);
1080 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectKeyIdentifier
)) {
1081 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
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");
1090 printf(" Subject KeyID : "); printDataAsHex(cdata
, 8);
1093 else if(cuCompareCssmData(thisOid
, &CSSMOID_AuthorityKeyIdentifier
)) {
1094 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1097 printAuthorityKeyId(*thisData
, parser
);
1099 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectAltName
)) {
1100 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1103 printSubjectIssuerAltName(*thisData
, parser
);
1105 else if(cuCompareCssmData(thisOid
, &CSSMOID_IssuerAltName
)) {
1106 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1109 printSubjectIssuerAltName(*thisData
, parser
);
1111 else if(cuCompareCssmData(thisOid
, &CSSMOID_CertificatePolicies
)) {
1112 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1115 printCertPolicies(*thisData
, parser
);
1117 else if(cuCompareCssmData(thisOid
, &CSSMOID_NetscapeCertType
)) {
1118 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1121 printNetscapeCertType(*thisData
);
1123 else if(cuCompareCssmData(thisOid
, &CSSMOID_CrlDistributionPoints
)) {
1124 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1127 printDistributionPoints(*thisData
, parser
);
1129 else if(cuCompareCssmData(thisOid
, &CSSMOID_AuthorityInfoAccess
)) {
1130 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1133 printAuthorityInfoAccess(*thisData
, parser
);
1135 else if(cuCompareCssmData(thisOid
, &CSSMOID_SubjectInfoAccess
)) {
1136 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1139 printAuthorityInfoAccess(*thisData
, parser
);
1141 else if(cuCompareCssmData(thisOid
, &CSSMOID_QC_Statements
)) {
1142 if(printExtensionCommon(*thisData
, parser
, verbose
)) {
1145 printQualCertStatements(*thisData
, parser
);
1147 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerName
)) {
1149 printf("Normalized Issuer : ");
1150 printDataAsHex(thisData
, 8);
1153 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectName
)) {
1155 printf("Normalized Subject : ");
1156 printDataAsHex(thisData
, 8);
1159 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1IssuerNameStd
)) {
1161 printf("DER-encoded issuer : ");
1162 printDataAsHex(thisData
, 8);
1165 else if(cuCompareCssmData(thisOid
, &CSSMOID_X509V1SubjectNameStd
)) {
1167 printf("DER-encoded subject: ");
1168 printDataAsHex(thisData
, 8);
1172 printf("Other field: : "); printOid(parser
, thisOid
);
1178 const CSSM_X509_EXTENSION
*exten
,
1182 const CSSM_OID
*oid
= &exten
->extnId
;
1183 const void *thisData
= exten
->value
.parsedValue
;
1185 if(exten
->format
== CSSM_X509_DATAFORMAT_ENCODED
) {
1186 if(printCdsaExtensionCommon(exten
, parser
, false, verbose
)) {
1189 printf(" Unparsed data : "); printDataAsHex(&exten
->BERvalue
, 8);
1191 else if(exten
->format
!= CSSM_X509_DATAFORMAT_PARSED
) {
1192 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1195 else if(cuCompareCssmData(oid
, &CSSMOID_AuthorityKeyIdentifier
)) {
1196 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1199 printCssmAuthorityKeyId((CE_AuthorityKeyID
*)thisData
, parser
);
1201 else if(cuCompareCssmData(oid
, &CSSMOID_IssuerAltName
)) {
1202 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1205 printGeneralNames((CE_GeneralNames
*)thisData
, parser
);
1207 else if(cuCompareCssmData(oid
, &CSSMOID_CrlNumber
)) {
1208 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1211 printf(" CRL Number : %u\n", *((unsigned *)thisData
));
1213 else if(cuCompareCssmData(oid
, &CSSMOID_DeltaCrlIndicator
)) {
1214 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1217 printf(" Delta CRL Base : %u\n", *((unsigned *)thisData
));
1219 else if(cuCompareCssmData(oid
, &CSSMOID_IssuingDistributionPoint
)) {
1220 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
)) {
1223 printIssuingDistributionPoint((CE_IssuingDistributionPoint
*)thisData
,
1227 /* should never happen - we're out of sync with the CL */
1228 printf("UNKNOWN EXTENSION : "); printOid(parser
, oid
);
1234 void printCrlEntryExten(
1235 const CSSM_X509_EXTENSION
*exten
,
1239 const CSSM_OID
*oid
= &exten
->extnId
;
1240 const void *thisData
= exten
->value
.parsedValue
;
1242 if(exten
->format
== CSSM_X509_DATAFORMAT_ENCODED
) {
1243 if(printCdsaExtensionCommon(exten
, parser
, false, verbose
, true)) {
1246 printf(" Unparsed data: "); printDataAsHex(&exten
->BERvalue
, 8);
1248 else if(exten
->format
!= CSSM_X509_DATAFORMAT_PARSED
) {
1249 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1252 else if(cuCompareCssmData(oid
, &CSSMOID_CrlReason
)) {
1253 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1256 CE_CrlReason
*cr
= (CE_CrlReason
*)thisData
;
1257 const char *reason
= "UNKNOWN";
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;
1278 printf(" CRL Reason : %s\n", reason
);
1280 else if(cuCompareCssmData(oid
, &CSSMOID_HoldInstructionCode
)) {
1281 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1284 printf(" Hold Instr : ");
1285 printOid(parser
, (CSSM_OID_PTR
)thisData
);
1287 else if(cuCompareCssmData(oid
, &CSSMOID_InvalidityDate
)) {
1288 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1291 printf(" Invalid Date : ");
1292 printTimeStr((CSSM_DATA_PTR
)thisData
);
1294 else if(cuCompareCssmData(oid
, &CSSMOID_CertIssuer
)) {
1295 if(printCdsaExtensionCommon(exten
, parser
, true, verbose
, true)) {
1298 printGeneralNames((CE_GeneralNames
*)thisData
, parser
);
1301 /* should never happen - we're out of sync with the CL */
1302 printf("UNKNOWN EXTENSION : "); printOid(parser
, oid
);
1307 void printCrlFields(
1308 const CSSM_X509_SIGNED_CRL
*signedCrl
,
1313 const CSSM_X509_TBS_CERTLIST
*tbsCrl
= &signedCrl
->tbsCertList
;
1315 if(tbsCrl
->version
.Data
) {
1316 printf("Version : %d\n", cuDER_ToInt(&tbsCrl
->version
));
1319 printf("TBS Sig Algorithm : ");
1320 const CSSM_X509_ALGORITHM_IDENTIFIER
*algId
= &tbsCrl
->signature
;
1321 printSigAlg(algId
, parser
);
1323 printf("Issuer Name :\n");
1324 printName(&tbsCrl
->issuer
, parser
);
1326 printf("This Update : ");
1327 printTime(&tbsCrl
->thisUpdate
);
1328 printf("Next Update : ");
1329 if(tbsCrl
->nextUpdate
.time
.Data
) {
1330 printTime(&tbsCrl
->nextUpdate
);
1333 printf("<not present>\n");
1336 CSSM_X509_REVOKED_CERT_LIST_PTR certList
= tbsCrl
->revokedCertificates
;
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) {
1354 printf(" Num Extensions : %u\n", (unsigned)numExtens
);
1355 for(unsigned dex
=0; dex
<numExtens
; dex
++) {
1356 printCrlEntryExten(&cssmExtens
->extensions
[dex
], verbose
,
1362 printf("Num Revoked Certs : %d (use verbose option to see)\n",
1363 (int)certList
->numberOfRevokedCertEntries
);
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
);
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);
1384 /* connect to CSSM/CL lazily, once */
1385 static CSSM_CL_HANDLE clHand
= 0;
1388 const unsigned char *certData
,
1392 CSSM_FIELD_PTR fieldPtr
; // mallocd by CL
1399 clHand
= cuClStartup();
1401 printf("***Error connecting to CSSM cert module; aborting cert "
1406 cert
.Data
= (uint8
*)certData
;
1407 cert
.Length
= certLen
;
1409 CSSM_RETURN crtn
= CSSM_CL_CertGetAllFields(clHand
,
1414 cuPrintError("CSSM_CL_CertGetAllFields", crtn
);
1418 for(i
=0; i
<numFields
; i
++) {
1419 printCertField(fieldPtr
[i
], parser
, verbose
);
1422 crtn
= CSSM_CL_FreeFields(clHand
, numFields
, &fieldPtr
);
1424 cuPrintError("CSSM_CL_FreeFields", crtn
);
1431 /* This one's easier, we just get one field - the whole parsed CRL */
1433 const unsigned char *crlData
,
1437 CSSM_DATA_PTR value
; // mallocd by CL
1444 clHand
= cuClStartup();
1446 printf("***Error connecting to CSSM cert module; aborting CRL"
1451 crl
.Data
= (uint8
*)crlData
;
1452 crl
.Length
= crlLen
;
1454 CSSM_RETURN crtn
= CSSM_CL_CrlGetFirstFieldValue(clHand
,
1456 &CSSMOID_X509V2CRLSignedCrlCStruct
,
1461 cuPrintError("CSSM_CL_CrlGetFirstFieldValue", crtn
);
1464 if(numFields
!= 1) {
1465 printf("***CSSM_CL_CrlGetFirstFieldValue: numFields error\n");
1466 printf(" expected 1, got %d\n", (int)numFields
);
1469 crtn
= CSSM_CL_CrlAbortQuery(clHand
, result
);
1471 cuPrintError("CSSM_CL_CertAbortQuery", crtn
);
1476 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n");
1479 if((value
->Data
== NULL
) ||
1480 (value
->Length
!= sizeof(CSSM_X509_SIGNED_CRL
))) {
1481 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n");
1484 const CSSM_X509_SIGNED_CRL
*signedCrl
=
1485 (const CSSM_X509_SIGNED_CRL
*)value
->Data
;
1486 printCrlFields(signedCrl
, verbose
, parser
);
1488 crtn
= CSSM_CL_FreeFieldValue(clHand
,
1489 &CSSMOID_X509V2CRLSignedCrlCStruct
,
1492 cuPrintError("CSSM_CL_FreeFieldValue", crtn
);
1499 void printCertShutdown()
1502 CSSM_ModuleDetach(clHand
);