1/*
2 * Copyright (c) 2005-2007,2010 Apple Inc. All Rights Reserved.
3 *
4 * parseCrl.c - parse a DER-encoded X509 CRL using libDER.
5 */
6
7#include <stdlib.h>
8#include <strings.h>
9#include <stdio.h>
10#include <unistd.h>
11#include <libDER/libDER.h>
12#include <libDER/asn1Types.h>
13#include <libDER/DER_CertCrl.h>
14#include <libDER/DER_Keys.h>
15#include <libDERUtils/fileIo.h>
16#include <libDERUtils/libDERUtils.h>
17#include <libDERUtils/printFields.h>
18
19static void usage(char **argv)
20{
21	printf("usage: %s crlFile [options]\n", argv[0]);
22	printf("Options:\n");
23	printf("  -v     -- verbose \n");
24	/* etc. */
25	exit(1);
26}
27
28/*
29 * This is a SEQUENCE OF so we use the low-level DERDecodeSeq* routines to snag one entry
30 * at a time.
31 */
32static void	printRevokedCerts(
33	DERItem *revokedCerts,
34	int verbose)
35{
36	DERReturn drtn;
37	DERDecodedInfo currItem;
38	DERSequence seq;
39	unsigned certNum;
40	DERRevokedCert revoked;
41
42	drtn = DERDecodeSeqContentInit(revokedCerts, &seq);
43	if(drtn) {
44		DERPerror("DERDecodeSeqContentInit(revokedCerts)", drtn);
45		return;
46	}
47
48	for(certNum=0; ; certNum++) {
49		drtn = DERDecodeSeqNext(&seq, &currItem);
50		switch(drtn) {
51			case DR_EndOfSequence:
52				/* normal termination */
53				return;
54			default:
55				DERPerror("DERDecodeSeqNext", drtn);
56				return;
57			case DR_Success:
58				doIndent();
59				printf("revoked cert %u\n", certNum);
60				incrIndent();
61				drtn = DERParseSequenceContent(&currItem.content,
62					DERNumRevokedCertItemSpecs, DERRevokedCertItemSpecs,
63					&revoked, sizeof(revoked));
64				if(drtn) {
65					DERPerror("DERParseSequenceContent(RevokedCert)", drtn);
66					decrIndent();
67					return;
68				}
69				printItem("serialNum", IT_Leaf, verbose, ASN1_INTEGER, &revoked.serialNum);
70				decodePrintItem("revocationDate",  IT_Leaf, verbose, &revoked.revocationDate);
71				printItem("extensions", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &revoked.extensions);
72				decrIndent();
73		}
74	}
75}
76
77int main(int argc, char **argv)
78{
79	unsigned char *crlData = NULL;
80	unsigned crlDataLen = 0;
81	DERSignedCertCrl signedCrl;
82	DERTBSCrl tbs;
83	DERReturn drtn;
84	DERItem item;
85	int verbose = 0;
86	extern char *optarg;
87	int arg;
88	extern int optind;
89
90	if(argc < 2) {
91		usage(argv);
92	}
93	if(readFile(argv[1], &crlData, &crlDataLen)) {
94		printf("***Error reading CRL from %s. Aborting.\n", argv[1]);
95		exit(1);
96	}
97
98	optind = 2;
99	while ((arg = getopt(argc, argv, "vh")) != -1) {
100		switch (arg) {
101			case 'v':
102				verbose = 1;
103				break;
104			case 'h':
105				usage(argv);
106		}
107	}
108	if(optind != argc) {
109		usage(argv);
110	}
111
112	/* Top level decode of signed CRL into 3 components */
113	item.data = crlData;
114	item.length = crlDataLen;
115	drtn = DERParseSequence(&item, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs,
116		&signedCrl, sizeof(signedCrl));
117	if(drtn) {
118		DERPerror("DERParseSequence(SignedCrl)", drtn);
119		exit(1);
120	}
121	printItem("TBSCrl", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCrl.tbs);
122
123	incrIndent();
124
125	/* decode the TBSCrl - it was saved in full DER form */
126	drtn = DERParseSequence(&signedCrl.tbs,
127		DERNumTBSCrlItemSpecs, DERTBSCrlItemSpecs,
128		&tbs, sizeof(tbs));
129	if(drtn) {
130		DERPerror("DERParseSequenceContent(TBSCrl)", drtn);
131		exit(1);
132	}
133	if(tbs.version.data) {
134		printItem("version", IT_Leaf, verbose, ASN1_INTEGER, &tbs.version);
135	}
136
137	printItem("tbsSigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &tbs.tbsSigAlg);
138	incrIndent();
139	printAlgId(&tbs.tbsSigAlg, verbose);
140	decrIndent();
141
142	printItem("issuer", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.issuer);
143
144	decodePrintItem("thisUpdate",  IT_Leaf, verbose, &tbs.thisUpdate);
145	decodePrintItem("nextUpdate",  IT_Leaf, verbose, &tbs.nextUpdate);
146
147	if(tbs.revokedCerts.data) {
148		printItem("version", IT_Leaf, verbose, ASN1_CONSTR_SEQUENCE, &tbs.revokedCerts);
149		incrIndent();
150		printRevokedCerts(&tbs.revokedCerts, verbose);
151		decrIndent();
152	}
153
154	if(tbs.extensions.data) {
155		printItem("extensions", IT_Leaf, verbose, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC | 3,
156			&tbs.extensions);
157	}
158
159	printItem("sigAlg", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &signedCrl.sigAlg);
160	incrIndent();
161	printAlgId(&signedCrl.sigAlg, verbose);
162	decrIndent();
163
164	printItem("sig", IT_Leaf, verbose, ASN1_BIT_STRING, &signedCrl.sig);
165
166	return 0;
167}
168