2 * makeCrl.cpp - create a CRL revoking a given cert
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>
20 #define THIS_UPDATE_DEF 0
21 #define NEXT_UPDATE_DEF (60 * 60 * 24)
22 #define REVOKE_TIME_DEF (60 * 60 * 12)
24 static void usage(char **argv
)
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");
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",
35 printf(" -t thisUpdate -- CRL thisUpdate, seconds after 'now'; default is %d\n",
37 printf(" -n thisUpdate -- CRL nextUpdate, seconds after 'now'; default is %d\n",
43 /* seconds from now --> NSS_Time */
44 /* caller must eventually free nssTime.item.Data */
45 static void secondsToNssTime(
49 char *revocationDate
= genTimeAtNowPlus(seconds
);
50 nssTime
->item
.Data
= (uint8
*)revocationDate
;
51 nssTime
->item
.Length
= strlen(revocationDate
);
52 nssTime
->tag
= SEC_ASN1_GENERALIZED_TIME
;
55 /* sign some data using a SecKeyRef */
56 static OSStatus
secSign(
58 CSSM_ALGORITHMS sigAlg
,
59 const CSSM_DATA
*ptext
,
62 const CSSM_KEY
*cssmKey
;
63 CSSM_CSP_HANDLE cspHand
;
64 const CSSM_ACCESS_CREDENTIALS
*creds
;
65 CSSM_CC_HANDLE sigHand
= 0;
69 ortn
= SecKeyGetCSSMKey(signingKey
, &cssmKey
);
71 cssmPerror("SecKeyGetCSSMKey", ortn
);
74 ortn
= SecKeyGetCSPHandle(signingKey
, &cspHand
);
76 cssmPerror("SecKeyGetCSPHandle", ortn
);
79 ortn
= SecKeyGetCredentials(signingKey
,
80 CSSM_ACL_AUTHORIZATION_SIGN
,
81 kSecCredentialTypeDefault
,
84 cssmPerror("SecKeyGetCredentials", ortn
);
87 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
93 cssmPerror("CSSM_CSP_CreateSignatureContext", crtn
);
98 crtn
= CSSM_SignData(sigHand
,
101 CSSM_ALGID_NONE
, // digestAlg for raw sign
103 CSSM_DeleteContext(sigHand
);
107 /* basic "create and sign a CRL" routine - the CL is not capable of this */
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
118 SecAsn1CoderRef coder
= NULL
;
121 NSS_Certificate subject
;
122 NSS_RevokedCert revokedCert
;
124 NSS_SignedCertOrCRL crl
;
125 CSSM_DATA encodedCrl
= {0, NULL
};
126 uint8 nullEnc
[2] = {5, 0};
127 CSSM_DATA nullEncData
= {2, nullEnc
};
129 ortn
= SecAsn1CoderCreate(&coder
);
131 cssmPerror("SecAsn1CoderCreate", ortn
);
135 /* decode subject to get serial number and issuer */
136 memset(&subject
, 0, sizeof(subject
));
137 ortn
= SecAsn1Decode(coder
, subjectCert
, subjectCertLen
, kSecAsn1SignedCertTemplate
,
140 cssmPerror("SecAsn1Decode(subjectCert)", ortn
);
144 /* revoked cert entry - no extensions */
145 revokedCert
.userCertificate
= subject
.tbs
.serialNumber
;
146 secondsToNssTime(revokeTime
, &revokedCert
.revocationDate
);
147 revokedCert
.extensions
= NULL
;
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
;
162 memset(&crl
, 0, sizeof(crl
));
163 ortn
= SecAsn1EncodeItem(coder
, &tbsCrl
, kSecAsn1TBSCrlTemplate
, &crl
.tbsBlob
);
165 cssmPerror("SecAsn1EncodeItem(tbsCrl)", ortn
);
169 /* encode top-level algid */
170 ortn
= SecAsn1EncodeItem(coder
, &tbsCrl
.signature
,
171 kSecAsn1AlgorithmIDTemplate
, &crl
.signatureAlgorithm
);
173 cssmPerror("SecAsn1EncodeItem(signatureAlgorithm)", ortn
);
178 ortn
= secSign(signingKey
, CSSM_ALGID_SHA1WithRSA
, &crl
.tbsBlob
,
184 /* Encode result. Signature is bit string... */
185 crl
.signature
.Length
*= 8;
186 ortn
= SecAsn1EncodeItem(coder
, &crl
,
187 kSecAsn1SignedCertOrCRLTemplate
, &encodedCrl
);
189 cssmPerror("SecAsn1EncodeItem(encodedCrl)", ortn
);
192 *crlOut
= (unsigned char *)malloc(encodedCrl
.Length
);
193 *crlOut
= (unsigned char *)encodedCrl
.Data
;
194 *crlOutLen
= encodedCrl
.Length
;
199 SecAsn1CoderRelease(coder
);
201 if(revokedCert
.revocationDate
.item
.Data
) {
202 CSSM_FREE(revokedCert
.revocationDate
.item
.Data
);
204 if(tbsCrl
.thisUpdate
.item
.Data
) {
205 CSSM_FREE(tbsCrl
.thisUpdate
.item
.Data
);
207 if(revokedCert
.revocationDate
.item
.Data
) {
208 CSSM_FREE(tbsCrl
.nextUpdate
.item
.Data
);
213 int main(int argc
, char **argv
)
215 char *subjectName
= NULL
;
216 char *issuerName
= NULL
;
217 char *outFileName
= NULL
;
219 int revokeTime
= REVOKE_TIME_DEF
;
220 int thisUpdate
= THIS_UPDATE_DEF
;
221 int nextUpdate
= NEXT_UPDATE_DEF
;
225 while ((arg
= getopt(argc
, argv
, "s:i:o:k:r:t:n:h")) != -1) {
228 subjectName
= optarg
;
234 outFileName
= optarg
;
240 revokeTime
= atoi(optarg
);
243 thisUpdate
= atoi(optarg
);
246 nextUpdate
= atoi(optarg
);
256 if((subjectName
== NULL
) || (issuerName
== NULL
) || (outFileName
== NULL
)) {
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
);
269 if(readFile(issuerName
, &issuerCert
, &issuerCertLen
)) {
270 printf("***Error reading %s. \n", issuerName
);
274 /* get issuer identity and signing key */
275 SecKeychainRef kcRef
= NULL
;
278 ortn
= SecKeychainOpen(kcName
, &kcRef
);
280 cssmPerror("SecKeychainOpen", ortn
);
284 SecCertificateRef certRef
= NULL
;
285 SecIdentityRef idRef
= NULL
;
286 SecKeyRef signingKey
= NULL
;
287 CSSM_DATA issuerCData
= {issuerCertLen
, (uint8
*)issuerCert
};
288 ortn
= SecCertificateCreateFromData(&issuerCData
,
290 CSSM_CERT_ENCODING_DER
,
293 cssmPerror("SecCertificateCreateFromData", ortn
);
296 ortn
= SecIdentityCreateWithCertificate(kcRef
, certRef
, &idRef
);
298 cssmPerror("SecIdentityCreateWithCertificate", ortn
);
301 ortn
= SecIdentityCopyPrivateKey(idRef
, &signingKey
);
303 cssmPerror("SecIdentityCopyPrivateKey", ortn
);
307 /* create and sign the CRL */
308 unsigned char *crlOut
= NULL
;
309 unsigned crlOutLen
= 0;
310 if(makeCrl(subjectCert
, subjectCertLen
,
312 revokeTime
, thisUpdate
, nextUpdate
,
313 &crlOut
, &crlOutLen
)) {
314 printf("***Error creating CRL. Aborting.\n");
319 if(writeFile(outFileName
, crlOut
, crlOutLen
)) {
320 printf("***Error writing CRL to %s\n", outFileName
);
323 printf("...wrote %u bytes to %s.\n", crlOutLen
, outFileName
);
325 /* cleanup if you must */