]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/makeCrl/makeCrl.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / makeCrl / makeCrl.cpp
1 /*
2 * makeCrl.cpp - create a CRL revoking a given cert
3 */
4
5 #include <stdlib.h>
6 #include <strings.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <Security/Security.h>
10 #include <Security/SecAsn1Coder.h>
11 #include <Security/SecAsn1Types.h>
12 #include <Security/X509Templates.h>
13 #include <Security/keyTemplates.h>
14 #include <Security/SecKeyPriv.h>
15 #include <Security/SecIdentityPriv.h>
16 #include <utilLib/common.h>
17 #include <security_cdsa_utils/cuFileIo.h>
18 #include <clAppUtils/timeStr.h>
19
20 #define THIS_UPDATE_DEF 0
21 #define NEXT_UPDATE_DEF (60 * 60 * 24)
22 #define REVOKE_TIME_DEF (60 * 60 * 12)
23
24 static void usage(char **argv)
25 {
26 printf("usage: %s [requiredParams...] [options...]\n", argv[0]);
27 printf("Required parameters:\n");
28 printf(" -s subjectCert\n");
29 printf(" -i issuerCert\n");
30 printf(" -o outputFile\n");
31 printf("Options:\n");
32 printf(" -k keychain -- contains issuerCert identity; default is default KC list\n");
33 printf(" -r revokeTime -- seconds after 'now' cert is revoked; default is %d\n",
34 REVOKE_TIME_DEF);
35 printf(" -t thisUpdate -- CRL thisUpdate, seconds after 'now'; default is %d\n",
36 THIS_UPDATE_DEF);
37 printf(" -n thisUpdate -- CRL nextUpdate, seconds after 'now'; default is %d\n",
38 NEXT_UPDATE_DEF);
39 /* etc. */
40 exit(1);
41 }
42
43 /* seconds from now --> NSS_Time */
44 /* caller must eventually free nssTime.item.Data */
45 static void secondsToNssTime(
46 int seconds,
47 NSS_Time *nssTime)
48 {
49 char *revocationDate = genTimeAtNowPlus(seconds);
50 nssTime->item.Data = (uint8 *)revocationDate;
51 nssTime->item.Length = strlen(revocationDate);
52 nssTime->tag = SEC_ASN1_GENERALIZED_TIME;
53 }
54
55 /* sign some data using a SecKeyRef */
56 static OSStatus secSign(
57 SecKeyRef signingKey,
58 CSSM_ALGORITHMS sigAlg,
59 const CSSM_DATA *ptext,
60 CSSM_DATA *sig)
61 {
62 const CSSM_KEY *cssmKey;
63 CSSM_CSP_HANDLE cspHand;
64 const CSSM_ACCESS_CREDENTIALS *creds;
65 CSSM_CC_HANDLE sigHand = 0;
66 CSSM_RETURN crtn;
67 OSStatus ortn;
68
69 ortn = SecKeyGetCSSMKey(signingKey, &cssmKey);
70 if(ortn) {
71 cssmPerror("SecKeyGetCSSMKey", ortn);
72 return ortn;
73 }
74 ortn = SecKeyGetCSPHandle(signingKey, &cspHand);
75 if(ortn) {
76 cssmPerror("SecKeyGetCSPHandle", ortn);
77 return ortn;
78 }
79 ortn = SecKeyGetCredentials(signingKey,
80 CSSM_ACL_AUTHORIZATION_SIGN,
81 kSecCredentialTypeDefault,
82 &creds);
83 if(ortn) {
84 cssmPerror("SecKeyGetCredentials", ortn);
85 return ortn;
86 }
87 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
88 sigAlg,
89 creds,
90 cssmKey,
91 &sigHand);
92 if(crtn) {
93 cssmPerror("CSSM_CSP_CreateSignatureContext", crtn);
94 return crtn;
95 }
96 sig->Data = NULL;
97 sig->Length = 0;
98 crtn = CSSM_SignData(sigHand,
99 ptext,
100 1,
101 CSSM_ALGID_NONE, // digestAlg for raw sign
102 sig);
103 CSSM_DeleteContext(sigHand);
104 return crtn;
105 }
106
107 /* basic "create and sign a CRL" routine - the CL is not capable of this */
108 static int makeCrl(
109 const unsigned char *subjectCert,
110 unsigned subjectCertLen,
111 SecKeyRef signingKey,
112 int revokeTime, // revocation time, seconds from now (+/-)
113 int crlThisUpdate, // CRL thisUpdate, seconds from now (+/-)
114 int crlNextUpdate, // CRL nextUpdate, seconds from now (+/-)
115 unsigned char **crlOut, // mallocd and returned
116 unsigned *crlOutLen) // returned
117 {
118 SecAsn1CoderRef coder = NULL;
119 OSStatus ortn;
120 int ourRtn = -1;
121 NSS_Certificate subject;
122 NSS_RevokedCert revokedCert;
123 NSS_TBSCrl tbsCrl;
124 NSS_SignedCertOrCRL crl;
125 CSSM_DATA encodedCrl = {0, NULL};
126 uint8 nullEnc[2] = {5, 0};
127 CSSM_DATA nullEncData = {2, nullEnc};
128
129 ortn = SecAsn1CoderCreate(&coder);
130 if(ortn) {
131 cssmPerror("SecAsn1CoderCreate", ortn);
132 goto errOut;
133 }
134
135 /* decode subject to get serial number and issuer */
136 memset(&subject, 0, sizeof(subject));
137 ortn = SecAsn1Decode(coder, subjectCert, subjectCertLen, kSecAsn1SignedCertTemplate,
138 &subject);
139 if(ortn) {
140 cssmPerror("SecAsn1Decode(subjectCert)", ortn);
141 goto errOut;
142 }
143
144 /* revoked cert entry - no extensions */
145 revokedCert.userCertificate = subject.tbs.serialNumber;
146 secondsToNssTime(revokeTime, &revokedCert.revocationDate);
147 revokedCert.extensions = NULL;
148
149 /* TBS CRL - assume RSA signing key for now */
150 memset(&tbsCrl, 0, sizeof(tbsCrl));
151 tbsCrl.signature.algorithm = CSSMOID_SHA1WithRSA;
152 tbsCrl.signature.parameters = nullEncData;
153 tbsCrl.issuer = subject.tbs.issuer;
154 secondsToNssTime(crlThisUpdate, &tbsCrl.thisUpdate);
155 secondsToNssTime(crlNextUpdate, &tbsCrl.nextUpdate);
156 tbsCrl.revokedCerts = (NSS_RevokedCert **)(SecAsn1Malloc(coder, sizeof(void *) * 2));
157 tbsCrl.revokedCerts[0] = &revokedCert;
158 tbsCrl.revokedCerts[1] = NULL;
159 tbsCrl.extensions = NULL;
160
161 /* encode TBS */
162 memset(&crl, 0, sizeof(crl));
163 ortn = SecAsn1EncodeItem(coder, &tbsCrl, kSecAsn1TBSCrlTemplate, &crl.tbsBlob);
164 if(ortn) {
165 cssmPerror("SecAsn1EncodeItem(tbsCrl)", ortn);
166 goto errOut;
167 }
168
169 /* encode top-level algid */
170 ortn = SecAsn1EncodeItem(coder, &tbsCrl.signature,
171 kSecAsn1AlgorithmIDTemplate, &crl.signatureAlgorithm);
172 if(ortn) {
173 cssmPerror("SecAsn1EncodeItem(signatureAlgorithm)", ortn);
174 goto errOut;
175 }
176
177 /* sign TBS */
178 ortn = secSign(signingKey, CSSM_ALGID_SHA1WithRSA, &crl.tbsBlob,
179 &crl.signature);
180 if(ortn) {
181 goto errOut;
182 }
183
184 /* Encode result. Signature is bit string... */
185 crl.signature.Length *= 8;
186 ortn = SecAsn1EncodeItem(coder, &crl,
187 kSecAsn1SignedCertOrCRLTemplate, &encodedCrl);
188 if(ortn) {
189 cssmPerror("SecAsn1EncodeItem(encodedCrl)", ortn);
190 goto errOut;
191 }
192 *crlOut = (unsigned char *)malloc(encodedCrl.Length);
193 *crlOut = (unsigned char *)encodedCrl.Data;
194 *crlOutLen = encodedCrl.Length;
195 ourRtn = 0;
196
197 errOut:
198 if(coder) {
199 SecAsn1CoderRelease(coder);
200 }
201 if(revokedCert.revocationDate.item.Data) {
202 CSSM_FREE(revokedCert.revocationDate.item.Data);
203 }
204 if(tbsCrl.thisUpdate.item.Data) {
205 CSSM_FREE(tbsCrl.thisUpdate.item.Data);
206 }
207 if(revokedCert.revocationDate.item.Data) {
208 CSSM_FREE(tbsCrl.nextUpdate.item.Data);
209 }
210 return ourRtn;
211 }
212
213 int main(int argc, char **argv)
214 {
215 char *subjectName = NULL;
216 char *issuerName = NULL;
217 char *outFileName = NULL;
218 char *kcName = NULL;
219 int revokeTime = REVOKE_TIME_DEF;
220 int thisUpdate = THIS_UPDATE_DEF;
221 int nextUpdate = NEXT_UPDATE_DEF;
222
223 extern char *optarg;
224 int arg;
225 while ((arg = getopt(argc, argv, "s:i:o:k:r:t:n:h")) != -1) {
226 switch (arg) {
227 case 's':
228 subjectName = optarg;
229 break;
230 case 'i':
231 issuerName = optarg;
232 break;
233 case 'o':
234 outFileName = optarg;
235 break;
236 case 'k':
237 kcName = optarg;
238 break;
239 case 'r':
240 revokeTime = atoi(optarg);
241 break;
242 case 't':
243 thisUpdate = atoi(optarg);
244 break;
245 case 'n':
246 nextUpdate = atoi(optarg);
247 break;
248 default:
249 case 'h':
250 usage(argv);
251 }
252 }
253 if(optind != argc) {
254 usage(argv);
255 }
256 if((subjectName == NULL) || (issuerName == NULL) || (outFileName == NULL)) {
257 usage(argv);
258 }
259
260 /* get input files */
261 unsigned char *subjectCert;
262 unsigned subjectCertLen;
263 unsigned char *issuerCert;
264 unsigned issuerCertLen;
265 if(readFile(subjectName, &subjectCert, &subjectCertLen)) {
266 printf("***Error reading %s. \n", subjectName);
267 exit(1);
268 }
269 if(readFile(issuerName, &issuerCert, &issuerCertLen)) {
270 printf("***Error reading %s. \n", issuerName);
271 exit(1);
272 }
273
274 /* get issuer identity and signing key */
275 SecKeychainRef kcRef = NULL;
276 OSStatus ortn;
277 if(kcName) {
278 ortn = SecKeychainOpen(kcName, &kcRef);
279 if(ortn) {
280 cssmPerror("SecKeychainOpen", ortn);
281 exit(1);
282 }
283 }
284 SecCertificateRef certRef = NULL;
285 SecIdentityRef idRef = NULL;
286 SecKeyRef signingKey = NULL;
287 CSSM_DATA issuerCData = {issuerCertLen, (uint8 *)issuerCert};
288 ortn = SecCertificateCreateFromData(&issuerCData,
289 CSSM_CERT_X_509v3,
290 CSSM_CERT_ENCODING_DER,
291 &certRef);
292 if(ortn) {
293 cssmPerror("SecCertificateCreateFromData", ortn);
294 exit(1);
295 }
296 ortn = SecIdentityCreateWithCertificate(kcRef, certRef, &idRef);
297 if(ortn) {
298 cssmPerror("SecIdentityCreateWithCertificate", ortn);
299 exit(1);
300 }
301 ortn = SecIdentityCopyPrivateKey(idRef, &signingKey);
302 if(ortn) {
303 cssmPerror("SecIdentityCopyPrivateKey", ortn);
304 exit(1);
305 }
306
307 /* create and sign the CRL */
308 unsigned char *crlOut = NULL;
309 unsigned crlOutLen = 0;
310 if(makeCrl(subjectCert, subjectCertLen,
311 signingKey,
312 revokeTime, thisUpdate, nextUpdate,
313 &crlOut, &crlOutLen)) {
314 printf("***Error creating CRL. Aborting.\n");
315 exit(1);
316 }
317
318 /* ==> outFile */
319 if(writeFile(outFileName, crlOut, crlOutLen)) {
320 printf("***Error writing CRL to %s\n", outFileName);
321 }
322 else {
323 printf("...wrote %u bytes to %s.\n", crlOutLen, outFileName);
324 }
325 /* cleanup if you must */
326
327 return 0;
328 }