|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /* |
|
6 * ocspresp - self test for OCSP response creation |
|
7 */ |
|
8 |
|
9 #include "nspr.h" |
|
10 #include "secutil.h" |
|
11 #include "secpkcs7.h" |
|
12 #include "cert.h" |
|
13 #include "certdb.h" |
|
14 #include "nss.h" |
|
15 #include "pk11func.h" |
|
16 #include "cryptohi.h" |
|
17 #include "ocsp.h" |
|
18 |
|
19 #if defined(XP_UNIX) |
|
20 #include <unistd.h> |
|
21 #endif |
|
22 |
|
23 #include <stdio.h> |
|
24 #include <string.h> |
|
25 |
|
26 secuPWData pwdata = { PW_NONE, 0 }; |
|
27 |
|
28 static PRBool |
|
29 getCaAndSubjectCert(CERTCertDBHandle *certHandle, |
|
30 const char *caNick, const char *eeNick, |
|
31 CERTCertificate **outCA, CERTCertificate **outCert) |
|
32 { |
|
33 *outCA = CERT_FindCertByNickname(certHandle, caNick); |
|
34 *outCert = CERT_FindCertByNickname(certHandle, eeNick); |
|
35 return *outCA && *outCert; |
|
36 } |
|
37 |
|
38 static SECItem * |
|
39 encode(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca) |
|
40 { |
|
41 SECItem *response; |
|
42 PRTime now = PR_Now(); |
|
43 PRTime nextUpdate; |
|
44 CERTOCSPSingleResponse **responses; |
|
45 CERTOCSPSingleResponse *sr; |
|
46 |
|
47 if (!arena) |
|
48 return NULL; |
|
49 |
|
50 nextUpdate = now + 10 * PR_USEC_PER_SEC; /* in the future */ |
|
51 |
|
52 sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, &nextUpdate); |
|
53 |
|
54 /* meaning of value 2: one entry + one end marker */ |
|
55 responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse*, 2); |
|
56 if (responses == NULL) |
|
57 return NULL; |
|
58 |
|
59 responses[0] = sr; |
|
60 responses[1] = NULL; |
|
61 |
|
62 response = CERT_CreateEncodedOCSPSuccessResponse( |
|
63 arena, ca, ocspResponderID_byName, now, responses, &pwdata); |
|
64 |
|
65 return response; |
|
66 } |
|
67 |
|
68 static SECItem * |
|
69 encodeRevoked(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca) |
|
70 { |
|
71 SECItem *response; |
|
72 PRTime now = PR_Now(); |
|
73 PRTime revocationTime; |
|
74 CERTOCSPSingleResponse **responses; |
|
75 CERTOCSPSingleResponse *sr; |
|
76 |
|
77 if (!arena) |
|
78 return NULL; |
|
79 |
|
80 revocationTime = now - 10 * PR_USEC_PER_SEC; /* in the past */ |
|
81 |
|
82 sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, NULL, |
|
83 revocationTime, NULL); |
|
84 |
|
85 /* meaning of value 2: one entry + one end marker */ |
|
86 responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse*, 2); |
|
87 if (responses == NULL) |
|
88 return NULL; |
|
89 |
|
90 responses[0] = sr; |
|
91 responses[1] = NULL; |
|
92 |
|
93 response = CERT_CreateEncodedOCSPSuccessResponse( |
|
94 arena, ca, ocspResponderID_byName, now, responses, &pwdata); |
|
95 |
|
96 return response; |
|
97 } |
|
98 |
|
99 int Usage(void) |
|
100 { |
|
101 PRFileDesc *pr_stderr = PR_STDERR; |
|
102 PR_fprintf (pr_stderr, "ocspresp runs an internal selftest for OCSP response creation"); |
|
103 PR_fprintf (pr_stderr, "Usage:"); |
|
104 PR_fprintf (pr_stderr, |
|
105 "\tocspresp <dbdir> <CA-nick> <EE-nick> [-p <pass>] [-f <file>]\n"); |
|
106 PR_fprintf (pr_stderr, |
|
107 "\tdbdir: Find security databases in \"dbdir\"\n"); |
|
108 PR_fprintf (pr_stderr, |
|
109 "\tCA-nick: nickname of a trusted CA certificate with private key\n"); |
|
110 PR_fprintf (pr_stderr, |
|
111 "\tEE-nick: nickname of a entity cert issued by CA\n"); |
|
112 PR_fprintf (pr_stderr, |
|
113 "\t-p: a password for db\n"); |
|
114 PR_fprintf (pr_stderr, |
|
115 "\t-f: a filename containing the password for db\n"); |
|
116 return -1; |
|
117 } |
|
118 |
|
119 int |
|
120 main(int argc, char **argv) |
|
121 { |
|
122 SECStatus rv; |
|
123 int retval = -1; |
|
124 CERTCertDBHandle *certHandle = NULL; |
|
125 CERTCertificate *caCert = NULL, *cert = NULL; |
|
126 CERTOCSPCertID *cid = NULL; |
|
127 PLArenaPool *arena = NULL; |
|
128 PRTime now = PR_Now(); |
|
129 |
|
130 SECItem *encoded = NULL; |
|
131 CERTOCSPResponse *decoded = NULL; |
|
132 SECStatus statusDecoded; |
|
133 |
|
134 SECItem *encodedRev = NULL; |
|
135 CERTOCSPResponse *decodedRev = NULL; |
|
136 SECStatus statusDecodedRev; |
|
137 |
|
138 SECItem *encodedFail = NULL; |
|
139 CERTOCSPResponse *decodedFail = NULL; |
|
140 SECStatus statusDecodedFail; |
|
141 |
|
142 CERTCertificate *obtainedSignerCert = NULL; |
|
143 |
|
144 if (argc != 4 && argc != 6) { |
|
145 return Usage(); |
|
146 } |
|
147 |
|
148 if (argc == 6) { |
|
149 if (!strcmp(argv[4], "-p")) { |
|
150 pwdata.source = PW_PLAINTEXT; |
|
151 pwdata.data = PORT_Strdup(argv[5]); |
|
152 } |
|
153 else if (!strcmp(argv[4], "-f")) { |
|
154 pwdata.source = PW_FROMFILE; |
|
155 pwdata.data = PORT_Strdup(argv[5]); |
|
156 } |
|
157 else |
|
158 return Usage(); |
|
159 } |
|
160 |
|
161 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
|
162 /*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/ |
|
163 rv = NSS_Init(argv[1]); |
|
164 if (rv != SECSuccess) { |
|
165 SECU_PrintPRandOSError(argv[0]); |
|
166 goto loser; |
|
167 } |
|
168 |
|
169 PK11_SetPasswordFunc(SECU_GetModulePassword); |
|
170 |
|
171 certHandle = CERT_GetDefaultCertDB(); |
|
172 if (!certHandle) |
|
173 goto loser; |
|
174 |
|
175 if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert)) |
|
176 goto loser; |
|
177 |
|
178 cid = CERT_CreateOCSPCertID(cert, now); |
|
179 |
|
180 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
181 encoded = encode(arena, cid, caCert); |
|
182 PORT_Assert(encoded); |
|
183 decoded = CERT_DecodeOCSPResponse(encoded); |
|
184 statusDecoded = CERT_GetOCSPResponseStatus(decoded); |
|
185 PORT_Assert(statusDecoded == SECSuccess); |
|
186 |
|
187 statusDecoded = CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata, |
|
188 &obtainedSignerCert, caCert); |
|
189 PORT_Assert(statusDecoded == SECSuccess); |
|
190 statusDecoded = CERT_GetOCSPStatusForCertID(certHandle, decoded, cid, |
|
191 obtainedSignerCert, now); |
|
192 PORT_Assert(statusDecoded == SECSuccess); |
|
193 CERT_DestroyCertificate(obtainedSignerCert); |
|
194 |
|
195 encodedRev = encodeRevoked(arena, cid, caCert); |
|
196 PORT_Assert(encodedRev); |
|
197 decodedRev = CERT_DecodeOCSPResponse(encodedRev); |
|
198 statusDecodedRev = CERT_GetOCSPResponseStatus(decodedRev); |
|
199 PORT_Assert(statusDecodedRev == SECSuccess); |
|
200 |
|
201 statusDecodedRev = CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata, |
|
202 &obtainedSignerCert, caCert); |
|
203 PORT_Assert(statusDecodedRev == SECSuccess); |
|
204 statusDecodedRev = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid, |
|
205 obtainedSignerCert, now); |
|
206 PORT_Assert(statusDecodedRev == SECFailure); |
|
207 PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE); |
|
208 CERT_DestroyCertificate(obtainedSignerCert); |
|
209 |
|
210 encodedFail = CERT_CreateEncodedOCSPErrorResponse( |
|
211 arena, SEC_ERROR_OCSP_TRY_SERVER_LATER); |
|
212 PORT_Assert(encodedFail); |
|
213 decodedFail = CERT_DecodeOCSPResponse(encodedFail); |
|
214 statusDecodedFail = CERT_GetOCSPResponseStatus(decodedFail); |
|
215 PORT_Assert(statusDecodedFail == SECFailure); |
|
216 PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER); |
|
217 |
|
218 retval = 0; |
|
219 loser: |
|
220 if (retval != 0) |
|
221 SECU_PrintError(argv[0], "tests failed"); |
|
222 |
|
223 if (cid) |
|
224 CERT_DestroyOCSPCertID(cid); |
|
225 if (cert) |
|
226 CERT_DestroyCertificate(cert); |
|
227 if (caCert) |
|
228 CERT_DestroyCertificate(caCert); |
|
229 if (arena) |
|
230 PORT_FreeArena(arena, PR_FALSE); |
|
231 if (decoded) |
|
232 CERT_DestroyOCSPResponse(decoded); |
|
233 if (decodedRev) |
|
234 CERT_DestroyOCSPResponse(decodedRev); |
|
235 if (decodedFail) |
|
236 CERT_DestroyOCSPResponse(decodedFail); |
|
237 if (pwdata.data) { |
|
238 PORT_Free(pwdata.data); |
|
239 } |
|
240 |
|
241 if (NSS_Shutdown() != SECSuccess) { |
|
242 SECU_PrintError(argv[0], "NSS shutdown:"); |
|
243 if (retval == 0) |
|
244 retval = -2; |
|
245 } |
|
246 |
|
247 return retval; |
|
248 } |