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