]> git.saurik.com Git - apple/security.git/blob - CdsaUtils/cuPrintCert.cpp
Security-176.tar.gz
[apple/security.git] / CdsaUtils / cuPrintCert.cpp
1 /*
2 * Copyright (c) 2002 Apple Computer, 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/cssmapple.h>
29 #include <string.h>
30 #include "cuPrintCert.h"
31 #include "cuOidParser.h"
32 #include "cuTimeStr.h"
33 #include <Security/certextensions.h>
34
35 static char *months[] = {
36 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
37 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
38 };
39
40 static void printTimeStr(const CSSM_DATA *cssmTime)
41 {
42 struct tm tm;
43
44 /* ignore cssmTime->timeType for now */
45 if(cuTimeStringToTm((char *)cssmTime->Data, cssmTime->Length, &tm)) {
46 printf("***Bad time string format***\n");
47 return;
48 }
49 if(tm.tm_mon > 11) {
50 printf("***Bad time string format***\n");
51 return;
52 }
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);
56
57 }
58
59
60 static void printTime(const CSSM_X509_TIME *cssmTime)
61 {
62 /* ignore cssmTime->timeType for now */
63 printTimeStr(&cssmTime->time);
64 }
65
66 static void printDataAsHex(
67 const CSSM_DATA *d,
68 unsigned maxToPrint = 0) // optional, 0 means print it all
69 {
70 unsigned i;
71 bool more = false;
72 uint32 len = d->Length;
73 uint8 *cp = d->Data;
74
75 if((maxToPrint != 0) && (len > maxToPrint)) {
76 len = maxToPrint;
77 more = true;
78 }
79 for(i=0; i<len; i++) {
80 printf("%02X ", ((unsigned char *)cp)[i]);
81 }
82 if(more) {
83 printf("...\n");
84 }
85 else {
86 printf("\n");
87 }
88 }
89
90 /*
91 * Identify CSSM_BER_TAG with a C string.
92 */
93 static char *tagTypeString(
94 CSSM_BER_TAG tagType)
95 {
96 static char unknownType[80];
97
98 switch(tagType) {
99 case BER_TAG_UNKNOWN:
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";
109 case BER_TAG_NULL:
110 return "BER_TAG_NULL";
111 case BER_TAG_OID:
112 return "BER_TAG_OID";
113 case BER_TAG_SEQUENCE:
114 return "BER_TAG_SEQUENCE";
115 case BER_TAG_SET:
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";
127 default:
128 sprintf(unknownType, "Other type (0x%x)", tagType);
129 return unknownType;
130 }
131 }
132
133 /*
134 * Print an OID, assumed to be in BER encoded "Intel" format
135 * Length is inferred from oid->Length
136 * Tag is implied
137 */
138 static void printOid(OidParser &parser, const CSSM_DATA *oid)
139 {
140 char strBuf[OID_PARSER_STRING_SIZE];
141
142 if(oid == NULL) {
143 printf("NULL\n");
144 return;
145 }
146 if((oid->Length == 0) || (oid->Data == NULL)) {
147 printf("EMPTY\n");
148 return;
149 }
150 parser.oidParse(oid->Data, oid->Length, strBuf);
151 printf("%s\n", strBuf);
152 }
153
154 /*
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.
160 */
161 #define BLOB_LENGTH_PRINT 3
162
163 static void printBlobBytes(
164 char *blobType,
165 char *quanta, // e.g., "bytes', "bits"
166 uint32 bytesToPrint,
167 const CSSM_DATA *thing)
168 {
169 uint32 dex;
170 uint32 toPrint = bytesToPrint;
171
172 if(toPrint > BLOB_LENGTH_PRINT) {
173 toPrint = BLOB_LENGTH_PRINT;
174 }
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)) {
180 break;
181 }
182 }
183 if(dex < bytesToPrint) {
184 printf(" ...\n");
185 }
186 else {
187 printf("\n");
188 }
189 }
190
191 /*
192 * Print an IA5String or Printable string. Null terminator is not assumed.
193 * Trailing newline is printed.
194 */
195 static void printString(
196 const CSSM_DATA *str)
197 {
198 unsigned i;
199 char *cp = (char *)str->Data;
200 for(i=0; i<str->Length; i++) {
201 printf("%c", *cp++);
202 }
203 printf("\n");
204 }
205
206 static void printDerThing(
207 CSSM_BER_TAG tagType,
208 const CSSM_DATA *thing,
209 OidParser &parser)
210 {
211 switch(tagType) {
212 case BER_TAG_INTEGER:
213 printf("%d\n", cuDER_ToInt(thing));
214 return;
215 case BER_TAG_BOOLEAN:
216 if(thing->Length != 1) {
217 printf("***malformed BER_TAG_BOOLEAN: length %u data ",
218 (unsigned)thing->Length);
219 }
220 printf("%u\n", cuDER_ToInt(thing));
221 return;
222 case BER_TAG_PRINTABLE_STRING:
223 case BER_TAG_IA5_STRING:
224 case BER_TAG_T61_STRING: // mostly printable....
225 printString(thing);
226 return;
227 case BER_TAG_OCTET_STRING:
228 printBlobBytes("Byte string", "bytes", thing->Length, thing);
229 return;
230 case BER_TAG_BIT_STRING:
231 printBlobBytes("Bit string", "bits", (thing->Length + 7) / 8, thing);
232 return;
233 case BER_TAG_SEQUENCE:
234 printBlobBytes("Sequence", "bytes", thing->Length, thing);
235 return;
236 case BER_TAG_SET:
237 printBlobBytes("Set", "bytes", thing->Length, thing);
238 return;
239 case BER_TAG_OID:
240 printf("OID = ");
241 printOid(parser, thing);
242 break;
243 default:
244 printf("not displayed (tagType = %s; length %u)\n",
245 tagTypeString(tagType), (unsigned)thing->Length);
246 break;
247
248 }
249 }
250
251 static void printSigAlg(
252 const CSSM_X509_ALGORITHM_IDENTIFIER *sigAlg,
253 OidParser &parser)
254 {
255 printOid(parser, &sigAlg->algorithm);
256 if(sigAlg->parameters.Data != NULL) {
257 printf(" alg params : ");
258 printDataAsHex(&sigAlg->parameters, 8);
259 }
260 }
261
262 /* compare two OIDs, return CSSM_TRUE if identical */
263 static CSSM_BOOL compareOids(
264 const CSSM_OID *oid1,
265 const CSSM_OID *oid2)
266 {
267 if((oid1 == NULL) || (oid2 == NULL)) {
268 return CSSM_FALSE;
269 }
270 if(oid1->Length != oid2->Length) {
271 return CSSM_FALSE;
272 }
273 if(memcmp(oid1->Data, oid2->Data, oid1->Length)) {
274 return CSSM_FALSE;
275 }
276 else {
277 return CSSM_TRUE;
278 }
279 }
280
281 static void printRdn(
282 const CSSM_X509_RDN *rdnp,
283 OidParser &parser)
284 {
285 CSSM_X509_TYPE_VALUE_PAIR *ptvp;
286 unsigned pairDex;
287 char *fieldName;
288
289 for(pairDex=0; pairDex<rdnp->numberOfPairs; pairDex++) {
290 ptvp = &rdnp->AttributeTypeAndValue[pairDex];
291 if(compareOids(&ptvp->type, &CSSMOID_CountryName)) {
292 fieldName = "Country ";
293 }
294 else if(compareOids(&ptvp->type, &CSSMOID_OrganizationName)) {
295 fieldName = "Org ";
296 }
297 else if(compareOids(&ptvp->type, &CSSMOID_LocalityName)) {
298 fieldName = "Locality ";
299 }
300 else if(compareOids(&ptvp->type, &CSSMOID_OrganizationalUnitName)) {
301 fieldName = "OrgUnit ";
302 }
303 else if(compareOids(&ptvp->type, &CSSMOID_CommonName)) {
304 fieldName = "Common Name ";
305 }
306 else if(compareOids(&ptvp->type, &CSSMOID_Surname)) {
307 fieldName = "Surname ";
308 }
309 else if(compareOids(&ptvp->type, &CSSMOID_Title)) {
310 fieldName = "Title ";
311 }
312 else if(compareOids(&ptvp->type, &CSSMOID_Surname)) {
313 fieldName = "Surname ";
314 }
315 else if(compareOids(&ptvp->type, &CSSMOID_StateProvinceName)) {
316 fieldName = "State ";
317 }
318 else if(compareOids(&ptvp->type, &CSSMOID_CollectiveStateProvinceName)) {
319 fieldName = "Coll. State ";
320 }
321 else if(compareOids(&ptvp->type, &CSSMOID_EmailAddress)) {
322 /* deprecated, used by Thawte */
323 fieldName = "Email addrs ";
324 }
325 else {
326 fieldName = "Other name ";
327 }
328 printf(" %s : ", fieldName);
329 printDerThing(ptvp->valueType, &ptvp->value, parser);
330 } /* for each type/value pair */
331 }
332
333 static CSSM_RETURN printName(
334 const CSSM_X509_NAME *x509Name,
335 OidParser &parser)
336 {
337 CSSM_X509_RDN_PTR rdnp;
338 unsigned rdnDex;
339
340 for(rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) {
341 rdnp = &x509Name->RelativeDistinguishedName[rdnDex];
342 printRdn(rdnp, parser);
343 }
344
345 return CSSM_OK;
346 }
347
348 static void printKeyHeader(
349 const CSSM_KEYHEADER &hdr)
350 {
351 printf(" Algorithm : ");
352 switch(hdr.AlgorithmId) {
353 case CSSM_ALGID_RSA:
354 printf("RSA\n");
355 break;
356 case CSSM_ALGID_DSA:
357 printf("DSA\n");
358 break;
359 case CSSM_ALGID_FEE:
360 printf("FEE\n");
361 break;
362 case CSSM_ALGID_DH:
363 printf("Diffie-Hellman\n");
364 break;
365 default:
366 printf("Unknown(%u(d), 0x%x)\n", (unsigned)hdr.AlgorithmId,
367 (unsigned)hdr.AlgorithmId);
368 }
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 ");
374 }
375 if(usage & CSSM_KEYUSE_ENCRYPT) {
376 printf("CSSM_KEYUSE_ENCRYPT ");
377 }
378 if(usage & CSSM_KEYUSE_DECRYPT) {
379 printf("CSSM_KEYUSE_DECRYPT ");
380 }
381 if(usage & CSSM_KEYUSE_SIGN) {
382 printf("CSSM_KEYUSE_SIGN ");
383 }
384 if(usage & CSSM_KEYUSE_VERIFY) {
385 printf("CSSM_KEYUSE_VERIFY ");
386 }
387 if(usage & CSSM_KEYUSE_SIGN_RECOVER) {
388 printf("CSSM_KEYUSE_SIGN_RECOVER ");
389 }
390 if(usage & CSSM_KEYUSE_VERIFY_RECOVER) {
391 printf("CSSM_KEYUSE_VERIFY_RECOVER ");
392 }
393 if(usage & CSSM_KEYUSE_WRAP) {
394 printf("CSSM_KEYUSE_WRAP ");
395 }
396 if(usage & CSSM_KEYUSE_UNWRAP) {
397 printf("CSSM_KEYUSE_UNWRAP ");
398 }
399 if(usage & CSSM_KEYUSE_DERIVE) {
400 printf("CSSM_KEYUSE_DERIVE ");
401 }
402 printf("\n");
403
404 }
405
406 /*
407 * Print contents of a CE_GeneralNames as best we can.
408 */
409 static void printGeneralNames(
410 const CE_GeneralNames *generalNames,
411 OidParser &parser)
412 {
413 unsigned i;
414 CE_GeneralName *name;
415
416 for(i=0; i<generalNames->numNames; i++) {
417 name = &generalNames->generalName[i];
418 switch(name->nameType) {
419 case GNT_RFC822Name:
420 printf(" RFC822Name : ");
421 printString(&name->name);
422 break;
423 case GNT_DNSName:
424 printf(" DNSName : ");
425 printString(&name->name);
426 break;
427 case GNT_URI:
428 printf(" URI : ");
429 printString(&name->name);
430 break;
431 case GNT_IPAddress:
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)) {
436 printf(".");
437 }
438 }
439 printf("\n");
440 break;
441 case GNT_RegisteredID:
442 printf(" RegisteredID : ");
443 printOid(parser, &name->name);
444 break;
445 case GNT_X400Address:
446 /* ORAddress, a very complicated struct - punt */
447 printf(" X400Address : ");
448 printBlobBytes("Sequence", "bytes", name->name.Length, &name->name);
449 break;
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");
455 break;
456 }
457 const CSSM_X509_NAME *x509Name =
458 (const CSSM_X509_NAME *)name->name.Data;
459 printf(" Dir Name :\n");
460 printName(x509Name, parser);
461 }
462 else {
463 /* encoded Name (i.e. CSSM_X509_NAME) */
464 printf(" Dir Name : ");
465 printBlobBytes("Byte string", "bytes",
466 name->name.Length, &name->name);
467 }
468 break;
469 case GNT_EdiPartyName:
470 /* sequence EDIPartyName */
471 printf(" EdiPartyName : ");
472 printBlobBytes("Sequence", "bytes", name->name.Length, &name->name);
473 break;
474 case GNT_OtherName:
475 {
476 printf(" OtherName :\n");
477 if(name->name.Length != sizeof(CE_OtherName)) {
478 printf("***Malformed CE_OtherName\n");
479 break;
480 }
481 CE_OtherName *other = (CE_OtherName *)name->name.Data;
482 printf(" typeID : ");
483 printOid(parser, &other->typeId);
484 printf(" value : ");
485 printDataAsHex(&other->value, 0);
486 break;
487 }
488 }
489 }
490 }
491
492 static int printCdsaExtensionCommon(
493 const CSSM_X509_EXTENSION *cssmExt,
494 OidParser &parser,
495 bool expectParsed,
496 CSSM_BOOL verbose,
497 bool extraIndent = false)
498 {
499 if(extraIndent) {
500 printf(" Extension : "); printOid(parser, &cssmExt->extnId);
501 printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE");
502 }
503 else {
504 printf("Extension struct : "); printOid(parser, &cssmExt->extnId);
505 printf(" Critical : %s\n", cssmExt->critical ? "TRUE" : "FALSE");
506 }
507 switch(cssmExt->format) {
508 case CSSM_X509_DATAFORMAT_ENCODED:
509 if(expectParsed) {
510 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_PARSED\n");
511 return 1;
512 }
513 if((cssmExt->BERvalue.Data == NULL) ||
514 (cssmExt->value.parsedValue != NULL)) {
515 printf("***Malformed CSSM_X509_EXTENSION (1)\n");
516 return 1;
517 }
518 break;
519 case CSSM_X509_DATAFORMAT_PARSED:
520 if(!expectParsed) {
521 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
522 return 1;
523 }
524 if((cssmExt->BERvalue.Data != NULL) ||
525 (cssmExt->value.parsedValue == NULL)) {
526 printf("***Malformed CSSM_X509_EXTENSION (2)\n");
527 return 1;
528 }
529 break;
530 case CSSM_X509_DATAFORMAT_PAIR:
531 /* both parsed and encoded forms present */
532 if(!expectParsed) {
533 printf("Bad CSSM_X509_EXTENSION; expected FORMAT_ENCODED\n");
534 return 1;
535 }
536 if((cssmExt->BERvalue.Data == NULL) ||
537 (cssmExt->value.parsedValue == NULL)) {
538 printf("***Malformed CSSM_X509_EXTENSION (3)\n");
539 return 1;
540 }
541 if(verbose) {
542 /* also print some of the encoded form */
543 if(extraIndent) {
544 printf(" Unparsed data : ");
545 }
546 else {
547 printf(" Unparsed data : ");
548 }
549 printDataAsHex(&cssmExt->BERvalue, 8);
550 }
551 break;
552 default:
553 printf("***Unknown CSSM_X509_EXTENSION.format\n");
554 return 1;
555 }
556 return 0;
557 }
558
559 static int printExtensionCommon(
560 const CSSM_DATA &value,
561 OidParser &parser,
562 CSSM_BOOL verbose,
563 bool expectParsed = true)
564 {
565 if(value.Length != sizeof(CSSM_X509_EXTENSION)) {
566 printf("***malformed CSSM_FIELD (1)\n");
567 return 1;
568 }
569 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
570 return printCdsaExtensionCommon(cssmExt, parser, expectParsed, verbose);
571 }
572
573
574 static void printKeyUsage(
575 const CSSM_DATA &value)
576 {
577 CE_KeyUsage usage;
578 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
579
580 usage = *((CE_KeyUsage *)cssmExt->value.parsedValue);
581 printf(" usage : ");
582 if(usage & CE_KU_DigitalSignature) {
583 printf("DigitalSignature ");
584 }
585 if(usage & CE_KU_NonRepudiation) {
586 printf("NonRepudiation ");
587 }
588 if(usage & CE_KU_KeyEncipherment) {
589 printf("KeyEncipherment ");
590 }
591 if(usage & CE_KU_DataEncipherment) {
592 printf("DataEncipherment ");
593 }
594 if(usage & CE_KU_KeyAgreement) {
595 printf("KeyAgreement ");
596 }
597 if(usage & CE_KU_KeyCertSign) {
598 printf("KeyCertSign ");
599 }
600 if(usage & CE_KU_CRLSign) {
601 printf("CRLSign ");
602 }
603 if(usage & CE_KU_EncipherOnly) {
604 printf("EncipherOnly ");
605 }
606 if(usage & CE_KU_DecipherOnly) {
607 printf("DecipherOnly ");
608 }
609 printf("\n");
610
611 }
612
613 static void printBasicConstraints(
614 const CSSM_DATA &value)
615 {
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);
621 }
622 }
623
624 static void printExtKeyUsage(
625 const CSSM_DATA &value,
626 OidParser &parser)
627 {
628 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
629 CE_ExtendedKeyUsage *eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
630 unsigned oidDex;
631 for(oidDex=0; oidDex<eku->numPurposes; oidDex++) {
632 printf(" purpose %2d : ", oidDex);
633 printOid(parser, &eku->purposes[oidDex]);
634 }
635 }
636
637 static void printCssmAuthorityKeyId(
638 const CE_AuthorityKeyID *akid,
639 OidParser &parser)
640 {
641 if(akid->keyIdentifierPresent) {
642 printf(" Auth KeyID : ");
643 printDataAsHex(&akid->keyIdentifier,
644 8);
645 }
646 if(akid->generalNamesPresent) {
647 printGeneralNames(akid->generalNames, parser);
648 }
649 if(akid->serialNumberPresent) {
650 printf(" serialNumber : ");
651 printDataAsHex(&akid->serialNumber, 8);
652 }
653 }
654
655 static void printAuthorityKeyId(
656 const CSSM_DATA &value,
657 OidParser &parser)
658 {
659 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
660 CE_AuthorityKeyID *akid = (CE_AuthorityKeyID *)cssmExt->value.parsedValue;
661 printCssmAuthorityKeyId(akid, parser);
662 }
663
664 static void printSubjectIssuerAltName(
665 const CSSM_DATA &value,
666 OidParser &parser)
667 {
668 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
669 CE_GeneralNames *san = (CE_GeneralNames *)cssmExt->value.parsedValue;
670 printGeneralNames(san, parser);
671 }
672
673 static void printDistPointName(
674 const CE_DistributionPointName *dpn,
675 OidParser &parser)
676 {
677 switch(dpn->nameType) {
678 case CE_CDNT_FullName:
679 printGeneralNames(dpn->fullName, parser);
680 break;
681 case CE_CDNT_NameRelativeToCrlIssuer:
682 printRdn(dpn->rdn, parser);
683 break;
684 default:
685 printf("***BOGUS CE_DistributionPointName.nameType\n");
686 break;
687 }
688 }
689
690 static void printDistPoint(
691 const CE_CRLDistributionPoint *dp,
692 OidParser &parser)
693 {
694 if(dp->distPointName) {
695 printf(" Dist pt Name :\n");
696 printDistPointName(dp->distPointName, parser);
697 }
698 printf(" reasonsPresent : %s\n", dp->reasonsPresent ? "TRUE" : "FALSE");
699 if(dp->reasonsPresent) {
700 /* FIXME - parse */
701 printf(" reasons : 0x%X\n", dp->reasons);
702 }
703 if(dp->crlIssuer) {
704 printf(" CRLIssuer :\n");
705 printGeneralNames(dp->crlIssuer, parser);
706 }
707 }
708
709 static void printDistributionPoints(
710 const CSSM_DATA &value,
711 OidParser &parser)
712 {
713 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
714 CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
715
716 for(unsigned dex=0; dex<dps->numDistPoints; dex++) {
717 printf(" Dist pt %d :\n", dex);
718 printDistPoint(&dps->distPoints[dex], parser);
719 }
720 }
721
722 static void printValueOrNotPresent(
723 CSSM_BOOL present,
724 CSSM_BOOL value)
725 {
726 if(!present) {
727 printf("<Not Present>\n");
728 }
729 else if(value) {
730 printf("TRUE\n");
731 }
732 else {
733 printf("FALSE");
734 }
735 }
736
737 static void printIssuingDistributionPoint(
738 const CE_IssuingDistributionPoint *idp,
739 OidParser &parser)
740 {
741 if(idp->distPointName) {
742 printf(" Dist pt :\n");
743 printDistPointName(idp->distPointName, parser);
744 }
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);
753 }
754
755 static void printCertPolicies(
756 const CSSM_DATA &value,
757 OidParser &parser)
758 {
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,
770 &CSSMOID_QT_CPS)) {
771 printf(" CPS : ");
772 printString(&cQualInfo->qualifier);
773 }
774 else {
775 printf(" unparsed : ");
776 printDataAsHex(&cQualInfo->qualifier, 8);
777 }
778 }
779 }
780 }
781
782 static void printNetscapeCertType(
783 const CSSM_DATA &value)
784 {
785 CE_NetscapeCertType certType;
786 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)value.Data;
787
788 certType = *((CE_NetscapeCertType *)cssmExt->value.parsedValue);
789 printf(" certType : ");
790 if(certType & CE_NCT_SSL_Client) {
791 printf("SSL_Client ");
792 }
793 if(certType & CE_NCT_SSL_Server) {
794 printf("SSL_Server ");
795 }
796 if(certType & CE_NCT_SMIME) {
797 printf("S/MIME ");
798 }
799 if(certType & CE_NCT_ObjSign) {
800 printf("ObjectSign ");
801 }
802 if(certType & CE_NCT_Reserved) {
803 printf("Reserved ");
804 }
805 if(certType & CE_NCT_SSL_CA) {
806 printf("SSL_CA ");
807 }
808 if(certType & CE_NCT_SMIME_CA) {
809 printf("SMIME_CA ");
810 }
811 if(certType & CE_NCT_ObjSignCA) {
812 printf("ObjSignCA ");
813 }
814 printf("\n");
815 }
816
817 /* print one field */
818 void printCertField(
819 const CSSM_FIELD &field,
820 OidParser &parser,
821 CSSM_BOOL verbose)
822 {
823 const CSSM_DATA *thisData = &field.FieldValue;
824 const CSSM_OID *thisOid = &field.FieldOid;
825
826 if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Version)) {
827 if(verbose) {
828 printf("Version : %u\n", cuDER_ToInt(thisData));
829 }
830 }
831 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SerialNumber)) {
832 printf("Serial Number : "); printDataAsHex(thisData, 0);
833 }
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");
839 }
840 else {
841 printName(name, parser);
842 }
843 }
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");
849 }
850 else {
851 printName(name, parser);
852 }
853 }
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");
858 }
859 else if(verbose) {
860 printf("Not Before : "); printString(&cssmTime->time);
861 printf(" : ");
862 printTime(cssmTime);
863 }
864 else {
865 printf("Not Before : ");
866 printTime(cssmTime);
867 }
868 }
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");
873 }
874 else if(verbose) {
875 printf("Not After : "); printString(&cssmTime->time);
876 printf(" : ");
877 printTime(cssmTime);
878 }
879 else {
880 printf("Not After : ");
881 printTime(cssmTime);
882 }
883 }
884 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SignatureAlgorithmTBS)) {
885 if(verbose) {
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");
893 }
894 else {
895 printSigAlg(algId, parser);
896 }
897 }
898 }
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");
906 }
907 else {
908 printSigAlg(algId, parser);
909 }
910 }
911 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateIssuerUniqueId)) {
912 if(verbose) {
913 printf("Issuer UniqueId : ");
914 printDerThing(BER_TAG_BIT_STRING, thisData, parser);
915 }
916 }
917 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1CertificateSubjectUniqueId)) {
918 if(verbose) {
919 printf("Subject UniqueId : ");
920 printDerThing(BER_TAG_BIT_STRING, thisData, parser);
921 }
922 }
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");
930 }
931 else {
932 printSigAlg(&pubKeyInfo->algorithm, parser);
933 printf("Pub key Bytes : Length %u bytes : ",
934 (unsigned)pubKeyInfo->subjectPublicKey.Length);
935 printDataAsHex(&pubKeyInfo->subjectPublicKey, 8);
936 }
937 }
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");
944 }
945 else {
946 printKeyHeader(cssmKey->KeyHeader);
947 if(verbose) {
948 printf(" Key Blob : ");
949 printDataAsHex(&cssmKey->KeyData, 8);
950 }
951 }
952 }
953 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1Signature)) {
954 printf("Signature : %u bytes : ", (unsigned)thisData->Length);
955 printDataAsHex(thisData, 8);
956 }
957 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V3CertificateExtensionCStruct)) {
958 if(printExtensionCommon(*thisData, parser, verbose, false)) {
959 return;
960 }
961 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)thisData->Data;
962 printf(" Unparsed data : "); printDataAsHex(&cssmExt->BERvalue, 8);
963 }
964 else if(cuCompareCssmData(thisOid, &CSSMOID_KeyUsage)) {
965 if(printExtensionCommon(*thisData, parser, verbose)) {
966 return;
967 }
968 printKeyUsage(*thisData);
969 }
970 else if(cuCompareCssmData(thisOid, &CSSMOID_BasicConstraints)) {
971 if(printExtensionCommon(*thisData, parser, verbose)) {
972 return;
973 }
974 printBasicConstraints(*thisData);
975 }
976 else if(cuCompareCssmData(thisOid, &CSSMOID_ExtendedKeyUsage)) {
977 if(printExtensionCommon(*thisData, parser, verbose)) {
978 return;
979 }
980 printExtKeyUsage(*thisData, parser);
981 }
982 else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectKeyIdentifier)) {
983 if(printExtensionCommon(*thisData, parser, verbose)) {
984 return;
985 }
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");
990 }
991 else {
992 printf(" Subject KeyID : "); printDataAsHex(cdata, 8);
993 }
994 }
995 else if(cuCompareCssmData(thisOid, &CSSMOID_AuthorityKeyIdentifier)) {
996 if(printExtensionCommon(*thisData, parser, verbose)) {
997 return;
998 }
999 printAuthorityKeyId(*thisData, parser);
1000 }
1001 else if(cuCompareCssmData(thisOid, &CSSMOID_SubjectAltName)) {
1002 if(printExtensionCommon(*thisData, parser, verbose)) {
1003 return;
1004 }
1005 printSubjectIssuerAltName(*thisData, parser);
1006 }
1007 else if(cuCompareCssmData(thisOid, &CSSMOID_IssuerAltName)) {
1008 if(printExtensionCommon(*thisData, parser, verbose)) {
1009 return;
1010 }
1011 printSubjectIssuerAltName(*thisData, parser);
1012 }
1013 else if(cuCompareCssmData(thisOid, &CSSMOID_CertificatePolicies)) {
1014 if(printExtensionCommon(*thisData, parser, verbose)) {
1015 return;
1016 }
1017 printCertPolicies(*thisData, parser);
1018 }
1019 else if(cuCompareCssmData(thisOid, &CSSMOID_NetscapeCertType)) {
1020 if(printExtensionCommon(*thisData, parser, verbose)) {
1021 return;
1022 }
1023 printNetscapeCertType(*thisData);
1024 }
1025 else if(cuCompareCssmData(thisOid, &CSSMOID_CrlDistributionPoints)) {
1026 if(printExtensionCommon(*thisData, parser, verbose)) {
1027 return;
1028 }
1029 printDistributionPoints(*thisData, parser);
1030 }
1031 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1IssuerName)) {
1032 if(verbose) {
1033 printf("Normalized Issuer : ");
1034 printDataAsHex(thisData, 8);
1035 }
1036 }
1037 else if(cuCompareCssmData(thisOid, &CSSMOID_X509V1SubjectName)) {
1038 if(verbose) {
1039 printf("Normalized Subject : ");
1040 printDataAsHex(thisData, 8);
1041 }
1042 }
1043 else {
1044 printf("Other field: : "); printOid(parser, thisOid);
1045 }
1046 }
1047
1048 void printCrlExten(
1049 const CSSM_X509_EXTENSION *exten,
1050 CSSM_BOOL verbose,
1051 OidParser &parser)
1052 {
1053 const CSSM_OID *oid = &exten->extnId;
1054 const void *thisData = exten->value.parsedValue;
1055
1056 if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) {
1057 if(printCdsaExtensionCommon(exten, parser, false, verbose)) {
1058 return;
1059 }
1060 printf(" Unparsed data : "); printDataAsHex(&exten->BERvalue, 8);
1061 }
1062 else if(exten->format != CSSM_X509_DATAFORMAT_PAIR) {
1063 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1064 return;
1065 }
1066 else if(cuCompareCssmData(oid, &CSSMOID_AuthorityKeyIdentifier)) {
1067 if(printCdsaExtensionCommon(exten, parser, true, verbose)) {
1068 return;
1069 }
1070 printCssmAuthorityKeyId((CE_AuthorityKeyID *)thisData, parser);
1071 }
1072 else if(cuCompareCssmData(oid, &CSSMOID_IssuerAltName)) {
1073 if(printCdsaExtensionCommon(exten, parser, true, verbose)) {
1074 return;
1075 }
1076 printGeneralNames((CE_GeneralNames *)thisData, parser);
1077 }
1078 else if(cuCompareCssmData(oid, &CSSMOID_CrlNumber)) {
1079 if(printCdsaExtensionCommon(exten, parser, true, verbose)) {
1080 return;
1081 }
1082 printf(" CRL Number : %u\n", *((unsigned *)thisData));
1083 }
1084 else if(cuCompareCssmData(oid, &CSSMOID_DeltaCrlIndicator)) {
1085 if(printCdsaExtensionCommon(exten, parser, true, verbose)) {
1086 return;
1087 }
1088 printf(" Delta CRL Base : %u\n", *((unsigned *)thisData));
1089 }
1090 else if(cuCompareCssmData(oid, &CSSMOID_IssuingDistributionPoint)) {
1091 if(printCdsaExtensionCommon(exten, parser, true, verbose)) {
1092 return;
1093 }
1094 printIssuingDistributionPoint((CE_IssuingDistributionPoint *)thisData,
1095 parser);
1096 }
1097 else {
1098 /* should never happen - we're out of sync with the CL */
1099 printf("UNKNOWN EXTENSION : "); printOid(parser, oid);
1100 }
1101 }
1102
1103 void printCrlEntryExten(
1104 const CSSM_X509_EXTENSION *exten,
1105 CSSM_BOOL verbose,
1106 OidParser &parser)
1107 {
1108 const CSSM_OID *oid = &exten->extnId;
1109 const void *thisData = exten->value.parsedValue;
1110
1111 if(exten->format == CSSM_X509_DATAFORMAT_ENCODED) {
1112 if(printCdsaExtensionCommon(exten, parser, false, verbose, true)) {
1113 return;
1114 }
1115 printf(" Unparsed data: "); printDataAsHex(&exten->BERvalue, 8);
1116 }
1117 else if(exten->format != CSSM_X509_DATAFORMAT_PAIR) {
1118 printf("***Badly formatted CSSM_X509_EXTENSION\n");
1119 return;
1120 }
1121 else if(cuCompareCssmData(oid, &CSSMOID_CrlReason)) {
1122 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) {
1123 return;
1124 }
1125 CE_CrlReason *cr = (CE_CrlReason *)thisData;
1126 char *reason = "UNKNOWN";
1127 switch(*cr) {
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;
1144 default:
1145 break;
1146 }
1147 printf(" CRL Reason : %s\n", reason);
1148 }
1149 else if(cuCompareCssmData(oid, &CSSMOID_HoldInstructionCode)) {
1150 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) {
1151 return;
1152 }
1153 printf(" Hold Instr : ");
1154 printOid(parser, (CSSM_OID_PTR)thisData);
1155 }
1156 else if(cuCompareCssmData(oid, &CSSMOID_InvalidityDate)) {
1157 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) {
1158 return;
1159 }
1160 printf(" Invalid Date : ");
1161 printTimeStr((CSSM_DATA_PTR)thisData);
1162 }
1163 else if(cuCompareCssmData(oid, &CSSMOID_CertIssuer)) {
1164 if(printCdsaExtensionCommon(exten, parser, true, verbose, true)) {
1165 return;
1166 }
1167 printGeneralNames((CE_GeneralNames *)thisData, parser);
1168 }
1169 else {
1170 /* should never happen - we're out of sync with the CL */
1171 printf("UNKNOWN EXTENSION : "); printOid(parser, oid);
1172 }
1173 }
1174
1175 void printCrlFields(
1176 const CSSM_X509_SIGNED_CRL *signedCrl,
1177 CSSM_BOOL verbose,
1178 OidParser &parser)
1179 {
1180 unsigned i;
1181 const CSSM_X509_TBS_CERTLIST *tbsCrl = &signedCrl->tbsCertList;
1182
1183 if(tbsCrl->version.Data) {
1184 printf("Version : %d\n", cuDER_ToInt(&tbsCrl->version));
1185 }
1186
1187 printf("TBS Sig Algorithm : ");
1188 const CSSM_X509_ALGORITHM_IDENTIFIER *algId = &tbsCrl->signature;
1189 printSigAlg(algId, parser);
1190
1191 printf("Issuer Name :\n");
1192 printName(&tbsCrl->issuer, parser);
1193
1194 printf("This Update : ");
1195 printTime(&tbsCrl->thisUpdate);
1196 printf("Next Update : ");
1197 if(tbsCrl->nextUpdate.time.Data) {
1198 printTime(&tbsCrl->nextUpdate);
1199 }
1200 else {
1201 printf("<not present>\n");
1202 }
1203
1204 CSSM_X509_REVOKED_CERT_LIST_PTR certList = tbsCrl->revokedCertificates;
1205 if(certList) {
1206 if(verbose) {
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) {
1220 continue;
1221 }
1222 printf(" Num Extensions : %u\n", (unsigned)numExtens);
1223 for(unsigned dex=0; dex<numExtens; dex++) {
1224 printCrlEntryExten(&cssmExtens->extensions[dex], verbose,
1225 parser);
1226 }
1227 }
1228 }
1229 else {
1230 printf("Num Revoked Certs : %d (use verbose option to see)\n",
1231 (int)certList->numberOfRevokedCertEntries);
1232 }
1233 }
1234
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);
1241 }
1242 }
1243
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);
1248 }
1249 }
1250
1251
1252 /* connect to CSSM/CL lazily, once */
1253 static CSSM_CL_HANDLE clHand = 0;
1254
1255 int printCert(
1256 const unsigned char *certData,
1257 unsigned certLen,
1258 CSSM_BOOL verbose)
1259 {
1260 CSSM_FIELD_PTR fieldPtr; // mallocd by CL
1261 uint32 i;
1262 uint32 numFields;
1263 OidParser parser;
1264 CSSM_DATA cert;
1265
1266 if(clHand == 0) {
1267 clHand = cuClStartup();
1268 if(clHand == 0) {
1269 printf("***Error connecting to CSSM cert module; aborting cert "
1270 "display\n");
1271 return 0;
1272 }
1273 }
1274 cert.Data = (uint8 *)certData;
1275 cert.Length = certLen;
1276
1277 CSSM_RETURN crtn = CSSM_CL_CertGetAllFields(clHand,
1278 &cert,
1279 &numFields,
1280 &fieldPtr);
1281 if(crtn) {
1282 cuPrintError("CSSM_CL_CertGetAllFields", crtn);
1283 return crtn;
1284 }
1285
1286 for(i=0; i<numFields; i++) {
1287 printCertField(fieldPtr[i], parser, verbose);
1288 }
1289
1290 crtn = CSSM_CL_FreeFields(clHand, numFields, &fieldPtr);
1291 if(crtn) {
1292 cuPrintError("CSSM_CL_FreeFields", crtn);
1293 return crtn;
1294 }
1295 return 0;
1296 }
1297
1298 /* parse CRL */
1299 /* This one's easier, we just get one field - the whole parsed CRL */
1300 int printCrl(
1301 const unsigned char *crlData,
1302 unsigned crlLen,
1303 CSSM_BOOL verbose)
1304 {
1305 CSSM_DATA_PTR value; // mallocd by CL
1306 uint32 numFields;
1307 OidParser parser;
1308 CSSM_DATA crl;
1309 CSSM_HANDLE result;
1310
1311 if(clHand == 0) {
1312 clHand = cuClStartup();
1313 if(clHand == 0) {
1314 printf("***Error connecting to CSSM cert module; aborting CRL"
1315 "display\n");
1316 return 0;
1317 }
1318 }
1319 crl.Data = (uint8 *)crlData;
1320 crl.Length = crlLen;
1321
1322 CSSM_RETURN crtn = CSSM_CL_CrlGetFirstFieldValue(clHand,
1323 &crl,
1324 &CSSMOID_X509V2CRLSignedCrlCStruct,
1325 &result,
1326 &numFields,
1327 &value);
1328 if(crtn) {
1329 cuPrintError("CSSM_CL_CrlGetFirstFieldValue", crtn);
1330 return crtn;
1331 }
1332 if(numFields != 1) {
1333 printf("***CSSM_CL_CrlGetFirstFieldValue: numFields error\n");
1334 printf(" expected 1, got %d\n", (int)numFields);
1335 return 1;
1336 }
1337 crtn = CSSM_CL_CrlAbortQuery(clHand, result);
1338 if(crtn) {
1339 cuPrintError("CSSM_CL_CertAbortQuery", crtn);
1340 return crtn;
1341 }
1342
1343 if(value == NULL) {
1344 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (1)\n");
1345 return 1;
1346 }
1347 if((value->Data == NULL) ||
1348 (value->Length != sizeof(CSSM_X509_SIGNED_CRL))) {
1349 printf("***CSSM_CL_CrlGetFirstFieldValue: value error (2)\n");
1350 return 1;
1351 }
1352 const CSSM_X509_SIGNED_CRL *signedCrl =
1353 (const CSSM_X509_SIGNED_CRL *)value->Data;
1354 printCrlFields(signedCrl, verbose, parser);
1355
1356 crtn = CSSM_CL_FreeFieldValue(clHand,
1357 &CSSMOID_X509V2CRLSignedCrlCStruct,
1358 value);
1359 if(crtn) {
1360 cuPrintError("CSSM_CL_FreeFieldValue", crtn);
1361 return crtn;
1362 }
1363 return 0;
1364 }
1365
1366
1367 void printCertShutdown()
1368 {
1369 if(clHand != 0) {
1370 CSSM_ModuleDetach(clHand);
1371 }
1372 }