|
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 * pkix_defaultcrlchecker.c |
|
6 * |
|
7 * Functions for default CRL Checkers |
|
8 * |
|
9 */ |
|
10 #include "pkix.h" |
|
11 #include "pkix_crlchecker.h" |
|
12 #include "pkix_tools.h" |
|
13 |
|
14 /* --Private-CRLChecker-Data-and-Types------------------------------- */ |
|
15 |
|
16 typedef struct pkix_CrlCheckerStruct { |
|
17 /* RevocationMethod is the super class of CrlChecker. */ |
|
18 pkix_RevocationMethod method; |
|
19 PKIX_List *certStores; /* list of CertStore */ |
|
20 PKIX_PL_VerifyCallback crlVerifyFn; |
|
21 } pkix_CrlChecker; |
|
22 |
|
23 |
|
24 /* --Private-CRLChecker-Functions----------------------------------- */ |
|
25 |
|
26 /* |
|
27 * FUNCTION: pkix_CrlCheckerstate_Destroy |
|
28 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
|
29 */ |
|
30 static PKIX_Error * |
|
31 pkix_CrlChecker_Destroy( |
|
32 PKIX_PL_Object *object, |
|
33 void *plContext) |
|
34 { |
|
35 pkix_CrlChecker *state = NULL; |
|
36 |
|
37 PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy"); |
|
38 PKIX_NULLCHECK_ONE(object); |
|
39 |
|
40 /* Check that this object is a default CRL checker state */ |
|
41 PKIX_CHECK( |
|
42 pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext), |
|
43 PKIX_OBJECTNOTCRLCHECKER); |
|
44 |
|
45 state = (pkix_CrlChecker *)object; |
|
46 |
|
47 PKIX_DECREF(state->certStores); |
|
48 |
|
49 cleanup: |
|
50 |
|
51 PKIX_RETURN(CRLCHECKER); |
|
52 } |
|
53 |
|
54 /* |
|
55 * FUNCTION: pkix_CrlChecker_RegisterSelf |
|
56 * |
|
57 * DESCRIPTION: |
|
58 * Registers PKIX_CRLCHECKER_TYPE and its related functions |
|
59 * with systemClasses[] |
|
60 * |
|
61 * THREAD SAFETY: |
|
62 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
|
63 * |
|
64 * Since this function is only called by PKIX_PL_Initialize, which should |
|
65 * only be called once, it is acceptable that this function is not |
|
66 * thread-safe. |
|
67 */ |
|
68 PKIX_Error * |
|
69 pkix_CrlChecker_RegisterSelf(void *plContext) |
|
70 { |
|
71 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
|
72 pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE]; |
|
73 |
|
74 PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf"); |
|
75 |
|
76 entry->description = "CRLChecker"; |
|
77 entry->typeObjectSize = sizeof(pkix_CrlChecker); |
|
78 entry->destructor = pkix_CrlChecker_Destroy; |
|
79 |
|
80 PKIX_RETURN(CRLCHECKER); |
|
81 } |
|
82 |
|
83 /* |
|
84 * FUNCTION: pkix_CrlChecker_Create |
|
85 * |
|
86 * DESCRIPTION: |
|
87 * Allocate and initialize CRLChecker state data. |
|
88 * |
|
89 * PARAMETERS |
|
90 * "certStores" |
|
91 * Address of CertStore List to be stored in state. Must be non-NULL. |
|
92 * "testDate" |
|
93 * Address of PKIX_PL_Date to be checked. May be NULL. |
|
94 * "trustedPubKey" |
|
95 * Trusted Anchor Public Key for verifying first Cert in the chain. |
|
96 * Must be non-NULL. |
|
97 * "certsRemaining" |
|
98 * Number of certificates remaining in the chain. |
|
99 * "nistCRLPolicyEnabled" |
|
100 * If enabled, enforce nist crl policy. |
|
101 * "pChecker" |
|
102 * Address of CRLChecker that is returned. Must be non-NULL. |
|
103 * "plContext" |
|
104 * Platform-specific context pointer. |
|
105 * |
|
106 * THREAD SAFETY: |
|
107 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
|
108 * |
|
109 * RETURNS: |
|
110 * Returns NULL if the function succeeds. |
|
111 * Returns a DefaultCrlChecker Error if the function fails in a |
|
112 * non-fatal way. |
|
113 * Returns a Fatal Error |
|
114 */ |
|
115 PKIX_Error * |
|
116 pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType, |
|
117 PKIX_UInt32 flags, |
|
118 PKIX_UInt32 priority, |
|
119 pkix_LocalRevocationCheckFn localRevChecker, |
|
120 pkix_ExternalRevocationCheckFn externalRevChecker, |
|
121 PKIX_List *certStores, |
|
122 PKIX_PL_VerifyCallback crlVerifyFn, |
|
123 pkix_RevocationMethod **pChecker, |
|
124 void *plContext) |
|
125 { |
|
126 pkix_CrlChecker *crlChecker = NULL; |
|
127 |
|
128 PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create"); |
|
129 PKIX_NULLCHECK_TWO(certStores, pChecker); |
|
130 |
|
131 PKIX_CHECK(PKIX_PL_Object_Alloc |
|
132 (PKIX_CRLCHECKER_TYPE, |
|
133 sizeof (pkix_CrlChecker), |
|
134 (PKIX_PL_Object **)&crlChecker, |
|
135 plContext), |
|
136 PKIX_COULDNOTCREATECRLCHECKEROBJECT); |
|
137 |
|
138 pkixErrorResult = pkix_RevocationMethod_Init( |
|
139 (pkix_RevocationMethod*)crlChecker, methodType, flags, priority, |
|
140 localRevChecker, externalRevChecker, plContext); |
|
141 if (pkixErrorResult) { |
|
142 goto cleanup; |
|
143 } |
|
144 |
|
145 /* Initialize fields */ |
|
146 PKIX_INCREF(certStores); |
|
147 crlChecker->certStores = certStores; |
|
148 |
|
149 crlChecker->crlVerifyFn = crlVerifyFn; |
|
150 *pChecker = (pkix_RevocationMethod*)crlChecker; |
|
151 crlChecker = NULL; |
|
152 |
|
153 cleanup: |
|
154 PKIX_DECREF(crlChecker); |
|
155 |
|
156 PKIX_RETURN(CRLCHECKER); |
|
157 } |
|
158 |
|
159 /* --Private-CRLChecker-Functions------------------------------------ */ |
|
160 |
|
161 /* |
|
162 * FUNCTION: pkix_CrlChecker_CheckLocal |
|
163 * |
|
164 * DESCRIPTION: |
|
165 * Check if the Cert has been revoked based the CRLs data. This function |
|
166 * maintains the checker state to be current. |
|
167 * |
|
168 * PARAMETERS |
|
169 * "checker" |
|
170 * Address of CertChainChecker which has the state data. |
|
171 * Must be non-NULL. |
|
172 * "cert" |
|
173 * Address of Certificate that is to be validated. Must be non-NULL. |
|
174 * "unreslvdCrtExts" |
|
175 * A List OIDs. Not **yet** used in this checker function. |
|
176 * "plContext" |
|
177 * Platform-specific context pointer. |
|
178 * |
|
179 * THREAD SAFETY: |
|
180 * Not Thread Safe |
|
181 * (see Thread Safety Definitions in Programmer's Guide) |
|
182 * |
|
183 * RETURNS: |
|
184 * Returns NULL if the function succeeds. |
|
185 * Returns a CertChainChecker Error if the function fails in a non-fatal way. |
|
186 * Returns a Fatal Error |
|
187 */ |
|
188 PKIX_Error * |
|
189 pkix_CrlChecker_CheckLocal( |
|
190 PKIX_PL_Cert *cert, |
|
191 PKIX_PL_Cert *issuer, |
|
192 PKIX_PL_Date *date, |
|
193 pkix_RevocationMethod *checkerObject, |
|
194 PKIX_ProcessingParams *procParams, |
|
195 PKIX_UInt32 methodFlags, |
|
196 PKIX_Boolean chainVerificationState, |
|
197 PKIX_RevocationStatus *pRevStatus, |
|
198 PKIX_UInt32 *pReasonCode, |
|
199 void *plContext) |
|
200 { |
|
201 PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn; |
|
202 PKIX_CertStore *certStore = NULL; |
|
203 pkix_CrlChecker *state = NULL; |
|
204 PKIX_UInt32 crlStoreIndex = 0; |
|
205 PKIX_UInt32 numCrlStores = 0; |
|
206 PKIX_Boolean storeIsLocal = PKIX_FALSE; |
|
207 PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; |
|
208 |
|
209 PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal"); |
|
210 PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject); |
|
211 |
|
212 state = (pkix_CrlChecker*)checkerObject; |
|
213 |
|
214 PKIX_CHECK( |
|
215 PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), |
|
216 PKIX_LISTGETLENGTHFAILED); |
|
217 |
|
218 for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { |
|
219 PKIX_CHECK( |
|
220 PKIX_List_GetItem(state->certStores, crlStoreIndex, |
|
221 (PKIX_PL_Object **)&certStore, |
|
222 plContext), |
|
223 PKIX_LISTGETITEMFAILED); |
|
224 |
|
225 PKIX_CHECK( |
|
226 PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, |
|
227 plContext), |
|
228 PKIX_CERTSTOREGETLOCALFLAGFAILED); |
|
229 if (storeIsLocal) { |
|
230 PKIX_CHECK( |
|
231 PKIX_CertStore_GetCrlCheckerFn(certStore, |
|
232 &storeCheckRevocationFn, |
|
233 plContext), |
|
234 PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); |
|
235 |
|
236 if (storeCheckRevocationFn) { |
|
237 PKIX_CHECK( |
|
238 (*storeCheckRevocationFn)(certStore, cert, issuer, |
|
239 /* delay sig check if building |
|
240 * a chain by not specifying the time*/ |
|
241 chainVerificationState ? date : NULL, |
|
242 /* crl downloading is not done. */ |
|
243 PKIX_FALSE, |
|
244 pReasonCode, &revStatus, plContext), |
|
245 PKIX_CERTSTORECRLCHECKFAILED); |
|
246 if (revStatus == PKIX_RevStatus_Revoked) { |
|
247 break; |
|
248 } |
|
249 } |
|
250 } |
|
251 PKIX_DECREF(certStore); |
|
252 } /* while */ |
|
253 |
|
254 cleanup: |
|
255 *pRevStatus = revStatus; |
|
256 PKIX_DECREF(certStore); |
|
257 |
|
258 PKIX_RETURN(CERTCHAINCHECKER); |
|
259 } |
|
260 |
|
261 /* |
|
262 * FUNCTION: pkix_CrlChecker_CheckRemote |
|
263 * |
|
264 * DESCRIPTION: |
|
265 * Check if the Cert has been revoked based the CRLs data. This function |
|
266 * maintains the checker state to be current. |
|
267 * |
|
268 * PARAMETERS |
|
269 * "checker" |
|
270 * Address of CertChainChecker which has the state data. |
|
271 * Must be non-NULL. |
|
272 * "cert" |
|
273 * Address of Certificate that is to be validated. Must be non-NULL. |
|
274 * "unreslvdCrtExts" |
|
275 * A List OIDs. Not **yet** used in this checker function. |
|
276 * "plContext" |
|
277 * Platform-specific context pointer. |
|
278 * |
|
279 * THREAD SAFETY: |
|
280 * Not Thread Safe |
|
281 * (see Thread Safety Definitions in Programmer's Guide) |
|
282 * |
|
283 * RETURNS: |
|
284 * Returns NULL if the function succeeds. |
|
285 * Returns a CertChainChecker Error if the function fails in a non-fatal way. |
|
286 * Returns a Fatal Error |
|
287 */ |
|
288 PKIX_Error * |
|
289 pkix_CrlChecker_CheckExternal( |
|
290 PKIX_PL_Cert *cert, |
|
291 PKIX_PL_Cert *issuer, |
|
292 PKIX_PL_Date *date, |
|
293 pkix_RevocationMethod *checkerObject, |
|
294 PKIX_ProcessingParams *procParams, |
|
295 PKIX_UInt32 methodFlags, |
|
296 PKIX_RevocationStatus *pRevStatus, |
|
297 PKIX_UInt32 *pReasonCode, |
|
298 void **pNBIOContext, |
|
299 void *plContext) |
|
300 { |
|
301 PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL; |
|
302 PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL; |
|
303 PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; |
|
304 PKIX_CertStore *certStore = NULL; |
|
305 PKIX_CertStore *localStore = NULL; |
|
306 PKIX_CRLSelector *crlSelector = NULL; |
|
307 PKIX_PL_X500Name *issuerName = NULL; |
|
308 pkix_CrlChecker *state = NULL; |
|
309 PKIX_UInt32 crlStoreIndex = 0; |
|
310 PKIX_UInt32 numCrlStores = 0; |
|
311 PKIX_Boolean storeIsLocal = PKIX_FALSE; |
|
312 PKIX_List *crlList = NULL; |
|
313 PKIX_List *dpList = NULL; |
|
314 void *nbioContext = NULL; |
|
315 |
|
316 PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal"); |
|
317 PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext); |
|
318 |
|
319 nbioContext = *pNBIOContext; |
|
320 *pNBIOContext = NULL; /* prepare for Error exit */ |
|
321 |
|
322 state = (pkix_CrlChecker*)checkerObject; |
|
323 |
|
324 PKIX_CHECK( |
|
325 PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), |
|
326 PKIX_LISTGETLENGTHFAILED); |
|
327 |
|
328 /* Find a cert store that is capable of storing crls */ |
|
329 for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { |
|
330 PKIX_CHECK( |
|
331 PKIX_List_GetItem(state->certStores, crlStoreIndex, |
|
332 (PKIX_PL_Object **)&certStore, |
|
333 plContext), |
|
334 PKIX_LISTGETITEMFAILED); |
|
335 |
|
336 PKIX_CHECK( |
|
337 PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, |
|
338 plContext), |
|
339 PKIX_CERTSTOREGETLOCALFLAGFAILED); |
|
340 if (storeIsLocal) { |
|
341 PKIX_CHECK( |
|
342 PKIX_CertStore_GetImportCrlCallback(certStore, |
|
343 &storeImportCrlFn, |
|
344 plContext), |
|
345 PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); |
|
346 |
|
347 PKIX_CHECK( |
|
348 PKIX_CertStore_GetCrlCheckerFn(certStore, |
|
349 &storeCheckRevocationFn, |
|
350 plContext), |
|
351 PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); |
|
352 |
|
353 if (storeImportCrlFn && storeCheckRevocationFn) { |
|
354 localStore = certStore; |
|
355 certStore = NULL; |
|
356 break; |
|
357 } |
|
358 } |
|
359 PKIX_DECREF(certStore); |
|
360 } /* while */ |
|
361 |
|
362 /* Report unknown status if we can not check crl in one of the |
|
363 * local stores. */ |
|
364 if (!localStore) { |
|
365 PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND); |
|
366 } |
|
367 PKIX_CHECK( |
|
368 PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext), |
|
369 PKIX_CERTCHECKKEYUSAGEFAILED); |
|
370 PKIX_CHECK( |
|
371 PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext), |
|
372 PKIX_CERTGETCRLDPFAILED); |
|
373 if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) && |
|
374 (!dpList || !dpList->length)) { |
|
375 goto cleanup; |
|
376 } |
|
377 PKIX_CHECK( |
|
378 PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext), |
|
379 PKIX_CERTGETISSUERFAILED); |
|
380 PKIX_CHECK( |
|
381 PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext), |
|
382 PKIX_CRLCHECKERSETSELECTORFAILED); |
|
383 /* Fetch crl and store in a local cert store */ |
|
384 for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) { |
|
385 PKIX_CertStore_CRLCallback getCrlsFn; |
|
386 |
|
387 PKIX_CHECK( |
|
388 PKIX_List_GetItem(state->certStores, crlStoreIndex, |
|
389 (PKIX_PL_Object **)&certStore, |
|
390 plContext), |
|
391 PKIX_LISTGETITEMFAILED); |
|
392 |
|
393 PKIX_CHECK( |
|
394 PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn, |
|
395 plContext), |
|
396 PKIX_CERTSTOREGETCRLCALLBACKFAILED); |
|
397 |
|
398 PKIX_CHECK( |
|
399 (*getCrlsFn)(certStore, crlSelector, &nbioContext, |
|
400 &crlList, plContext), |
|
401 PKIX_GETCRLSFAILED); |
|
402 |
|
403 PKIX_CHECK( |
|
404 (*storeImportCrlFn)(localStore, issuerName, crlList, plContext), |
|
405 PKIX_CERTSTOREFAILTOIMPORTCRLLIST); |
|
406 |
|
407 PKIX_CHECK( |
|
408 (*storeCheckRevocationFn)(certStore, cert, issuer, date, |
|
409 /* done with crl downloading */ |
|
410 PKIX_TRUE, |
|
411 pReasonCode, &revStatus, plContext), |
|
412 PKIX_CERTSTORECRLCHECKFAILED); |
|
413 if (revStatus != PKIX_RevStatus_NoInfo) { |
|
414 break; |
|
415 } |
|
416 PKIX_DECREF(crlList); |
|
417 PKIX_DECREF(certStore); |
|
418 } /* while */ |
|
419 |
|
420 cleanup: |
|
421 /* Update return flags */ |
|
422 if (revStatus == PKIX_RevStatus_NoInfo && |
|
423 ((dpList && dpList->length > 0) || |
|
424 (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) && |
|
425 methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) { |
|
426 revStatus = PKIX_RevStatus_Revoked; |
|
427 } |
|
428 *pRevStatus = revStatus; |
|
429 |
|
430 PKIX_DECREF(dpList); |
|
431 PKIX_DECREF(crlList); |
|
432 PKIX_DECREF(certStore); |
|
433 PKIX_DECREF(issuerName); |
|
434 PKIX_DECREF(localStore); |
|
435 PKIX_DECREF(crlSelector); |
|
436 |
|
437 PKIX_RETURN(CERTCHAINCHECKER); |
|
438 } |