OLD | NEW |
| (Empty) |
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_build.c | |
6 * | |
7 * Top level buildChain function | |
8 * | |
9 */ | |
10 | |
11 /* #define PKIX_BUILDDEBUG 1 */ | |
12 /* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */ | |
13 | |
14 #include "pkix_build.h" | |
15 | |
16 extern PRLogModuleInfo *pkixLog; | |
17 | |
18 /* | |
19 * List of critical extension OIDs associate with what build chain has | |
20 * checked. Those OIDs need to be removed from the unresolved critical | |
21 * extension OIDs list manually (instead of by checker automatically). | |
22 */ | |
23 static SECOidTag buildCheckedCritExtOIDs[] = { | |
24 PKIX_CERTKEYUSAGE_OID, | |
25 PKIX_CERTSUBJALTNAME_OID, | |
26 PKIX_BASICCONSTRAINTS_OID, | |
27 PKIX_NAMECONSTRAINTS_OID, | |
28 PKIX_EXTENDEDKEYUSAGE_OID, | |
29 PKIX_NSCERTTYPE_OID, | |
30 PKIX_UNKNOWN_OID | |
31 }; | |
32 | |
33 /* --Private-ForwardBuilderState-Functions---------------------------------- */ | |
34 | |
35 /* | |
36 * FUNCTION: pkix_ForwardBuilderState_Destroy | |
37 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
38 */ | |
39 static PKIX_Error * | |
40 pkix_ForwardBuilderState_Destroy( | |
41 PKIX_PL_Object *object, | |
42 void *plContext) | |
43 { | |
44 PKIX_ForwardBuilderState *state = NULL; | |
45 | |
46 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy"); | |
47 PKIX_NULLCHECK_ONE(object); | |
48 | |
49 PKIX_CHECK(pkix_CheckType | |
50 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), | |
51 PKIX_OBJECTNOTFORWARDBUILDERSTATE); | |
52 | |
53 state = (PKIX_ForwardBuilderState *)object; | |
54 | |
55 state->status = BUILD_INITIAL; | |
56 state->traversedCACerts = 0; | |
57 state->certStoreIndex = 0; | |
58 state->numCerts = 0; | |
59 state->numAias = 0; | |
60 state->certIndex = 0; | |
61 state->aiaIndex = 0; | |
62 state->certCheckedIndex = 0; | |
63 state->checkerIndex = 0; | |
64 state->hintCertIndex = 0; | |
65 state->numFanout = 0; | |
66 state->numDepth = 0; | |
67 state->reasonCode = 0; | |
68 state->revCheckDelayed = PKIX_FALSE; | |
69 state->canBeCached = PKIX_FALSE; | |
70 state->useOnlyLocal = PKIX_FALSE; | |
71 state->revChecking = PKIX_FALSE; | |
72 state->usingHintCerts = PKIX_FALSE; | |
73 state->certLoopingDetected = PKIX_FALSE; | |
74 PKIX_DECREF(state->validityDate); | |
75 PKIX_DECREF(state->prevCert); | |
76 PKIX_DECREF(state->candidateCert); | |
77 PKIX_DECREF(state->traversedSubjNames); | |
78 PKIX_DECREF(state->trustChain); | |
79 PKIX_DECREF(state->aia); | |
80 PKIX_DECREF(state->candidateCerts); | |
81 PKIX_DECREF(state->reversedCertChain); | |
82 PKIX_DECREF(state->checkedCritExtOIDs); | |
83 PKIX_DECREF(state->checkerChain); | |
84 PKIX_DECREF(state->certSel); | |
85 PKIX_DECREF(state->verifyNode); | |
86 PKIX_DECREF(state->client); | |
87 | |
88 /* | |
89 * If we ever add a child link we have to be careful not to have loops | |
90 * in the Destroy process. But with one-way links we should be okay. | |
91 */ | |
92 if (state->parentState == NULL) { | |
93 state->buildConstants.numAnchors = 0; | |
94 state->buildConstants.numCertStores = 0; | |
95 state->buildConstants.numHintCerts = 0; | |
96 state->buildConstants.procParams = 0; | |
97 PKIX_DECREF(state->buildConstants.testDate); | |
98 PKIX_DECREF(state->buildConstants.timeLimit); | |
99 PKIX_DECREF(state->buildConstants.targetCert); | |
100 PKIX_DECREF(state->buildConstants.targetPubKey); | |
101 PKIX_DECREF(state->buildConstants.certStores); | |
102 PKIX_DECREF(state->buildConstants.anchors); | |
103 PKIX_DECREF(state->buildConstants.userCheckers); | |
104 PKIX_DECREF(state->buildConstants.hintCerts); | |
105 PKIX_DECREF(state->buildConstants.revChecker); | |
106 PKIX_DECREF(state->buildConstants.aiaMgr); | |
107 } else { | |
108 PKIX_DECREF(state->parentState); | |
109 } | |
110 | |
111 cleanup: | |
112 | |
113 PKIX_RETURN(FORWARDBUILDERSTATE); | |
114 } | |
115 | |
116 /* | |
117 * FUNCTION: pkix_ForwardBuilderState_Create | |
118 * | |
119 * DESCRIPTION: | |
120 * Allocate and initialize a ForwardBuilderState. | |
121 * | |
122 * PARAMETERS | |
123 * "traversedCACerts" | |
124 * Number of CA certificates traversed. | |
125 * "numFanout" | |
126 * Number of Certs that can be considered at this level (0 = no limit) | |
127 * "numDepth" | |
128 * Number of additional levels that can be searched (0 = no limit) | |
129 * "revCheckDelayed" | |
130 * Boolean value indicating whether rev check is delayed until after | |
131 * entire chain is built. | |
132 * "canBeCached" | |
133 * Boolean value indicating whether all certs on the chain can be cached. | |
134 * "validityDate" | |
135 * Address of Date at which build chain Certs' most restricted validity | |
136 * time is kept. May be NULL. | |
137 * "prevCert" | |
138 * Address of Cert just traversed. Must be non-NULL. | |
139 * "traversedSubjNames" | |
140 * Address of List of GeneralNames that have been traversed. | |
141 * Must be non-NULL. | |
142 * "trustChain" | |
143 * Address of List of certificates traversed. Must be non-NULL. | |
144 * "parentState" | |
145 * Address of previous ForwardBuilderState | |
146 * "pState" | |
147 * Address where ForwardBuilderState will be stored. Must be non-NULL. | |
148 * "plContext" | |
149 * Platform-specific context pointer. | |
150 * THREAD SAFETY: | |
151 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
152 * RETURNS: | |
153 * Returns NULL if the function succeeds. | |
154 * Returns a Build Error if the function fails in a non-fatal way. | |
155 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
156 */ | |
157 static PKIX_Error * | |
158 pkix_ForwardBuilderState_Create( | |
159 PKIX_Int32 traversedCACerts, | |
160 PKIX_UInt32 numFanout, | |
161 PKIX_UInt32 numDepth, | |
162 PKIX_Boolean revCheckDelayed, | |
163 PKIX_Boolean canBeCached, | |
164 PKIX_PL_Date *validityDate, | |
165 PKIX_PL_Cert *prevCert, | |
166 PKIX_List *traversedSubjNames, | |
167 PKIX_List *trustChain, | |
168 PKIX_ForwardBuilderState *parentState, | |
169 PKIX_ForwardBuilderState **pState, | |
170 void *plContext) | |
171 { | |
172 PKIX_ForwardBuilderState *state = NULL; | |
173 | |
174 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create"); | |
175 PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain); | |
176 | |
177 PKIX_CHECK(PKIX_PL_Object_Alloc | |
178 (PKIX_FORWARDBUILDERSTATE_TYPE, | |
179 sizeof (PKIX_ForwardBuilderState), | |
180 (PKIX_PL_Object **)&state, | |
181 plContext), | |
182 PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT); | |
183 | |
184 state->status = BUILD_INITIAL; | |
185 state->traversedCACerts = traversedCACerts; | |
186 state->certStoreIndex = 0; | |
187 state->numCerts = 0; | |
188 state->numAias = 0; | |
189 state->certIndex = 0; | |
190 state->aiaIndex = 0; | |
191 state->certCheckedIndex = 0; | |
192 state->checkerIndex = 0; | |
193 state->hintCertIndex = 0; | |
194 state->numFanout = numFanout; | |
195 state->numDepth = numDepth; | |
196 state->reasonCode = 0; | |
197 state->revChecking = numDepth; | |
198 state->revCheckDelayed = revCheckDelayed; | |
199 state->canBeCached = canBeCached; | |
200 state->useOnlyLocal = PKIX_TRUE; | |
201 state->revChecking = PKIX_FALSE; | |
202 state->usingHintCerts = PKIX_FALSE; | |
203 state->certLoopingDetected = PKIX_FALSE; | |
204 | |
205 PKIX_INCREF(validityDate); | |
206 state->validityDate = validityDate; | |
207 | |
208 PKIX_INCREF(prevCert); | |
209 state->prevCert = prevCert; | |
210 | |
211 state->candidateCert = NULL; | |
212 | |
213 PKIX_INCREF(traversedSubjNames); | |
214 state->traversedSubjNames = traversedSubjNames; | |
215 | |
216 PKIX_INCREF(trustChain); | |
217 state->trustChain = trustChain; | |
218 | |
219 state->aia = NULL; | |
220 state->candidateCerts = NULL; | |
221 state->reversedCertChain = NULL; | |
222 state->checkedCritExtOIDs = NULL; | |
223 state->checkerChain = NULL; | |
224 state->certSel = NULL; | |
225 state->verifyNode = NULL; | |
226 state->client = NULL; | |
227 | |
228 PKIX_INCREF(parentState); | |
229 state->parentState = parentState; | |
230 | |
231 if (parentState != NULL) { | |
232 state->buildConstants.numAnchors = | |
233 parentState->buildConstants.numAnchors; | |
234 state->buildConstants.numCertStores = | |
235 parentState->buildConstants.numCertStores; | |
236 state->buildConstants.numHintCerts = | |
237 parentState->buildConstants.numHintCerts; | |
238 state->buildConstants.maxFanout = | |
239 parentState->buildConstants.maxFanout; | |
240 state->buildConstants.maxDepth = | |
241 parentState->buildConstants.maxDepth; | |
242 state->buildConstants.maxTime = | |
243 parentState->buildConstants.maxTime; | |
244 state->buildConstants.procParams = | |
245 parentState->buildConstants.procParams; | |
246 state->buildConstants.testDate = | |
247 parentState->buildConstants.testDate; | |
248 state->buildConstants.timeLimit = | |
249 parentState->buildConstants.timeLimit; | |
250 state->buildConstants.targetCert = | |
251 parentState->buildConstants.targetCert; | |
252 state->buildConstants.targetPubKey = | |
253 parentState->buildConstants.targetPubKey; | |
254 state->buildConstants.certStores = | |
255 parentState->buildConstants.certStores; | |
256 state->buildConstants.anchors = | |
257 parentState->buildConstants.anchors; | |
258 state->buildConstants.userCheckers = | |
259 parentState->buildConstants.userCheckers; | |
260 state->buildConstants.hintCerts = | |
261 parentState->buildConstants.hintCerts; | |
262 state->buildConstants.revChecker = | |
263 parentState->buildConstants.revChecker; | |
264 state->buildConstants.aiaMgr = | |
265 parentState->buildConstants.aiaMgr; | |
266 state->buildConstants.trustOnlyUserAnchors = | |
267 parentState->buildConstants.trustOnlyUserAnchors; | |
268 } | |
269 | |
270 *pState = state; | |
271 state = NULL; | |
272 cleanup: | |
273 | |
274 PKIX_DECREF(state); | |
275 | |
276 PKIX_RETURN(FORWARDBUILDERSTATE); | |
277 } | |
278 | |
279 /* | |
280 * FUNCTION: pkix_Build_GetResourceLimits | |
281 * | |
282 * DESCRIPTION: | |
283 * Retrieve Resource Limits from ProcessingParams and initialize them in | |
284 * BuildConstants. | |
285 * | |
286 * PARAMETERS | |
287 * "buildConstants" | |
288 * Address of a BuildConstants structure containing objects and values | |
289 * that remain constant throughout the building of a chain. Must be | |
290 * non-NULL. | |
291 * "plContext" | |
292 * Platform-specific context pointer. | |
293 * THREAD SAFETY: | |
294 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
295 * RETURNS: | |
296 * Returns NULL if the function succeeds. | |
297 * Returns a Build Error if the function fails in a non-fatal way. | |
298 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
299 */ | |
300 static PKIX_Error * | |
301 pkix_Build_GetResourceLimits( | |
302 BuildConstants *buildConstants, | |
303 void *plContext) | |
304 { | |
305 PKIX_ResourceLimits *resourceLimits = NULL; | |
306 | |
307 PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits"); | |
308 PKIX_NULLCHECK_ONE(buildConstants); | |
309 | |
310 PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits | |
311 (buildConstants->procParams, &resourceLimits, plContext), | |
312 PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED); | |
313 | |
314 buildConstants->maxFanout = 0; | |
315 buildConstants->maxDepth = 0; | |
316 buildConstants->maxTime = 0; | |
317 | |
318 if (resourceLimits) { | |
319 | |
320 PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout | |
321 (resourceLimits, &buildConstants->maxFanout, plContext), | |
322 PKIX_RESOURCELIMITSGETMAXFANOUTFAILED); | |
323 | |
324 PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth | |
325 (resourceLimits, &buildConstants->maxDepth, plContext), | |
326 PKIX_RESOURCELIMITSGETMAXDEPTHFAILED); | |
327 | |
328 PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime | |
329 (resourceLimits, &buildConstants->maxTime, plContext), | |
330 PKIX_RESOURCELIMITSGETMAXTIMEFAILED); | |
331 } | |
332 | |
333 cleanup: | |
334 | |
335 PKIX_DECREF(resourceLimits); | |
336 | |
337 PKIX_RETURN(BUILD); | |
338 } | |
339 | |
340 /* | |
341 * FUNCTION: pkix_ForwardBuilderState_ToString | |
342 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
343 */ | |
344 static PKIX_Error * | |
345 pkix_ForwardBuilderState_ToString | |
346 (PKIX_PL_Object *object, | |
347 PKIX_PL_String **pString, | |
348 void *plContext) | |
349 { | |
350 PKIX_ForwardBuilderState *state = NULL; | |
351 PKIX_PL_String *formatString = NULL; | |
352 PKIX_PL_String *resultString = NULL; | |
353 PKIX_PL_String *buildStatusString = NULL; | |
354 PKIX_PL_String *validityDateString = NULL; | |
355 PKIX_PL_String *prevCertString = NULL; | |
356 PKIX_PL_String *candidateCertString = NULL; | |
357 PKIX_PL_String *traversedSubjNamesString = NULL; | |
358 PKIX_PL_String *trustChainString = NULL; | |
359 PKIX_PL_String *candidateCertsString = NULL; | |
360 PKIX_PL_String *certSelString = NULL; | |
361 PKIX_PL_String *verifyNodeString = NULL; | |
362 PKIX_PL_String *parentStateString = NULL; | |
363 char *asciiFormat = "\n" | |
364 "\t{buildStatus: \t%s\n" | |
365 "\ttraversedCACerts: \t%d\n" | |
366 "\tcertStoreIndex: \t%d\n" | |
367 "\tnumCerts: \t%d\n" | |
368 "\tnumAias: \t%d\n" | |
369 "\tcertIndex: \t%d\n" | |
370 "\taiaIndex: \t%d\n" | |
371 "\tnumFanout: \t%d\n" | |
372 "\tnumDepth: \t%d\n" | |
373 "\treasonCode: \t%d\n" | |
374 "\trevCheckDelayed: \t%d\n" | |
375 "\tcanBeCached: \t%d\n" | |
376 "\tuseOnlyLocal: \t%d\n" | |
377 "\trevChecking: \t%d\n" | |
378 "\tvalidityDate: \t%s\n" | |
379 "\tprevCert: \t%s\n" | |
380 "\tcandidateCert: \t%s\n" | |
381 "\ttraversedSubjNames: \t%s\n" | |
382 "\ttrustChain: \t%s\n" | |
383 "\tcandidateCerts: \t%s\n" | |
384 "\tcertSel: \t%s\n" | |
385 "\tverifyNode: \t%s\n" | |
386 "\tparentState: \t%s}\n"; | |
387 char *asciiStatus = NULL; | |
388 | |
389 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString"); | |
390 PKIX_NULLCHECK_TWO(object, pString); | |
391 | |
392 PKIX_CHECK(pkix_CheckType | |
393 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), | |
394 PKIX_OBJECTNOTFORWARDBUILDERSTATE); | |
395 | |
396 state = (PKIX_ForwardBuilderState *)object; | |
397 | |
398 PKIX_CHECK(PKIX_PL_String_Create | |
399 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), | |
400 PKIX_STRINGCREATEFAILED); | |
401 | |
402 switch (state->status) { | |
403 case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING"; | |
404 break; | |
405 case BUILD_INITIAL: asciiStatus = "BUILD_INITIAL"; | |
406 break; | |
407 case BUILD_TRYAIA: asciiStatus = "BUILD_TRYAIA"; | |
408 break; | |
409 case BUILD_AIAPENDING: asciiStatus = "BUILD_AIAPENDING"; | |
410 break; | |
411 case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS"; | |
412 break; | |
413 case BUILD_GATHERPENDING: asciiStatus = "BUILD_GATHERPENDING"; | |
414 break; | |
415 case BUILD_CERTVALIDATING: asciiStatus = "BUILD_CERTVALIDATING"; | |
416 break; | |
417 case BUILD_ABANDONNODE: asciiStatus = "BUILD_ABANDONNODE"; | |
418 break; | |
419 case BUILD_CRLPREP: asciiStatus = "BUILD_CRLPREP"; | |
420 break; | |
421 case BUILD_CRL1: asciiStatus = "BUILD_CRL1"; | |
422 break; | |
423 case BUILD_DATEPREP: asciiStatus = "BUILD_DATEPREP"; | |
424 break; | |
425 case BUILD_CHECKTRUSTED: asciiStatus = "BUILD_CHECKTRUSTED"; | |
426 break; | |
427 case BUILD_CHECKTRUSTED2: asciiStatus = "BUILD_CHECKTRUSTED2"; | |
428 break; | |
429 case BUILD_ADDTOCHAIN: asciiStatus = "BUILD_ADDTOCHAIN"; | |
430 break; | |
431 case BUILD_CRL2: asciiStatus = "BUILD_CRL2"; | |
432 break; | |
433 case BUILD_VALCHAIN: asciiStatus = "BUILD_VALCHAIN"; | |
434 break; | |
435 case BUILD_VALCHAIN2: asciiStatus = "BUILD_VALCHAIN2"; | |
436 break; | |
437 case BUILD_EXTENDCHAIN: asciiStatus = "BUILD_EXTENDCHAIN"; | |
438 break; | |
439 case BUILD_GETNEXTCERT: asciiStatus = "BUILD_GETNEXTCERT"; | |
440 break; | |
441 default: asciiStatus = "INVALID STATUS"; | |
442 break; | |
443 } | |
444 | |
445 PKIX_CHECK(PKIX_PL_String_Create | |
446 (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext), | |
447 PKIX_STRINGCREATEFAILED); | |
448 | |
449 PKIX_TOSTRING | |
450 (state->validityDate, &validityDateString, plContext, | |
451 PKIX_OBJECTTOSTRINGFAILED); | |
452 | |
453 PKIX_TOSTRING | |
454 (state->prevCert, &prevCertString, plContext, | |
455 PKIX_OBJECTTOSTRINGFAILED); | |
456 | |
457 PKIX_TOSTRING | |
458 (state->candidateCert, &candidateCertString, plContext, | |
459 PKIX_OBJECTTOSTRINGFAILED); | |
460 | |
461 PKIX_TOSTRING | |
462 (state->traversedSubjNames, | |
463 &traversedSubjNamesString, | |
464 plContext, | |
465 PKIX_OBJECTTOSTRINGFAILED); | |
466 | |
467 PKIX_TOSTRING | |
468 (state->trustChain, &trustChainString, plContext, | |
469 PKIX_OBJECTTOSTRINGFAILED); | |
470 | |
471 PKIX_TOSTRING | |
472 (state->candidateCerts, &candidateCertsString, plContext, | |
473 PKIX_OBJECTTOSTRINGFAILED); | |
474 | |
475 PKIX_TOSTRING | |
476 (state->certSel, &certSelString, plContext, | |
477 PKIX_OBJECTTOSTRINGFAILED); | |
478 | |
479 PKIX_TOSTRING | |
480 (state->verifyNode, &verifyNodeString, plContext, | |
481 PKIX_OBJECTTOSTRINGFAILED); | |
482 | |
483 PKIX_TOSTRING | |
484 (state->parentState, &parentStateString, plContext, | |
485 PKIX_OBJECTTOSTRINGFAILED); | |
486 | |
487 PKIX_CHECK(PKIX_PL_Sprintf | |
488 (&resultString, | |
489 plContext, | |
490 formatString, | |
491 buildStatusString, | |
492 (PKIX_Int32)state->traversedCACerts, | |
493 (PKIX_UInt32)state->certStoreIndex, | |
494 (PKIX_UInt32)state->numCerts, | |
495 (PKIX_UInt32)state->numAias, | |
496 (PKIX_UInt32)state->certIndex, | |
497 (PKIX_UInt32)state->aiaIndex, | |
498 (PKIX_UInt32)state->numFanout, | |
499 (PKIX_UInt32)state->numDepth, | |
500 (PKIX_UInt32)state->reasonCode, | |
501 state->revCheckDelayed, | |
502 state->canBeCached, | |
503 state->useOnlyLocal, | |
504 state->revChecking, | |
505 validityDateString, | |
506 prevCertString, | |
507 candidateCertString, | |
508 traversedSubjNamesString, | |
509 trustChainString, | |
510 candidateCertsString, | |
511 certSelString, | |
512 verifyNodeString, | |
513 parentStateString), | |
514 PKIX_SPRINTFFAILED); | |
515 | |
516 *pString = resultString; | |
517 | |
518 cleanup: | |
519 PKIX_DECREF(formatString); | |
520 PKIX_DECREF(buildStatusString); | |
521 PKIX_DECREF(validityDateString); | |
522 PKIX_DECREF(prevCertString); | |
523 PKIX_DECREF(candidateCertString); | |
524 PKIX_DECREF(traversedSubjNamesString); | |
525 PKIX_DECREF(trustChainString); | |
526 PKIX_DECREF(candidateCertsString); | |
527 PKIX_DECREF(certSelString); | |
528 PKIX_DECREF(verifyNodeString); | |
529 PKIX_DECREF(parentStateString); | |
530 | |
531 PKIX_RETURN(FORWARDBUILDERSTATE); | |
532 | |
533 } | |
534 | |
535 /* | |
536 * FUNCTION: pkix_ForwardBuilderState_RegisterSelf | |
537 * | |
538 * DESCRIPTION: | |
539 * Registers PKIX_FORWARDBUILDERSTATE_TYPE and its related functions | |
540 * with systemClasses[] | |
541 * | |
542 * THREAD SAFETY: | |
543 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
544 * | |
545 * Since this function is only called by PKIX_PL_Initialize, which should | |
546 * only be called once, it is acceptable that this function is not | |
547 * thread-safe. | |
548 */ | |
549 PKIX_Error * | |
550 pkix_ForwardBuilderState_RegisterSelf(void *plContext) | |
551 { | |
552 | |
553 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
554 pkix_ClassTable_Entry entry; | |
555 | |
556 PKIX_ENTER(FORWARDBUILDERSTATE, | |
557 "pkix_ForwardBuilderState_RegisterSelf"); | |
558 | |
559 entry.description = "ForwardBuilderState"; | |
560 entry.objCounter = 0; | |
561 entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState); | |
562 entry.destructor = pkix_ForwardBuilderState_Destroy; | |
563 entry.equalsFunction = NULL; | |
564 entry.hashcodeFunction = NULL; | |
565 entry.toStringFunction = pkix_ForwardBuilderState_ToString; | |
566 entry.comparator = NULL; | |
567 entry.duplicateFunction = NULL; | |
568 | |
569 systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry; | |
570 | |
571 PKIX_RETURN(FORWARDBUILDERSTATE); | |
572 } | |
573 | |
574 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
575 /* | |
576 * FUNCTION: pkix_ForwardBuilderState_DumpState | |
577 * | |
578 * DESCRIPTION: | |
579 * This function invokes the ToString function on the argument pointed to | |
580 * by "state". | |
581 * PARAMETERS: | |
582 * "state" | |
583 * The address of the ForwardBuilderState object. Must be non-NULL. | |
584 * | |
585 * THREAD SAFETY: | |
586 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
587 */ | |
588 PKIX_Error * | |
589 pkix_ForwardBuilderState_DumpState( | |
590 PKIX_ForwardBuilderState *state, | |
591 void *plContext) | |
592 { | |
593 PKIX_PL_String *stateString = NULL; | |
594 char *stateAscii = NULL; | |
595 PKIX_UInt32 length; | |
596 | |
597 PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState"); | |
598 PKIX_NULLCHECK_ONE(state); | |
599 | |
600 PKIX_CHECK(PKIX_PL_Object_InvalidateCache | |
601 ((PKIX_PL_Object *)state, plContext), | |
602 PKIX_OBJECTINVALIDATECACHEFAILED); | |
603 | |
604 PKIX_CHECK(PKIX_PL_Object_ToString | |
605 ((PKIX_PL_Object*)state, &stateString, plContext), | |
606 PKIX_OBJECTTOSTRINGFAILED); | |
607 | |
608 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
609 (stateString, | |
610 PKIX_ESCASCII, | |
611 (void **)&stateAscii, | |
612 &length, | |
613 plContext), | |
614 PKIX_STRINGGETENCODEDFAILED); | |
615 | |
616 PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii); | |
617 | |
618 PKIX_FREE(stateAscii); | |
619 PKIX_DECREF(stateString); | |
620 | |
621 cleanup: | |
622 PKIX_RETURN(FORWARDBUILDERSTATE); | |
623 } | |
624 #endif | |
625 | |
626 /* | |
627 * FUNCTION: pkix_ForwardBuilderState_IsIOPending | |
628 * DESCRIPTION: | |
629 * | |
630 * This function determines whether the state of the ForwardBuilderState | |
631 * pointed to by "state" indicates I/O is in progress, and stores the Boolean | |
632 * result at "pPending". | |
633 * | |
634 * PARAMETERS: | |
635 * "state" | |
636 * The address of the ForwardBuilderState object. Must be non-NULL. | |
637 * "pPending" | |
638 * The address at which the result is stored. Must be non-NULL. | |
639 * "plContext" | |
640 * Platform-specific context pointer. | |
641 * THREAD SAFETY: | |
642 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
643 * RETURNS: | |
644 * Returns NULL if the function succeeds. | |
645 * Returns a ForwardBuilderState Error if the function fails in a | |
646 * non-fatal way. | |
647 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
648 */ | |
649 static PKIX_Error* | |
650 pkix_ForwardBuilderState_IsIOPending( | |
651 PKIX_ForwardBuilderState *state, | |
652 PKIX_Boolean *pPending, | |
653 void *plContext) | |
654 { | |
655 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending"); | |
656 PKIX_NULLCHECK_TWO(state, pPending); | |
657 | |
658 if ((state->status == BUILD_GATHERPENDING) || | |
659 (state->status == BUILD_CRL1) || | |
660 (state->status == BUILD_CRL2) || | |
661 (state->status == BUILD_CHECKTRUSTED2) || | |
662 (state->status == BUILD_VALCHAIN2) || | |
663 (state->status == BUILD_AIAPENDING)) { | |
664 *pPending = PKIX_TRUE; | |
665 } else { | |
666 *pPending = PKIX_FALSE; | |
667 } | |
668 | |
669 PKIX_RETURN(FORWARDBUILDERSTATE); | |
670 } | |
671 | |
672 /* --Private-BuildChain-Functions------------------------------------------- */ | |
673 | |
674 /* | |
675 * FUNCTION: pkix_Build_SortCertComparator | |
676 * DESCRIPTION: | |
677 * | |
678 * This Function takes two Certificates cast in "obj1" and "obj2", | |
679 * compares their validity NotAfter dates and returns the result at | |
680 * "pResult". The comparison key(s) can be expanded by using other | |
681 * data in the Certificate in the future. | |
682 * | |
683 * PARAMETERS: | |
684 * "obj1" | |
685 * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. | |
686 * Must be non-NULL. | |
687 * "obj2" | |
688 * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. | |
689 * Must be non-NULL. | |
690 * "pResult" | |
691 * Address where the comparison result is returned. Must be non-NULL. | |
692 * "plContext" | |
693 * Platform-specific context pointer. | |
694 * THREAD SAFETY: | |
695 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
696 * RETURNS: | |
697 * Returns NULL if the function succeeds. | |
698 * Returns a Build Error if the function fails in a non-fatal way | |
699 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
700 */ | |
701 static PKIX_Error * | |
702 pkix_Build_SortCertComparator( | |
703 PKIX_PL_Object *obj1, | |
704 PKIX_PL_Object *obj2, | |
705 PKIX_Int32 *pResult, | |
706 void *plContext) | |
707 { | |
708 PKIX_PL_Date *date1 = NULL; | |
709 PKIX_PL_Date *date2 = NULL; | |
710 PKIX_Boolean result = PKIX_FALSE; | |
711 | |
712 PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator"); | |
713 PKIX_NULLCHECK_THREE(obj1, obj2, pResult); | |
714 | |
715 /* | |
716 * For sorting candidate certificates, we use NotAfter date as the | |
717 * sorted key for now (can be expanded if desired in the future). | |
718 * | |
719 * In PKIX_BuildChain, the List of CertStores was reordered so that | |
720 * trusted CertStores are ahead of untrusted CertStores. That sort, or | |
721 * this one, could be taken out if it is determined that it doesn't help | |
722 * performance, or in some way hinders the solution of choosing desired | |
723 * candidates. | |
724 */ | |
725 | |
726 PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext), | |
727 PKIX_OBJECTNOTCERT); | |
728 PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext), | |
729 PKIX_OBJECTNOTCERT); | |
730 | |
731 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
732 ((PKIX_PL_Cert *)obj1, &date1, plContext), | |
733 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
734 | |
735 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
736 ((PKIX_PL_Cert *)obj2, &date2, plContext), | |
737 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
738 | |
739 PKIX_CHECK(PKIX_PL_Object_Compare | |
740 ((PKIX_PL_Object *)date1, | |
741 (PKIX_PL_Object *)date2, | |
742 &result, | |
743 plContext), | |
744 PKIX_OBJECTCOMPARATORFAILED); | |
745 | |
746 *pResult = !result; | |
747 | |
748 cleanup: | |
749 | |
750 PKIX_DECREF(date1); | |
751 PKIX_DECREF(date2); | |
752 | |
753 PKIX_RETURN(BUILD); | |
754 } | |
755 | |
756 /* This local error check macro */ | |
757 #define ERROR_CHECK(errCode) \ | |
758 if (pkixErrorResult) { \ | |
759 if (pkixLog) { \ | |
760 PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCo
de)); \ | |
761 } \ | |
762 pkixTempErrorReceived = PKIX_TRUE; \ | |
763 pkixErrorClass = pkixErrorResult->errClass; \ | |
764 if (pkixErrorClass == PKIX_FATAL_ERROR) { \ | |
765 goto cleanup; \ | |
766 } \ | |
767 if (verifyNode) { \ | |
768 PKIX_DECREF(verifyNode->error); \ | |
769 PKIX_INCREF(pkixErrorResult); \ | |
770 verifyNode->error = pkixErrorResult; \ | |
771 } \ | |
772 pkixErrorCode = errCode; \ | |
773 goto cleanup; \ | |
774 } | |
775 | |
776 /* | |
777 * FUNCTION: pkix_Build_VerifyCertificate | |
778 * DESCRIPTION: | |
779 * | |
780 * Checks whether the previous Cert stored in the ForwardBuilderState pointed | |
781 * to by "state" successfully chains, including signature verification, to the | |
782 * candidate Cert also stored in "state", using the Boolean value in "trusted" | |
783 * to determine whether "candidateCert" is trusted. Using the Boolean value in | |
784 * "revocationChecking" for the existence of revocation checking, it sets | |
785 * "pNeedsCRLChecking" to PKIX_TRUE if the candidate Cert needs to be checked | |
786 * against Certificate Revocation Lists. | |
787 * | |
788 * First it checks whether "candidateCert" has already been traversed by | |
789 * determining whether it is contained in the List of traversed Certs. It | |
790 * checks the candidate Cert with user checkers, if any, in the List pointed to | |
791 * by "userCheckers". It then runs the signature validation. Finally, it | |
792 * determines the appropriate value for "pNeedsCRLChecking". | |
793 * | |
794 * If this Certificate fails verification, and state->verifyNode is non-NULL, | |
795 * this function sets the Error code into the verifyNode. | |
796 * | |
797 * PARAMETERS: | |
798 * "state" | |
799 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
800 * "userCheckers" | |
801 * Address of a List of CertChainCheckers to be used, if present, to | |
802 * validate the candidateCert. | |
803 * "revocationChecking" | |
804 * Boolean indication of whether revocation checking is available, either | |
805 * as a CertChainChecker or a List of RevocationCheckers. | |
806 * "trusted" | |
807 * Boolean value of trust for the candidate Cert | |
808 * "pNeedsCRLChecking" | |
809 * Address where Boolean CRL-checking-needed value is stored. | |
810 * Must be non-NULL. | |
811 * "plContext" | |
812 * Platform-specific context pointer. | |
813 * THREAD SAFETY: | |
814 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
815 * RETURNS: | |
816 * Returns NULL if the function succeeds. | |
817 * Returns a Build Error if the function fails in a non-fatal way | |
818 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
819 */ | |
820 static PKIX_Error * | |
821 pkix_Build_VerifyCertificate( | |
822 PKIX_ForwardBuilderState *state, | |
823 PKIX_List *userCheckers, | |
824 PKIX_Boolean revocationChecking, | |
825 PKIX_Boolean *pTrusted, | |
826 PKIX_Boolean *pNeedsCRLChecking, | |
827 PKIX_VerifyNode *verifyNode, | |
828 void *plContext) | |
829 { | |
830 PKIX_UInt32 numUserCheckers = 0; | |
831 PKIX_UInt32 i = 0; | |
832 PKIX_Boolean loopFound = PKIX_FALSE; | |
833 PKIX_Boolean supportForwardChecking = PKIX_FALSE; | |
834 PKIX_Boolean trusted = PKIX_FALSE; | |
835 PKIX_PL_Cert *candidateCert = NULL; | |
836 PKIX_PL_PublicKey *candidatePubKey = NULL; | |
837 PKIX_CertChainChecker *userChecker = NULL; | |
838 PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; | |
839 PKIX_Boolean trustOnlyUserAnchors = PKIX_FALSE; | |
840 void *nbioContext = NULL; | |
841 | |
842 PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate"); | |
843 PKIX_NULLCHECK_THREE(state, pTrusted, pNeedsCRLChecking); | |
844 PKIX_NULLCHECK_THREE | |
845 (state->candidateCerts, state->prevCert, state->trustChain); | |
846 | |
847 *pNeedsCRLChecking = PKIX_FALSE; | |
848 | |
849 PKIX_INCREF(state->candidateCert); | |
850 candidateCert = state->candidateCert; | |
851 | |
852 if (state->buildConstants.numAnchors) { | |
853 trustOnlyUserAnchors = state->buildConstants.trustOnlyUserAnchors; | |
854 } | |
855 | |
856 PKIX_CHECK( | |
857 PKIX_PL_Cert_IsCertTrusted(candidateCert, | |
858 trustOnlyUserAnchors, | |
859 &trusted, plContext), | |
860 PKIX_CERTISCERTTRUSTEDFAILED); | |
861 | |
862 *pTrusted = trusted; | |
863 | |
864 /* check for loops */ | |
865 PKIX_CHECK(pkix_List_Contains | |
866 (state->trustChain, | |
867 (PKIX_PL_Object *)candidateCert, | |
868 &loopFound, | |
869 plContext), | |
870 PKIX_LISTCONTAINSFAILED); | |
871 | |
872 if (loopFound) { | |
873 if (verifyNode != NULL) { | |
874 PKIX_Error *verifyError = NULL; | |
875 PKIX_ERROR_CREATE | |
876 (BUILD, | |
877 PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, | |
878 verifyError); | |
879 PKIX_DECREF(verifyNode->error); | |
880 verifyNode->error = verifyError; | |
881 } | |
882 /* Even if error logged, still need to abort | |
883 * if cert is not trusted. */ | |
884 if (!trusted) { | |
885 PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
886 } | |
887 state->certLoopingDetected = PKIX_TRUE; | |
888 } | |
889 | |
890 if (userCheckers != NULL) { | |
891 | |
892 PKIX_CHECK(PKIX_List_GetLength | |
893 (userCheckers, &numUserCheckers, plContext), | |
894 PKIX_LISTGETLENGTHFAILED); | |
895 | |
896 for (i = 0; i < numUserCheckers; i++) { | |
897 | |
898 PKIX_CHECK(PKIX_List_GetItem | |
899 (userCheckers, | |
900 i, | |
901 (PKIX_PL_Object **) &userChecker, | |
902 plContext), | |
903 PKIX_LISTGETITEMFAILED); | |
904 | |
905 PKIX_CHECK | |
906 (PKIX_CertChainChecker_IsForwardCheckingSupported | |
907 (userChecker, &supportForwardChecking, plContext), | |
908 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); | |
909 | |
910 if (supportForwardChecking == PKIX_TRUE) { | |
911 | |
912 PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback | |
913 (userChecker, &checkerCheck, plContext), | |
914 PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); | |
915 | |
916 pkixErrorResult = | |
917 checkerCheck(userChecker, candidateCert, NULL, | |
918 &nbioContext, plContext); | |
919 | |
920 ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED); | |
921 } | |
922 | |
923 PKIX_DECREF(userChecker); | |
924 } | |
925 } | |
926 | |
927 /* Check that public key of the trusted dsa cert has | |
928 * dsa parameters */ | |
929 if (trusted) { | |
930 PKIX_Boolean paramsNeeded = PKIX_FALSE; | |
931 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
932 (candidateCert, &candidatePubKey, plContext), | |
933 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
934 PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters | |
935 (candidatePubKey, ¶msNeeded, plContext), | |
936 PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED); | |
937 if (paramsNeeded) { | |
938 PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS); | |
939 } | |
940 } | |
941 | |
942 | |
943 if (revocationChecking) { | |
944 if (!trusted) { | |
945 if (state->revCheckDelayed) { | |
946 goto cleanup; | |
947 } else { | |
948 PKIX_Boolean isSelfIssued = PKIX_FALSE; | |
949 PKIX_CHECK( | |
950 pkix_IsCertSelfIssued(candidateCert, &isSelfIssued, | |
951 plContext), | |
952 PKIX_ISCERTSELFISSUEDFAILED); | |
953 if (isSelfIssued) { | |
954 state->revCheckDelayed = PKIX_TRUE; | |
955 goto cleanup; | |
956 } | |
957 } | |
958 } | |
959 *pNeedsCRLChecking = PKIX_TRUE; | |
960 } | |
961 | |
962 cleanup: | |
963 PKIX_DECREF(candidateCert); | |
964 PKIX_DECREF(candidatePubKey); | |
965 PKIX_DECREF(userChecker); | |
966 | |
967 PKIX_RETURN(BUILD); | |
968 } | |
969 | |
970 /* | |
971 * FUNCTION: pkix_Build_ValidationCheckers | |
972 * DESCRIPTION: | |
973 * | |
974 * Creates a List of Objects to be used in determining whether the List of | |
975 * Certs pointed to by "certChain" successfully validates using the | |
976 * ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by | |
977 * "anchor". These objects are a reversed Cert Chain, consisting of the certs | |
978 * in "certChain" in reversed order, suitable for presenting to the | |
979 * CertChainCheckers; a List of critical extension OIDS that have already been | |
980 * processed in forward building; a List of CertChainCheckers to be called, and | |
981 * a List of RevocationCheckers to be called. These results are stored in | |
982 * fields of "state". | |
983 * | |
984 * PARAMETERS: | |
985 * "state" | |
986 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
987 * "certChain" | |
988 * Address of List of Certs to be validated. Must be non-NULL. | |
989 * "anchor" | |
990 * Address of TrustAnchor to be used. Must be non-NULL. | |
991 * "addEkuChecker" | |
992 * Boolean flags that tells to add eku checker to the list | |
993 * of checkers. Only needs to be done for existing chain revalidation. | |
994 * "plContext" | |
995 * Platform-specific context pointer. | |
996 * THREAD SAFETY: | |
997 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
998 * RETURNS: | |
999 * Returns NULL if the function succeeds. | |
1000 * Returns a Build Error if the function fails in a non-fatal way | |
1001 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1002 */ | |
1003 static PKIX_Error * | |
1004 pkix_Build_ValidationCheckers( | |
1005 PKIX_ForwardBuilderState *state, | |
1006 PKIX_List *certChain, | |
1007 PKIX_TrustAnchor *anchor, | |
1008 PKIX_Boolean chainRevalidationStage, | |
1009 void *plContext) | |
1010 { | |
1011 PKIX_List *checkers = NULL; | |
1012 PKIX_List *initialPolicies = NULL; | |
1013 PKIX_List *reversedCertChain = NULL; | |
1014 PKIX_List *buildCheckedCritExtOIDsList = NULL; | |
1015 PKIX_ProcessingParams *procParams = NULL; | |
1016 PKIX_PL_Cert *trustedCert = NULL; | |
1017 PKIX_PL_PublicKey *trustedPubKey = NULL; | |
1018 PKIX_CertChainChecker *sigChecker = NULL; | |
1019 PKIX_CertChainChecker *policyChecker = NULL; | |
1020 PKIX_CertChainChecker *userChecker = NULL; | |
1021 PKIX_CertChainChecker *checker = NULL; | |
1022 PKIX_CertSelector *certSelector = NULL; | |
1023 PKIX_List *userCheckerExtOIDs = NULL; | |
1024 PKIX_PL_OID *oid = NULL; | |
1025 PKIX_Boolean supportForwardChecking = PKIX_FALSE; | |
1026 PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; | |
1027 PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; | |
1028 PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; | |
1029 PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; | |
1030 PKIX_UInt32 numChainCerts; | |
1031 PKIX_UInt32 numCertCheckers; | |
1032 PKIX_UInt32 i; | |
1033 | |
1034 PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers"); | |
1035 PKIX_NULLCHECK_THREE(state, certChain, anchor); | |
1036 | |
1037 PKIX_CHECK(PKIX_List_Create(&checkers, plContext), | |
1038 PKIX_LISTCREATEFAILED); | |
1039 | |
1040 PKIX_CHECK(PKIX_List_ReverseList | |
1041 (certChain, &reversedCertChain, plContext), | |
1042 PKIX_LISTREVERSELISTFAILED); | |
1043 | |
1044 PKIX_CHECK(PKIX_List_GetLength | |
1045 (reversedCertChain, &numChainCerts, plContext), | |
1046 PKIX_LISTGETLENGTHFAILED); | |
1047 | |
1048 procParams = state->buildConstants.procParams; | |
1049 | |
1050 /* Do need to add a number of checker to revalidate | |
1051 * a built chain. KU, EKU, CertType and Validity Date | |
1052 * get checked by certificate selector during chain | |
1053 * construction, but needed to be checked for chain from | |
1054 * the cache.*/ | |
1055 if (chainRevalidationStage) { | |
1056 PKIX_CHECK(pkix_ExpirationChecker_Initialize | |
1057 (state->buildConstants.testDate, &checker, plContext), | |
1058 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); | |
1059 PKIX_CHECK(PKIX_List_AppendItem | |
1060 (checkers, (PKIX_PL_Object *)checker, plContext), | |
1061 PKIX_LISTAPPENDITEMFAILED); | |
1062 PKIX_DECREF(checker); | |
1063 | |
1064 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
1065 (procParams, &certSelector, plContext), | |
1066 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
1067 | |
1068 PKIX_CHECK(pkix_TargetCertChecker_Initialize | |
1069 (certSelector, numChainCerts, &checker, plContext), | |
1070 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); | |
1071 PKIX_CHECK(PKIX_List_AppendItem | |
1072 (checkers, (PKIX_PL_Object *)checker, plContext), | |
1073 PKIX_LISTAPPENDITEMFAILED); | |
1074 PKIX_DECREF(checker); | |
1075 } | |
1076 | |
1077 PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies | |
1078 (procParams, &initialPolicies, plContext), | |
1079 PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); | |
1080 | |
1081 PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected | |
1082 (procParams, &policyQualifiersRejected, plContext), | |
1083 PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); | |
1084 | |
1085 PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited | |
1086 (procParams, &initialPolicyMappingInhibit, plContext), | |
1087 PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); | |
1088 | |
1089 PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited | |
1090 (procParams, &initialAnyPolicyInhibit, plContext), | |
1091 PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); | |
1092 | |
1093 PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired | |
1094 (procParams, &initialExplicitPolicy, plContext), | |
1095 PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); | |
1096 | |
1097 PKIX_CHECK(pkix_PolicyChecker_Initialize | |
1098 (initialPolicies, | |
1099 policyQualifiersRejected, | |
1100 initialPolicyMappingInhibit, | |
1101 initialExplicitPolicy, | |
1102 initialAnyPolicyInhibit, | |
1103 numChainCerts, | |
1104 &policyChecker, | |
1105 plContext), | |
1106 PKIX_POLICYCHECKERINITIALIZEFAILED); | |
1107 | |
1108 PKIX_CHECK(PKIX_List_AppendItem | |
1109 (checkers, (PKIX_PL_Object *)policyChecker, plContext), | |
1110 PKIX_LISTAPPENDITEMFAILED); | |
1111 | |
1112 /* | |
1113 * Create an OID list that contains critical extensions processed | |
1114 * by BuildChain. These are specified in a static const array. | |
1115 */ | |
1116 PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext), | |
1117 PKIX_LISTCREATEFAILED); | |
1118 | |
1119 for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) { | |
1120 PKIX_CHECK(PKIX_PL_OID_Create | |
1121 (buildCheckedCritExtOIDs[i], &oid, plContext), | |
1122 PKIX_OIDCREATEFAILED); | |
1123 | |
1124 PKIX_CHECK(PKIX_List_AppendItem | |
1125 (buildCheckedCritExtOIDsList, | |
1126 (PKIX_PL_Object *) oid, | |
1127 plContext), | |
1128 PKIX_LISTAPPENDITEMFAILED); | |
1129 | |
1130 PKIX_DECREF(oid); | |
1131 } | |
1132 | |
1133 if (state->buildConstants.userCheckers != NULL) { | |
1134 | |
1135 PKIX_CHECK(PKIX_List_GetLength | |
1136 (state->buildConstants.userCheckers, | |
1137 &numCertCheckers, | |
1138 plContext), | |
1139 PKIX_LISTGETLENGTHFAILED); | |
1140 | |
1141 for (i = 0; i < numCertCheckers; i++) { | |
1142 | |
1143 PKIX_CHECK(PKIX_List_GetItem | |
1144 (state->buildConstants.userCheckers, | |
1145 i, | |
1146 (PKIX_PL_Object **) &userChecker, | |
1147 plContext), | |
1148 PKIX_LISTGETITEMFAILED); | |
1149 | |
1150 PKIX_CHECK | |
1151 (PKIX_CertChainChecker_IsForwardCheckingSupported | |
1152 (userChecker, &supportForwardChecking, plContext), | |
1153 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
1154 | |
1155 /* | |
1156 * If this userChecker supports forwardChecking then it | |
1157 * should have been checked during build chain. Skip | |
1158 * checking but need to add checker's extension OIDs | |
1159 * to buildCheckedCritExtOIDsList. | |
1160 */ | |
1161 if (supportForwardChecking == PKIX_TRUE) { | |
1162 | |
1163 PKIX_CHECK | |
1164 (PKIX_CertChainChecker_GetSupportedExtensions | |
1165 (userChecker, &userCheckerExtOIDs, plContext), | |
1166 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
1167 | |
1168 if (userCheckerExtOIDs != NULL) { | |
1169 PKIX_CHECK(pkix_List_AppendList | |
1170 (buildCheckedCritExtOIDsList, | |
1171 userCheckerExtOIDs, | |
1172 plContext), | |
1173 PKIX_LISTAPPENDLISTFAILED); | |
1174 } | |
1175 | |
1176 } else { | |
1177 PKIX_CHECK(PKIX_List_AppendItem | |
1178 (checkers, | |
1179 (PKIX_PL_Object *)userChecker, | |
1180 plContext), | |
1181 PKIX_LISTAPPENDITEMFAILED); | |
1182 } | |
1183 | |
1184 PKIX_DECREF(userCheckerExtOIDs); | |
1185 PKIX_DECREF(userChecker); | |
1186 } | |
1187 } | |
1188 | |
1189 /* Inabling post chain building signature check on the certs. */ | |
1190 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
1191 (anchor, &trustedCert, plContext), | |
1192 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
1193 | |
1194 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
1195 (trustedCert, &trustedPubKey, plContext), | |
1196 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
1197 | |
1198 PKIX_CHECK(pkix_SignatureChecker_Initialize | |
1199 (trustedPubKey, | |
1200 numChainCerts, | |
1201 &sigChecker, | |
1202 plContext), | |
1203 PKIX_SIGNATURECHECKERINITIALIZEFAILED); | |
1204 | |
1205 PKIX_CHECK(PKIX_List_AppendItem | |
1206 (checkers, | |
1207 (PKIX_PL_Object *)sigChecker, | |
1208 plContext), | |
1209 PKIX_LISTAPPENDITEMFAILED); | |
1210 | |
1211 PKIX_DECREF(state->reversedCertChain); | |
1212 PKIX_INCREF(reversedCertChain); | |
1213 state->reversedCertChain = reversedCertChain; | |
1214 PKIX_DECREF(state->checkedCritExtOIDs); | |
1215 PKIX_INCREF(buildCheckedCritExtOIDsList); | |
1216 state->checkedCritExtOIDs = buildCheckedCritExtOIDsList; | |
1217 PKIX_DECREF(state->checkerChain); | |
1218 state->checkerChain = checkers; | |
1219 checkers = NULL; | |
1220 state->certCheckedIndex = 0; | |
1221 state->checkerIndex = 0; | |
1222 state->revChecking = PKIX_FALSE; | |
1223 | |
1224 | |
1225 cleanup: | |
1226 | |
1227 PKIX_DECREF(oid); | |
1228 PKIX_DECREF(reversedCertChain); | |
1229 PKIX_DECREF(buildCheckedCritExtOIDsList); | |
1230 PKIX_DECREF(checker); | |
1231 PKIX_DECREF(checkers); | |
1232 PKIX_DECREF(initialPolicies); | |
1233 PKIX_DECREF(trustedCert); | |
1234 PKIX_DECREF(trustedPubKey); | |
1235 PKIX_DECREF(certSelector); | |
1236 PKIX_DECREF(sigChecker); | |
1237 PKIX_DECREF(policyChecker); | |
1238 PKIX_DECREF(userChecker); | |
1239 PKIX_DECREF(userCheckerExtOIDs); | |
1240 | |
1241 PKIX_RETURN(BUILD); | |
1242 } | |
1243 | |
1244 /* | |
1245 * FUNCTION: pkix_Build_ValidateEntireChain | |
1246 * DESCRIPTION: | |
1247 * | |
1248 * Checks whether the current List of Certs successfully validates using the | |
1249 * TrustAnchor pointed to by "anchor" and other parameters contained, as was | |
1250 * the Cert List, in "state". | |
1251 * | |
1252 * If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O | |
1253 * context (NBIOContext), an indication that I/O is in progress and the | |
1254 * checking has not been completed, this function stores that context at | |
1255 * "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext". | |
1256 * | |
1257 * If not awaiting I/O and if successful, a ValidateResult is created | |
1258 * containing the Public Key of the target certificate (including DSA parameter | |
1259 * inheritance, if any) and the PolicyNode representing the policy tree output | |
1260 * by the validation algorithm. If not successful, an Error pointer is | |
1261 * returned. | |
1262 * | |
1263 * PARAMETERS: | |
1264 * "state" | |
1265 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
1266 * "anchor" | |
1267 * Address of TrustAnchor to be used. Must be non-NULL. | |
1268 * "pNBIOContext" | |
1269 * Address at which the NBIOContext is stored indicating whether the | |
1270 * validation is complete. Must be non-NULL. | |
1271 * "pValResult" | |
1272 * Address at which the ValidateResult is stored. Must be non-NULL. | |
1273 * "plContext" | |
1274 * Platform-specific context pointer. | |
1275 * THREAD SAFETY: | |
1276 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1277 * RETURNS: | |
1278 * Returns NULL if the function succeeds. | |
1279 * Returns a Build Error if the function fails in a non-fatal way | |
1280 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1281 */ | |
1282 static PKIX_Error * | |
1283 pkix_Build_ValidateEntireChain( | |
1284 PKIX_ForwardBuilderState *state, | |
1285 PKIX_TrustAnchor *anchor, | |
1286 void **pNBIOContext, | |
1287 PKIX_ValidateResult **pValResult, | |
1288 PKIX_VerifyNode *verifyNode, | |
1289 void *plContext) | |
1290 { | |
1291 PKIX_UInt32 numChainCerts = 0; | |
1292 PKIX_PL_PublicKey *subjPubKey = NULL; | |
1293 PKIX_PolicyNode *policyTree = NULL; | |
1294 PKIX_ValidateResult *valResult = NULL; | |
1295 void *nbioContext = NULL; | |
1296 | |
1297 PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain"); | |
1298 PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult); | |
1299 | |
1300 *pNBIOContext = NULL; /* prepare for case of error exit */ | |
1301 | |
1302 PKIX_CHECK(PKIX_List_GetLength | |
1303 (state->reversedCertChain, &numChainCerts, plContext), | |
1304 PKIX_LISTGETLENGTHFAILED); | |
1305 | |
1306 pkixErrorResult = | |
1307 pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor, | |
1308 state->checkerChain, | |
1309 state->buildConstants.revChecker, | |
1310 state->checkedCritExtOIDs, | |
1311 state->buildConstants.procParams, | |
1312 &state->certCheckedIndex, &state->checkerIndex, | |
1313 &state->revChecking, &state->reasonCode, | |
1314 &nbioContext, &subjPubKey, &policyTree, NULL, | |
1315 plContext); | |
1316 | |
1317 if (nbioContext != NULL) { | |
1318 *pNBIOContext = nbioContext; | |
1319 goto cleanup; | |
1320 } | |
1321 | |
1322 ERROR_CHECK(PKIX_CHECKCHAINFAILED); | |
1323 | |
1324 if (state->reasonCode != 0) { | |
1325 PKIX_ERROR(PKIX_CHAINREJECTEDBYREVOCATIONCHECKER); | |
1326 } | |
1327 | |
1328 PKIX_CHECK(pkix_ValidateResult_Create | |
1329 (subjPubKey, anchor, policyTree, &valResult, plContext), | |
1330 PKIX_VALIDATERESULTCREATEFAILED); | |
1331 | |
1332 *pValResult = valResult; | |
1333 valResult = NULL; | |
1334 | |
1335 cleanup: | |
1336 PKIX_DECREF(subjPubKey); | |
1337 PKIX_DECREF(policyTree); | |
1338 PKIX_DECREF(valResult); | |
1339 | |
1340 PKIX_RETURN(BUILD); | |
1341 } | |
1342 | |
1343 /* | |
1344 * FUNCTION: pkix_Build_SortCandidateCerts | |
1345 * DESCRIPTION: | |
1346 * | |
1347 * This function sorts a List of candidate Certs pointed to by "candidates" | |
1348 * using an algorithm that places Certs most likely to produce a successful | |
1349 * chain at the front of the list, storing the resulting sorted List at | |
1350 * "pSortedCandidates". | |
1351 * | |
1352 * At present the only sort criterion is that trusted Certs go ahead of | |
1353 * untrusted Certs. | |
1354 * | |
1355 * PARAMETERS: | |
1356 * "candidates" | |
1357 * Address of List of Candidate Certs to be sorted. Must be non-NULL. | |
1358 * "pSortedCandidates" | |
1359 * Address at which sorted List is stored. Must be non-NULL. | |
1360 * "plContext" | |
1361 * Platform-specific context pointer. | |
1362 * THREAD SAFETY: | |
1363 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1364 * RETURNS: | |
1365 * Returns NULL if the function succeeds. | |
1366 * Returns a Build Error if the function fails in a non-fatal way | |
1367 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1368 */ | |
1369 static PKIX_Error * | |
1370 pkix_Build_SortCandidateCerts( | |
1371 PKIX_List *candidates, | |
1372 PKIX_List **pSortedCandidates, | |
1373 void *plContext) | |
1374 { | |
1375 PKIX_List *sortedList = NULL; | |
1376 | |
1377 PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts"); | |
1378 PKIX_NULLCHECK_TWO(candidates, pSortedCandidates); | |
1379 | |
1380 /* | |
1381 * Both bubble and quick sort algorithms are available. | |
1382 * For a list of fewer than around 100 items, the bubble sort is more | |
1383 * efficient. (This number was determined by experimenting with both | |
1384 * algorithms on a Java List.) | |
1385 * If the candidate list is very small, using the sort can drag down | |
1386 * the performance a little bit. | |
1387 */ | |
1388 | |
1389 PKIX_CHECK(pkix_List_BubbleSort | |
1390 (candidates, | |
1391 pkix_Build_SortCertComparator, | |
1392 &sortedList, | |
1393 plContext), | |
1394 PKIX_LISTBUBBLESORTFAILED); | |
1395 | |
1396 *pSortedCandidates = sortedList; | |
1397 | |
1398 cleanup: | |
1399 | |
1400 PKIX_RETURN(BUILD); | |
1401 } | |
1402 | |
1403 /* | |
1404 * FUNCTION: pkix_Build_BuildSelectorAndParams | |
1405 * DESCRIPTION: | |
1406 * | |
1407 * This function creates a CertSelector, initialized with an appropriate | |
1408 * ComCertSelParams, using the variables provided in the ForwardBuilderState | |
1409 * pointed to by "state". The CertSelector created is stored in the certsel | |
1410 * element of "state". | |
1411 * | |
1412 * PARAMETERS: | |
1413 * "state" | |
1414 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
1415 * "plContext" | |
1416 * Platform-specific context pointer. | |
1417 * THREAD SAFETY: | |
1418 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1419 * RETURNS: | |
1420 * Returns NULL if the function succeeds. | |
1421 * Returns a Build Error if the function fails in a non-fatal way | |
1422 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1423 */ | |
1424 static PKIX_Error * | |
1425 pkix_Build_BuildSelectorAndParams( | |
1426 PKIX_ForwardBuilderState *state, | |
1427 void *plContext) | |
1428 { | |
1429 PKIX_ComCertSelParams *certSelParams = NULL; | |
1430 PKIX_CertSelector *certSel = NULL; | |
1431 PKIX_PL_X500Name *currentIssuer = NULL; | |
1432 PKIX_PL_ByteArray *authKeyId = NULL; | |
1433 PKIX_PL_Date *testDate = NULL; | |
1434 PKIX_CertSelector *callerCertSelector = NULL; | |
1435 PKIX_ComCertSelParams *callerComCertSelParams = NULL; | |
1436 PKIX_UInt32 reqKu = 0; | |
1437 PKIX_List *reqEkuOids = NULL; | |
1438 | |
1439 PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams"); | |
1440 PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames); | |
1441 | |
1442 PKIX_CHECK(PKIX_PL_Cert_GetIssuer | |
1443 (state->prevCert, ¤tIssuer, plContext), | |
1444 PKIX_CERTGETISSUERFAILED); | |
1445 | |
1446 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
1447 (state->prevCert, &authKeyId, plContext), | |
1448 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); | |
1449 | |
1450 PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext), | |
1451 PKIX_COMCERTSELPARAMSCREATEFAILED); | |
1452 | |
1453 PKIX_CHECK(PKIX_ComCertSelParams_SetSubject | |
1454 (certSelParams, currentIssuer, plContext), | |
1455 PKIX_COMCERTSELPARAMSSETSUBJECTFAILED); | |
1456 | |
1457 if (authKeyId != NULL) { | |
1458 PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier | |
1459 (certSelParams, authKeyId, plContext), | |
1460 PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED); | |
1461 } | |
1462 | |
1463 PKIX_INCREF(state->buildConstants.testDate); | |
1464 testDate = state->buildConstants.testDate; | |
1465 | |
1466 PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid | |
1467 (certSelParams, testDate, plContext), | |
1468 PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); | |
1469 | |
1470 PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints | |
1471 (certSelParams, state->traversedCACerts, plContext), | |
1472 PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED); | |
1473 | |
1474 PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames | |
1475 (certSelParams, state->traversedSubjNames, plContext), | |
1476 PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED); | |
1477 | |
1478 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
1479 (state->buildConstants.procParams, | |
1480 &callerCertSelector, plContext), | |
1481 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
1482 | |
1483 if (callerCertSelector != NULL) { | |
1484 | |
1485 /* Get initial EKU OIDs from ComCertSelParams, if set */ | |
1486 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
1487 (callerCertSelector, &callerComCertSelParams, plContext), | |
1488 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
1489 | |
1490 if (callerComCertSelParams != NULL) { | |
1491 PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage | |
1492 (callerComCertSelParams, &reqEkuOids, plContext), | |
1493 PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); | |
1494 | |
1495 PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage | |
1496 (callerComCertSelParams, &reqKu, plContext), | |
1497 PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); | |
1498 } | |
1499 } | |
1500 | |
1501 PKIX_CHECK( | |
1502 PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu, | |
1503 plContext), | |
1504 PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED); | |
1505 | |
1506 PKIX_CHECK( | |
1507 PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams, | |
1508 reqEkuOids, | |
1509 plContext), | |
1510 PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED); | |
1511 | |
1512 PKIX_CHECK(PKIX_CertSelector_Create | |
1513 (NULL, NULL, &state->certSel, plContext), | |
1514 PKIX_CERTSELECTORCREATEFAILED); | |
1515 | |
1516 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams | |
1517 (state->certSel, certSelParams, plContext), | |
1518 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); | |
1519 | |
1520 PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext), | |
1521 PKIX_LISTCREATEFAILED); | |
1522 | |
1523 state->certStoreIndex = 0; | |
1524 | |
1525 cleanup: | |
1526 PKIX_DECREF(certSelParams); | |
1527 PKIX_DECREF(certSel); | |
1528 PKIX_DECREF(currentIssuer); | |
1529 PKIX_DECREF(authKeyId); | |
1530 PKIX_DECREF(testDate); | |
1531 PKIX_DECREF(reqEkuOids); | |
1532 PKIX_DECREF(callerComCertSelParams); | |
1533 PKIX_DECREF(callerCertSelector); | |
1534 | |
1535 PKIX_RETURN(BUILD); | |
1536 } | |
1537 | |
1538 /* Match trust anchor to select params in order to find next cert. */ | |
1539 static PKIX_Error* | |
1540 pkix_Build_SelectCertsFromTrustAnchors( | |
1541 PKIX_List *trustAnchorsList, | |
1542 PKIX_ComCertSelParams *certSelParams, | |
1543 PKIX_List **pMatchList, | |
1544 void *plContext) | |
1545 { | |
1546 int anchorIndex = 0; | |
1547 PKIX_TrustAnchor *anchor = NULL; | |
1548 PKIX_PL_Cert *trustedCert = NULL; | |
1549 PKIX_List *matchList = NULL; | |
1550 PKIX_CertSelector *certSel = NULL; | |
1551 PKIX_CertSelector_MatchCallback selectorMatchCB = NULL; | |
1552 | |
1553 PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors"); | |
1554 | |
1555 PKIX_CHECK(PKIX_CertSelector_Create | |
1556 (NULL, NULL, &certSel, plContext), | |
1557 PKIX_CERTSELECTORCREATEFAILED); | |
1558 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams | |
1559 (certSel, certSelParams, plContext), | |
1560 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); | |
1561 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback | |
1562 (certSel, &selectorMatchCB, plContext), | |
1563 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); | |
1564 | |
1565 for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++)
{ | |
1566 PKIX_CHECK( | |
1567 PKIX_List_GetItem(trustAnchorsList, | |
1568 anchorIndex, | |
1569 (PKIX_PL_Object **)&anchor, | |
1570 plContext), | |
1571 PKIX_LISTGETITEMFAILED); | |
1572 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
1573 (anchor, &trustedCert, plContext), | |
1574 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
1575 pkixErrorResult = | |
1576 (*selectorMatchCB)(certSel, trustedCert, plContext); | |
1577 if (!pkixErrorResult) { | |
1578 if (!matchList) { | |
1579 PKIX_CHECK(PKIX_List_Create(&matchList, | |
1580 plContext), | |
1581 PKIX_LISTCREATEFAILED); | |
1582 } | |
1583 PKIX_CHECK( | |
1584 PKIX_List_AppendItem(matchList, | |
1585 (PKIX_PL_Object*)trustedCert, | |
1586 plContext), | |
1587 PKIX_LISTAPPENDITEMFAILED); | |
1588 } else { | |
1589 PKIX_DECREF(pkixErrorResult); | |
1590 } | |
1591 PKIX_DECREF(trustedCert); | |
1592 PKIX_DECREF(anchor); | |
1593 } | |
1594 | |
1595 *pMatchList = matchList; | |
1596 matchList = NULL; | |
1597 | |
1598 cleanup: | |
1599 PKIX_DECREF(matchList); | |
1600 PKIX_DECREF(trustedCert); | |
1601 PKIX_DECREF(anchor); | |
1602 PKIX_DECREF(certSel); | |
1603 | |
1604 PKIX_RETURN(BUILD); | |
1605 } | |
1606 | |
1607 | |
1608 static PKIX_Error* | |
1609 pkix_Build_RemoveDupUntrustedCerts( | |
1610 PKIX_List *trustedCertList, | |
1611 PKIX_List *certsFound, | |
1612 void *plContext) | |
1613 { | |
1614 PKIX_UInt32 trustIndex; | |
1615 PKIX_PL_Cert *trustCert = NULL, *cert = NULL; | |
1616 | |
1617 PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts"); | |
1618 if (trustedCertList == NULL || certsFound == NULL) { | |
1619 goto cleanup; | |
1620 } | |
1621 for (trustIndex = 0;trustIndex < trustedCertList->length; | |
1622 trustIndex++) { | |
1623 PKIX_UInt32 certIndex = 0; | |
1624 PKIX_CHECK( | |
1625 PKIX_List_GetItem(trustedCertList, | |
1626 trustIndex, | |
1627 (PKIX_PL_Object **)&trustCert, | |
1628 plContext), | |
1629 PKIX_LISTGETITEMFAILED); | |
1630 | |
1631 while (certIndex < certsFound->length) { | |
1632 PKIX_Boolean result = PKIX_FALSE; | |
1633 PKIX_DECREF(cert); | |
1634 PKIX_CHECK( | |
1635 PKIX_List_GetItem(certsFound, certIndex, | |
1636 (PKIX_PL_Object **)&cert, | |
1637 plContext), | |
1638 PKIX_LISTGETITEMFAILED); | |
1639 PKIX_CHECK( | |
1640 PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert, | |
1641 (PKIX_PL_Object *)cert, | |
1642 &result, | |
1643 plContext), | |
1644 PKIX_OBJECTEQUALSFAILED); | |
1645 if (!result) { | |
1646 certIndex += 1; | |
1647 continue; | |
1648 } | |
1649 PKIX_CHECK( | |
1650 PKIX_List_DeleteItem(certsFound, certIndex, | |
1651 plContext), | |
1652 PKIX_LISTDELETEITEMFAILED); | |
1653 } | |
1654 PKIX_DECREF(trustCert); | |
1655 } | |
1656 cleanup: | |
1657 PKIX_DECREF(cert); | |
1658 PKIX_DECREF(trustCert); | |
1659 | |
1660 PKIX_RETURN(BUILD); | |
1661 } | |
1662 | |
1663 | |
1664 /* | |
1665 * FUNCTION: pkix_Build_GatherCerts | |
1666 * DESCRIPTION: | |
1667 * | |
1668 * This function traverses the CertStores in the List of CertStores contained | |
1669 * in "state", using the certSelector and other parameters contained in | |
1670 * "state", to obtain a List of all available Certs that satisfy the criteria. | |
1671 * If a CertStore has a cache, "certSelParams" is used both to query the cache | |
1672 * and, if an actual CertStore search occurred, to update the cache. (Behavior | |
1673 * is undefined if "certSelParams" is different from the parameters that were | |
1674 * used to initialize the certSelector in "state".) | |
1675 * | |
1676 * If a CertStore using non-blocking I/O returns with an indication that I/O is | |
1677 * in progress and the checking has not been completed, this function stores | |
1678 * platform-dependent information at "pNBIOContext". Otherwise it stores NULL | |
1679 * at "pNBIOContext", and state is updated with the results of the search. | |
1680 * | |
1681 * PARAMETERS: | |
1682 * "state" | |
1683 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
1684 * "certSelParams" | |
1685 * Address of ComCertSelParams which were used in creating the current | |
1686 * CertSelector, and to be used in querying and updating any caches that | |
1687 * may be associated with with the CertStores. | |
1688 * "pNBIOContext" | |
1689 * Address at which platform-dependent information is returned if request | |
1690 * is suspended for non-blocking I/O. Must be non-NULL. | |
1691 * "plContext" | |
1692 * Platform-specific context pointer. | |
1693 * THREAD SAFETY: | |
1694 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1695 * RETURNS: | |
1696 * Returns NULL if the function succeeds. | |
1697 * Returns a Build Error if the function fails in a non-fatal way | |
1698 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1699 */ | |
1700 /* return NULL if wouldblock, empty list if none found, else list of found */ | |
1701 static PKIX_Error * | |
1702 pkix_Build_GatherCerts( | |
1703 PKIX_ForwardBuilderState *state, | |
1704 PKIX_ComCertSelParams *certSelParams, | |
1705 void **pNBIOContext, | |
1706 void *plContext) | |
1707 { | |
1708 PKIX_Boolean certStoreIsCached = PKIX_FALSE; | |
1709 PKIX_Boolean certStoreIsLocal = PKIX_FALSE; | |
1710 PKIX_Boolean foundInCache = PKIX_FALSE; | |
1711 PKIX_CertStore *certStore = NULL; | |
1712 PKIX_CertStore_CertCallback getCerts = NULL; | |
1713 PKIX_List *certsFound = NULL; | |
1714 PKIX_List *trustedCertList = NULL; | |
1715 void *nbioContext = NULL; | |
1716 | |
1717 PKIX_ENTER(BUILD, "pkix_Build_GatherCerts"); | |
1718 PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext); | |
1719 | |
1720 nbioContext = *pNBIOContext; | |
1721 *pNBIOContext = NULL; | |
1722 | |
1723 PKIX_DECREF(state->candidateCerts); | |
1724 | |
1725 while (state->certStoreIndex < state->buildConstants.numCertStores) { | |
1726 | |
1727 /* Get the current CertStore */ | |
1728 PKIX_CHECK(PKIX_List_GetItem | |
1729 (state->buildConstants.certStores, | |
1730 state->certStoreIndex, | |
1731 (PKIX_PL_Object **)&certStore, | |
1732 plContext), | |
1733 PKIX_LISTGETITEMFAILED); | |
1734 | |
1735 PKIX_CHECK(PKIX_CertStore_GetLocalFlag | |
1736 (certStore, &certStoreIsLocal, plContext), | |
1737 PKIX_CERTSTOREGETLOCALFLAGFAILED); | |
1738 | |
1739 if (state->useOnlyLocal == certStoreIsLocal) { | |
1740 /* If GATHERPENDING, we've already checked the cache */ | |
1741 if (state->status == BUILD_GATHERPENDING) { | |
1742 certStoreIsCached = PKIX_FALSE; | |
1743 foundInCache = PKIX_FALSE; | |
1744 } else { | |
1745 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag | |
1746 (certStore, &certStoreIsCached, plContext), | |
1747 PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); | |
1748 | |
1749 if (certStoreIsCached) { | |
1750 /* | |
1751 * Look for Certs in the cache, using the SubjectName as | |
1752 * the key. Then the ComCertSelParams are used to filter | |
1753 * for qualified certs. If none are found, then the | |
1754 * certStores are queried. When we eventually add items | |
1755 * to the cache, we will only add items that passed the | |
1756 * ComCertSelParams filter, rather than all Certs which | |
1757 * matched the SubjectName. | |
1758 */ | |
1759 | |
1760 PKIX_CHECK(pkix_CacheCert_Lookup | |
1761 (certStore, | |
1762 certSelParams, | |
1763 state->buildConstants.testDate, | |
1764 &foundInCache, | |
1765 &certsFound, | |
1766 plContext), | |
1767 PKIX_CACHECERTCHAINLOOKUPFAILED); | |
1768 | |
1769 } | |
1770 } | |
1771 | |
1772 /* | |
1773 * XXX need to verify if Cert is trusted, hence may not | |
1774 * be worth it to have the Cert Cached or | |
1775 * If it is trusted, don't cache, but once there is cached | |
1776 * certs, we won't get certs from database any more. | |
1777 * can use flag to force not getting certs from cache | |
1778 */ | |
1779 if (!foundInCache) { | |
1780 | |
1781 if (nbioContext == NULL) { | |
1782 PKIX_CHECK(PKIX_CertStore_GetCertCallback | |
1783 (certStore, &getCerts, plContext), | |
1784 PKIX_CERTSTOREGETCERTCALLBACKFAILED); | |
1785 | |
1786 PKIX_CHECK(getCerts | |
1787 (certStore, | |
1788 state->certSel, | |
1789 state->verifyNode, | |
1790 &nbioContext, | |
1791 &certsFound, | |
1792 plContext), | |
1793 PKIX_GETCERTSFAILED); | |
1794 } else { | |
1795 PKIX_CHECK(PKIX_CertStore_CertContinue | |
1796 (certStore, | |
1797 state->certSel, | |
1798 state->verifyNode, | |
1799 &nbioContext, | |
1800 &certsFound, | |
1801 plContext), | |
1802 PKIX_CERTSTORECERTCONTINUEFAILED); | |
1803 } | |
1804 | |
1805 if (certStoreIsCached && certsFound) { | |
1806 | |
1807 PKIX_CHECK(pkix_CacheCert_Add | |
1808 (certStore, | |
1809 certSelParams, | |
1810 certsFound, | |
1811 plContext), | |
1812 PKIX_CACHECERTADDFAILED); | |
1813 } | |
1814 } | |
1815 | |
1816 /* | |
1817 * getCerts returns an empty list for "NONE FOUND", | |
1818 * a NULL list for "would block" | |
1819 */ | |
1820 if (certsFound == NULL) { | |
1821 state->status = BUILD_GATHERPENDING; | |
1822 *pNBIOContext = nbioContext; | |
1823 goto cleanup; | |
1824 } | |
1825 } | |
1826 | |
1827 /* Are there any more certStores to query? */ | |
1828 PKIX_DECREF(certStore); | |
1829 ++(state->certStoreIndex); | |
1830 } | |
1831 | |
1832 if (certsFound && certsFound->length > 1) { | |
1833 PKIX_List *sorted = NULL; | |
1834 | |
1835 /* sort Certs to try to optimize search */ | |
1836 PKIX_CHECK(pkix_Build_SortCandidateCerts | |
1837 (certsFound, &sorted, plContext), | |
1838 PKIX_BUILDSORTCANDIDATECERTSFAILED); | |
1839 PKIX_DECREF(certsFound); | |
1840 certsFound = sorted; | |
1841 } | |
1842 | |
1843 PKIX_CHECK( | |
1844 pkix_Build_SelectCertsFromTrustAnchors( | |
1845 state->buildConstants.anchors, | |
1846 certSelParams, &trustedCertList, | |
1847 plContext), | |
1848 PKIX_FAILTOSELECTCERTSFROMANCHORS); | |
1849 PKIX_CHECK( | |
1850 pkix_Build_RemoveDupUntrustedCerts(trustedCertList, | |
1851 certsFound, | |
1852 plContext), | |
1853 PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED); | |
1854 | |
1855 PKIX_CHECK( | |
1856 pkix_List_MergeLists(trustedCertList, | |
1857 certsFound, | |
1858 &state->candidateCerts, | |
1859 plContext), | |
1860 PKIX_LISTMERGEFAILED); | |
1861 | |
1862 /* No, return the list we have gathered */ | |
1863 PKIX_CHECK(PKIX_List_GetLength | |
1864 (state->candidateCerts, &state->numCerts, plContext), | |
1865 PKIX_LISTGETLENGTHFAILED); | |
1866 | |
1867 state->certIndex = 0; | |
1868 | |
1869 cleanup: | |
1870 PKIX_DECREF(trustedCertList); | |
1871 PKIX_DECREF(certStore); | |
1872 PKIX_DECREF(certsFound); | |
1873 | |
1874 PKIX_RETURN(BUILD); | |
1875 } | |
1876 | |
1877 /* | |
1878 * FUNCTION: pkix_Build_UpdateDate | |
1879 * DESCRIPTION: | |
1880 * | |
1881 * This function updates the validityDate contained in "state", for the current | |
1882 * CertChain contained in "state", to include the validityDate of the | |
1883 * candidateCert contained in "state". The validityDate of a chain is the | |
1884 * earliest of all the notAfter dates contained in the respective Certificates. | |
1885 * | |
1886 * PARAMETERS: | |
1887 * "state" | |
1888 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
1889 * "plContext" | |
1890 * Platform-specific context pointer. | |
1891 * THREAD SAFETY: | |
1892 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1893 * RETURNS: | |
1894 * Returns NULL if the function succeeds. | |
1895 * Returns a Build Error if the function fails in a non-fatal way | |
1896 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1897 */ | |
1898 static PKIX_Error * | |
1899 pkix_Build_UpdateDate( | |
1900 PKIX_ForwardBuilderState *state, | |
1901 void *plContext) | |
1902 { | |
1903 PKIX_Boolean canBeCached = PKIX_FALSE; | |
1904 PKIX_Int32 comparison = 0; | |
1905 PKIX_PL_Date *notAfter = NULL; | |
1906 | |
1907 PKIX_ENTER(BUILD, "pkix_Build_UpdateDate"); | |
1908 PKIX_NULLCHECK_ONE(state); | |
1909 | |
1910 PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag | |
1911 (state->candidateCert, &canBeCached, plContext), | |
1912 PKIX_CERTGETCACHEFLAGFAILED); | |
1913 | |
1914 state->canBeCached = state->canBeCached && canBeCached; | |
1915 if (state->canBeCached == PKIX_TRUE) { | |
1916 | |
1917 /* | |
1918 * So far, all certs can be cached. Update cert | |
1919 * chain validity time, which is the earliest of | |
1920 * all certs' notAfter times. | |
1921 */ | |
1922 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
1923 (state->candidateCert, ¬After, plContext), | |
1924 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
1925 | |
1926 if (state->validityDate == NULL) { | |
1927 state->validityDate = notAfter; | |
1928 notAfter = NULL; | |
1929 } else { | |
1930 PKIX_CHECK(PKIX_PL_Object_Compare | |
1931 ((PKIX_PL_Object *)state->validityDate, | |
1932 (PKIX_PL_Object *)notAfter, | |
1933 &comparison, | |
1934 plContext), | |
1935 PKIX_OBJECTCOMPARATORFAILED); | |
1936 if (comparison > 0) { | |
1937 PKIX_DECREF(state->validityDate); | |
1938 state->validityDate = notAfter; | |
1939 notAfter = NULL; | |
1940 } | |
1941 } | |
1942 } | |
1943 | |
1944 cleanup: | |
1945 | |
1946 PKIX_DECREF(notAfter); | |
1947 | |
1948 PKIX_RETURN(BUILD); | |
1949 } | |
1950 | |
1951 /* Prepare 'state' for the AIA round. */ | |
1952 static void | |
1953 pkix_PrepareForwardBuilderStateForAIA( | |
1954 PKIX_ForwardBuilderState *state) | |
1955 { | |
1956 PORT_Assert(state->useOnlyLocal == PKIX_TRUE); | |
1957 state->useOnlyLocal = PKIX_FALSE; | |
1958 state->certStoreIndex = 0; | |
1959 state->numFanout = state->buildConstants.maxFanout; | |
1960 state->status = BUILD_TRYAIA; | |
1961 } | |
1962 | |
1963 /* | |
1964 * FUNCTION: pkix_BuildForwardDepthFirstSearch | |
1965 * DESCRIPTION: | |
1966 * | |
1967 * This function performs a depth first search in the "forward" direction (from | |
1968 * the target Cert to the trust anchor). A non-NULL targetCert must be stored | |
1969 * in the ForwardBuilderState before this function is called. It is not written | |
1970 * recursively since execution may be suspended in in any of several places | |
1971 * pending completion of non-blocking I/O. This iterative structure makes it | |
1972 * much easier to resume where it left off. | |
1973 * | |
1974 * Since the nature of the search is recursive, the recursion is handled by | |
1975 * chaining states. That is, each new step involves creating a new | |
1976 * ForwardBuilderState linked to its predecessor. If a step turns out to be | |
1977 * fruitless, the state of the predecessor is restored and the next alternative | |
1978 * is tried. When a search is successful, values needed from the last state | |
1979 * (canBeCached and validityDate) are copied to the state provided by the | |
1980 * caller, so that the caller can retrieve those values. | |
1981 * | |
1982 * There are three return arguments, the NBIOContext, the ValidateResult and | |
1983 * the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is | |
1984 * suspended until the results of a non-blocking IO become available. The | |
1985 * caller may wait for the completion using platform-dependent methods and then | |
1986 * call this function again, allowing it to resume the search. If NBIOContext | |
1987 * is NULL and the ValidateResult is non-NULL, it means the search has | |
1988 * concluded successfully. If the NBIOContext is NULL but the ValidateResult is | |
1989 * NULL, it means the search was unsuccessful. | |
1990 * | |
1991 * This function performs several steps at each node in the constructed chain: | |
1992 * | |
1993 * 1) It retrieves Certs from the registered CertStores that match the | |
1994 * criteria established by the ForwardBuilderState pointed to by "state", such | |
1995 * as a subject name matching the issuer name of the previous Cert. If there | |
1996 * are no matching Certs, the function returns to the previous, or "parent", | |
1997 * state and tries to continue the chain building with another of the Certs | |
1998 * obtained from the CertStores as possible issuers for that parent Cert. | |
1999 * | |
2000 * 2) For each candidate Cert returned by the CertStores, this function checks | |
2001 * whether the Cert is valid. If it is trusted, this function checks whether | |
2002 * this Cert might serve as a TrustAnchor for a complete chain. | |
2003 * | |
2004 * 3) It determines whether this Cert, in conjunction with any of the | |
2005 * TrustAnchors, might complete a chain. A complete chain, from this or the | |
2006 * preceding step, is checked to see whether it is valid as a complete | |
2007 * chain, including the checks that cannot be done in the forward direction. | |
2008 * | |
2009 * 4) If this Cert chains successfully, but is not a complete chain, that is, | |
2010 * we have not reached a trusted Cert, a new ForwardBuilderState is created | |
2011 * with this Cert as the immediate predecessor, and we continue in step (1), | |
2012 * attempting to get Certs from the CertStores with this Certs "issuer" as | |
2013 * their subject. | |
2014 * | |
2015 * 5) If an entire chain validates successfully, then we are done. A | |
2016 * ValidateResult is created containing the Public Key of the target | |
2017 * certificate (including DSA parameter inheritance, if any) and the | |
2018 * PolicyNode representing the policy tree output by the validation algorithm, | |
2019 * and stored at pValResult, and the function exits returning NULL. | |
2020 * | |
2021 * 5) If the entire chain does not validate successfully, the algorithm | |
2022 * discards the latest Cert and continues in step 2 with the next candidate | |
2023 * Cert, backing up to a parent state when no more possibilities exist at a | |
2024 * given level, and returning failure when we try to back up but discover we | |
2025 * are at the top level. | |
2026 * | |
2027 * PARAMETERS: | |
2028 * "pNBIOContext" | |
2029 * Address at which platform-dependent information is returned if building | |
2030 * is suspended for non-blocking I/O. Must be non-NULL. | |
2031 * "pState" | |
2032 * Address at which input ForwardBuilderState is found, and at which output | |
2033 * ForwardBuilderState is stored. Must be non-NULL. | |
2034 * "pValResult" | |
2035 * Address at which the ValidateResult is stored. Must be non-NULL. | |
2036 * "plContext" | |
2037 * Platform-specific context pointer. | |
2038 * THREAD SAFETY: | |
2039 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
2040 * RETURNS: | |
2041 * Returns NULL if the function succeeds. | |
2042 * Returns a Build Error if the function fails in a non-fatal way. | |
2043 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
2044 */ | |
2045 static PKIX_Error * | |
2046 pkix_BuildForwardDepthFirstSearch( | |
2047 void **pNBIOContext, | |
2048 PKIX_ForwardBuilderState *state, | |
2049 PKIX_ValidateResult **pValResult, | |
2050 void *plContext) | |
2051 { | |
2052 PKIX_Boolean outOfOptions = PKIX_FALSE; | |
2053 PKIX_Boolean trusted = PKIX_FALSE; | |
2054 PKIX_Boolean isSelfIssued = PKIX_FALSE; | |
2055 PKIX_Boolean canBeCached = PKIX_FALSE; | |
2056 PKIX_Boolean revocationCheckingExists = PKIX_FALSE; | |
2057 PKIX_Boolean needsCRLChecking = PKIX_FALSE; | |
2058 PKIX_Boolean ioPending = PKIX_FALSE; | |
2059 PKIX_PL_Date *validityDate = NULL; | |
2060 PKIX_PL_Date *currTime = NULL; | |
2061 PKIX_Int32 childTraversedCACerts = 0; | |
2062 PKIX_UInt32 numSubjectNames = 0; | |
2063 PKIX_UInt32 numChained = 0; | |
2064 PKIX_Int32 cmpTimeResult = 0; | |
2065 PKIX_UInt32 i = 0; | |
2066 PKIX_UInt32 certsSoFar = 0; | |
2067 PKIX_List *childTraversedSubjNames = NULL; | |
2068 PKIX_List *subjectNames = NULL; | |
2069 PKIX_List *unfilteredCerts = NULL; | |
2070 PKIX_List *filteredCerts = NULL; | |
2071 PKIX_PL_Object *subjectName = NULL; | |
2072 PKIX_ValidateResult *valResult = NULL; | |
2073 PKIX_ForwardBuilderState *childState = NULL; | |
2074 PKIX_ForwardBuilderState *parentState = NULL; | |
2075 PKIX_PL_Object *revCheckerState = NULL; | |
2076 PKIX_ComCertSelParams *certSelParams = NULL; | |
2077 PKIX_TrustAnchor *trustAnchor = NULL; | |
2078 PKIX_PL_Cert *trustedCert = NULL; | |
2079 PKIX_VerifyNode *verifyNode = NULL; | |
2080 PKIX_Error *verifyError = NULL; | |
2081 PKIX_Error *finalError = NULL; | |
2082 void *nbio = NULL; | |
2083 PKIX_UInt32 numIterations = 0; | |
2084 | |
2085 PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch"); | |
2086 PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult); | |
2087 | |
2088 nbio = *pNBIOContext; | |
2089 *pNBIOContext = NULL; | |
2090 PKIX_INCREF(state->validityDate); | |
2091 validityDate = state->validityDate; | |
2092 canBeCached = state->canBeCached; | |
2093 PKIX_DECREF(*pValResult); | |
2094 | |
2095 /* | |
2096 * We return if successful; if we fall off the end | |
2097 * of this "while" clause our search has failed. | |
2098 */ | |
2099 while (outOfOptions == PKIX_FALSE) { | |
2100 /* | |
2101 * The maximum number of iterations works around a bug that | |
2102 * causes this while loop to never exit when AIA and cross | |
2103 * certificates are involved. See bug xxxxx. | |
2104 */ | |
2105 if (numIterations++ > 250) | |
2106 PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); | |
2107 | |
2108 if (state->buildConstants.maxTime != 0) { | |
2109 PKIX_DECREF(currTime); | |
2110 PKIX_CHECK(PKIX_PL_Date_Create_UTCTime | |
2111 (NULL, &currTime, plContext), | |
2112 PKIX_DATECREATEUTCTIMEFAILED); | |
2113 | |
2114 PKIX_CHECK(PKIX_PL_Object_Compare | |
2115 ((PKIX_PL_Object *)state->buildConstants.timeLimit, | |
2116 (PKIX_PL_Object *)currTime, | |
2117 &cmpTimeResult, | |
2118 plContext), | |
2119 PKIX_OBJECTCOMPARATORFAILED); | |
2120 | |
2121 if (cmpTimeResult < 0) { | |
2122 if (state->verifyNode != NULL) { | |
2123 PKIX_ERROR_CREATE | |
2124 (BUILD, | |
2125 PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS, | |
2126 verifyError); | |
2127 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
2128 (state->verifyNode, | |
2129 verifyError, | |
2130 plContext), | |
2131 PKIX_VERIFYNODESETERRORFAILED); | |
2132 PKIX_DECREF(finalError); | |
2133 finalError = verifyError; | |
2134 verifyError = NULL; | |
2135 } | |
2136 /* Even if we logged error, we still have to abort */ | |
2137 PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); | |
2138 } | |
2139 } | |
2140 | |
2141 if (state->status == BUILD_INITIAL) { | |
2142 | |
2143 PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext), | |
2144 PKIX_BUILDBUILDSELECTORANDPARAMSFAILED); | |
2145 | |
2146 /* | |
2147 * If the caller supplied a partial certChain (hintCerts) try | |
2148 * the next one from that List before we go to the certStores. | |
2149 */ | |
2150 if (state->buildConstants.numHintCerts > 0) { | |
2151 /* How many Certs does our trust chain have already? */ | |
2152 PKIX_CHECK(PKIX_List_GetLength | |
2153 (state->trustChain, &certsSoFar, plContext), | |
2154 PKIX_LISTGETLENGTHFAILED); | |
2155 | |
2156 /* That includes the target Cert. Don't count it. */ | |
2157 certsSoFar--; | |
2158 | |
2159 /* Are we still within range of the partial chain? */ | |
2160 if (certsSoFar >= state->buildConstants.numHintCerts) { | |
2161 state->status = BUILD_TRYAIA; | |
2162 } else { | |
2163 /* | |
2164 * If we already have n certs, we want the n+1th | |
2165 * (i.e., index = n) from the list of hints. | |
2166 */ | |
2167 PKIX_DECREF(state->candidateCert); | |
2168 PKIX_CHECK(PKIX_List_GetItem | |
2169 (state->buildConstants.hintCerts, | |
2170 certsSoFar, | |
2171 (PKIX_PL_Object **)&state->candidateCert, | |
2172 plContext), | |
2173 PKIX_LISTGETITEMFAILED); | |
2174 | |
2175 PKIX_CHECK(PKIX_List_AppendItem | |
2176 (state->candidateCerts, | |
2177 (PKIX_PL_Object *)state->candidateCert, | |
2178 plContext), | |
2179 PKIX_LISTAPPENDITEMFAILED); | |
2180 | |
2181 state->numCerts = 1; | |
2182 state->usingHintCerts = PKIX_TRUE; | |
2183 state->status = BUILD_CERTVALIDATING; | |
2184 } | |
2185 } else { | |
2186 state->status = BUILD_TRYAIA; | |
2187 } | |
2188 | |
2189 } | |
2190 | |
2191 if (state->status == BUILD_TRYAIA) { | |
2192 if (state->useOnlyLocal == PKIX_TRUE) { | |
2193 state->status = BUILD_COLLECTINGCERTS; | |
2194 } else { | |
2195 state->status = BUILD_AIAPENDING; | |
2196 } | |
2197 } | |
2198 | |
2199 if (state->status == BUILD_AIAPENDING && | |
2200 state->buildConstants.aiaMgr) { | |
2201 pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts | |
2202 (state->buildConstants.aiaMgr, | |
2203 state->prevCert, | |
2204 &nbio, | |
2205 &unfilteredCerts, | |
2206 plContext); | |
2207 | |
2208 if (nbio != NULL) { | |
2209 /* IO still pending, resume later */ | |
2210 *pNBIOContext = nbio; | |
2211 goto cleanup; | |
2212 } | |
2213 state->numCerts = 0; | |
2214 if (pkixErrorResult) { | |
2215 pkixErrorClass = pkixErrorResult->errClass; | |
2216 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
2217 goto fatal; | |
2218 } | |
2219 PKIX_DECREF(finalError); | |
2220 finalError = pkixErrorResult; | |
2221 pkixErrorResult = NULL; | |
2222 if (state->verifyNode != NULL) { | |
2223 /* state->verifyNode is the object that contains a list | |
2224 * of verifyNodes. verifyNodes contains cert chain | |
2225 * build failures that occurred on this level of chain | |
2226 * building. Here, creating new verify node | |
2227 * to log the failure and adding it to the list. */ | |
2228 PKIX_CHECK_FATAL(pkix_VerifyNode_Create | |
2229 (state->prevCert, | |
2230 0, NULL, | |
2231 &verifyNode, | |
2232 plContext), | |
2233 PKIX_VERIFYNODECREATEFAILED); | |
2234 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
2235 (verifyNode, finalError, plContext), | |
2236 PKIX_VERIFYNODESETERRORFAILED); | |
2237 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2238 (state->verifyNode, | |
2239 verifyNode, | |
2240 plContext), | |
2241 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2242 PKIX_DECREF(verifyNode); | |
2243 } | |
2244 } | |
2245 #ifdef PKIX_BUILDDEBUG | |
2246 /* Turn this on to trace the List of Certs, before CertSelect */ | |
2247 { | |
2248 PKIX_PL_String *unString; | |
2249 char *unAscii; | |
2250 PKIX_UInt32 length; | |
2251 PKIX_TOSTRING | |
2252 ((PKIX_PL_Object*)unfilteredCerts, | |
2253 &unString, | |
2254 plContext, | |
2255 PKIX_OBJECTTOSTRINGFAILED); | |
2256 | |
2257 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
2258 (unString, | |
2259 PKIX_ESCASCII, | |
2260 (void **)&unAscii, | |
2261 &length, | |
2262 plContext), | |
2263 PKIX_STRINGGETENCODEDFAILED); | |
2264 | |
2265 PKIX_DEBUG_ARG | |
2266 ("unfilteredCerts = %s\n", unAscii); | |
2267 PKIX_DECREF(unString); | |
2268 PKIX_FREE(unAscii); | |
2269 } | |
2270 #endif | |
2271 | |
2272 /* Note: Certs winnowed here don't get into VerifyTree. */ | |
2273 if (unfilteredCerts) { | |
2274 PKIX_CHECK(pkix_CertSelector_Select | |
2275 (state->certSel, | |
2276 unfilteredCerts, | |
2277 &filteredCerts, | |
2278 plContext), | |
2279 PKIX_CERTSELECTORSELECTFAILED); | |
2280 | |
2281 PKIX_DECREF(unfilteredCerts); | |
2282 | |
2283 PKIX_CHECK(PKIX_List_GetLength | |
2284 (filteredCerts, &(state->numCerts), plContext), | |
2285 PKIX_LISTGETLENGTHFAILED); | |
2286 | |
2287 #ifdef PKIX_BUILDDEBUG | |
2288 /* Turn this on to trace the List of Certs, after CertSelect */ | |
2289 { | |
2290 PKIX_PL_String *unString; | |
2291 char *unAscii; | |
2292 PKIX_UInt32 length; | |
2293 PKIX_TOSTRING | |
2294 ((PKIX_PL_Object*)filteredCerts, | |
2295 &unString, | |
2296 plContext, | |
2297 PKIX_OBJECTTOSTRINGFAILED); | |
2298 | |
2299 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
2300 (unString, | |
2301 PKIX_ESCASCII, | |
2302 (void **)&unAscii, | |
2303 &length, | |
2304 plContext), | |
2305 PKIX_STRINGGETENCODEDFAILED); | |
2306 | |
2307 PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii); | |
2308 PKIX_DECREF(unString); | |
2309 PKIX_FREE(unAscii); | |
2310 } | |
2311 #endif | |
2312 | |
2313 PKIX_DECREF(state->candidateCerts); | |
2314 state->candidateCerts = filteredCerts; | |
2315 state->certIndex = 0; | |
2316 filteredCerts = NULL; | |
2317 } | |
2318 | |
2319 /* Are there any Certs to try? */ | |
2320 if (state->numCerts > 0) { | |
2321 state->status = BUILD_CERTVALIDATING; | |
2322 } else { | |
2323 state->status = BUILD_COLLECTINGCERTS; | |
2324 } | |
2325 } | |
2326 | |
2327 PKIX_DECREF(certSelParams); | |
2328 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
2329 (state->certSel, &certSelParams, plContext), | |
2330 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
2331 | |
2332 /* **** Querying the CertStores ***** */ | |
2333 if ((state->status == BUILD_COLLECTINGCERTS) || | |
2334 (state->status == BUILD_GATHERPENDING)) { | |
2335 | |
2336 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
2337 PKIX_CHECK(pkix_ForwardBuilderState_DumpState | |
2338 (state, plContext), | |
2339 PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); | |
2340 #endif | |
2341 | |
2342 PKIX_CHECK(pkix_Build_GatherCerts | |
2343 (state, certSelParams, &nbio, plContext), | |
2344 PKIX_BUILDGATHERCERTSFAILED); | |
2345 | |
2346 if (nbio != NULL) { | |
2347 /* IO still pending, resume later */ | |
2348 *pNBIOContext = nbio; | |
2349 goto cleanup; | |
2350 } | |
2351 | |
2352 /* Are there any Certs to try? */ | |
2353 if (state->numCerts > 0) { | |
2354 state->status = BUILD_CERTVALIDATING; | |
2355 } else { | |
2356 state->status = BUILD_ABANDONNODE; | |
2357 } | |
2358 } | |
2359 | |
2360 /* ****Phase 2 - Chain building***** */ | |
2361 | |
2362 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
2363 PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext), | |
2364 PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); | |
2365 #endif | |
2366 | |
2367 if (state->status == BUILD_CERTVALIDATING) { | |
2368 revocationCheckingExists = | |
2369 (state->buildConstants.revChecker != NULL); | |
2370 | |
2371 PKIX_DECREF(state->candidateCert); | |
2372 PKIX_CHECK(PKIX_List_GetItem | |
2373 (state->candidateCerts, | |
2374 state->certIndex, | |
2375 (PKIX_PL_Object **)&(state->candidateCert), | |
2376 plContext), | |
2377 PKIX_LISTGETITEMFAILED); | |
2378 | |
2379 if ((state->verifyNode) != NULL) { | |
2380 PKIX_CHECK_FATAL(pkix_VerifyNode_Create | |
2381 (state->candidateCert, | |
2382 0, | |
2383 NULL, | |
2384 &verifyNode, | |
2385 plContext), | |
2386 PKIX_VERIFYNODECREATEFAILED); | |
2387 } | |
2388 | |
2389 /* If failure, this function sets Error in verifyNode */ | |
2390 verifyError = pkix_Build_VerifyCertificate | |
2391 (state, | |
2392 state->buildConstants.userCheckers, | |
2393 revocationCheckingExists, | |
2394 &trusted, | |
2395 &needsCRLChecking, | |
2396 verifyNode, | |
2397 plContext); | |
2398 | |
2399 if (verifyError) { | |
2400 pkixTempErrorReceived = PKIX_TRUE; | |
2401 pkixErrorClass = verifyError->errClass; | |
2402 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
2403 pkixErrorResult = verifyError; | |
2404 verifyError = NULL; | |
2405 goto fatal; | |
2406 } | |
2407 } | |
2408 | |
2409 if (PKIX_ERROR_RECEIVED) { | |
2410 if (state->verifyNode != NULL) { | |
2411 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
2412 (verifyNode, verifyError, plContext), | |
2413 PKIX_VERIFYNODESETERRORFAILED); | |
2414 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2415 (state->verifyNode, | |
2416 verifyNode, | |
2417 plContext), | |
2418 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2419 PKIX_DECREF(verifyNode); | |
2420 } | |
2421 pkixTempErrorReceived = PKIX_FALSE; | |
2422 PKIX_DECREF(finalError); | |
2423 finalError = verifyError; | |
2424 verifyError = NULL; | |
2425 if (state->certLoopingDetected) { | |
2426 PKIX_ERROR | |
2427 (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
2428 } | |
2429 state->status = BUILD_GETNEXTCERT; | |
2430 } else if (needsCRLChecking) { | |
2431 state->status = BUILD_CRLPREP; | |
2432 } else { | |
2433 state->status = BUILD_DATEPREP; | |
2434 } | |
2435 } | |
2436 | |
2437 if (state->status == BUILD_CRLPREP) { | |
2438 PKIX_RevocationStatus revStatus; | |
2439 PKIX_UInt32 reasonCode; | |
2440 | |
2441 verifyError = | |
2442 PKIX_RevocationChecker_Check( | |
2443 state->prevCert, state->candidateCert, | |
2444 state->buildConstants.revChecker, | |
2445 state->buildConstants.procParams, | |
2446 PKIX_FALSE, | |
2447 (state->parentState == NULL) ? | |
2448 PKIX_TRUE : PKIX_FALSE, | |
2449 &revStatus, &reasonCode, | |
2450 &nbio, plContext); | |
2451 if (nbio != NULL) { | |
2452 *pNBIOContext = nbio; | |
2453 goto cleanup; | |
2454 } | |
2455 if (revStatus == PKIX_RevStatus_Revoked || verifyError) { | |
2456 if (!verifyError) { | |
2457 /* if verifyError is returned then use it as | |
2458 * it has a detailed revocation error code. | |
2459 * Otherwise create a new error */ | |
2460 PKIX_ERROR_CREATE(VALIDATE, PKIX_CERTIFICATEREVOKED, | |
2461 verifyError); | |
2462 } | |
2463 if (state->verifyNode != NULL) { | |
2464 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
2465 (verifyNode, verifyError, plContext), | |
2466 PKIX_VERIFYNODESETERRORFAILED); | |
2467 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2468 (state->verifyNode, | |
2469 verifyNode, | |
2470 plContext), | |
2471 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2472 PKIX_DECREF(verifyNode); | |
2473 } | |
2474 PKIX_DECREF(finalError); | |
2475 finalError = verifyError; | |
2476 verifyError = NULL; | |
2477 if (state->certLoopingDetected) { | |
2478 PKIX_ERROR | |
2479 (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
2480 } | |
2481 state->status = BUILD_GETNEXTCERT; | |
2482 } else { | |
2483 state->status = BUILD_DATEPREP; | |
2484 } | |
2485 } | |
2486 | |
2487 if (state->status == BUILD_DATEPREP) { | |
2488 /* Keep track of whether this chain can be cached */ | |
2489 PKIX_CHECK(pkix_Build_UpdateDate(state, plContext), | |
2490 PKIX_BUILDUPDATEDATEFAILED); | |
2491 | |
2492 canBeCached = state->canBeCached; | |
2493 PKIX_DECREF(validityDate); | |
2494 PKIX_INCREF(state->validityDate); | |
2495 validityDate = state->validityDate; | |
2496 if (trusted == PKIX_TRUE) { | |
2497 state->status = BUILD_CHECKTRUSTED; | |
2498 } else { | |
2499 state->status = BUILD_ADDTOCHAIN; | |
2500 } | |
2501 } | |
2502 | |
2503 if (state->status == BUILD_CHECKTRUSTED) { | |
2504 | |
2505 /* | |
2506 * If this cert is trusted, try to validate the entire | |
2507 * chain using this certificate as trust anchor. | |
2508 */ | |
2509 PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert | |
2510 (state->candidateCert, | |
2511 &trustAnchor, | |
2512 plContext), | |
2513 PKIX_TRUSTANCHORCREATEWITHCERTFAILED); | |
2514 | |
2515 PKIX_CHECK(pkix_Build_ValidationCheckers | |
2516 (state, | |
2517 state->trustChain, | |
2518 trustAnchor, | |
2519 PKIX_FALSE, /* do not add eku checker | |
2520 * since eku was already | |
2521 * checked */ | |
2522 plContext), | |
2523 PKIX_BUILDVALIDATIONCHECKERSFAILED); | |
2524 | |
2525 state->status = BUILD_CHECKTRUSTED2; | |
2526 } | |
2527 | |
2528 if (state->status == BUILD_CHECKTRUSTED2) { | |
2529 verifyError = | |
2530 pkix_Build_ValidateEntireChain(state, | |
2531 trustAnchor, | |
2532 &nbio, &valResult, | |
2533 verifyNode, | |
2534 plContext); | |
2535 if (nbio != NULL) { | |
2536 /* IO still pending, resume later */ | |
2537 goto cleanup; | |
2538 } else { | |
2539 /* checking the error for fatal status */ | |
2540 if (verifyError) { | |
2541 pkixTempErrorReceived = PKIX_TRUE; | |
2542 pkixErrorClass = verifyError->errClass; | |
2543 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
2544 pkixErrorResult = verifyError; | |
2545 verifyError = NULL; | |
2546 goto fatal; | |
2547 } | |
2548 } | |
2549 if (state->verifyNode != NULL) { | |
2550 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2551 (state->verifyNode, | |
2552 verifyNode, | |
2553 plContext), | |
2554 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2555 PKIX_DECREF(verifyNode); | |
2556 } | |
2557 if (!PKIX_ERROR_RECEIVED) { | |
2558 *pValResult = valResult; | |
2559 valResult = NULL; | |
2560 /* Change state so IsIOPending is FALSE */ | |
2561 state->status = BUILD_CHECKTRUSTED; | |
2562 goto cleanup; | |
2563 } | |
2564 PKIX_DECREF(finalError); | |
2565 finalError = verifyError; | |
2566 verifyError = NULL; | |
2567 /* Reset temp error that was set by | |
2568 * PKIX_CHECK_ONLY_FATAL and continue */ | |
2569 pkixTempErrorReceived = PKIX_FALSE; | |
2570 PKIX_DECREF(trustAnchor); | |
2571 } | |
2572 | |
2573 /* | |
2574 * If chain doesn't validate with a trusted Cert, | |
2575 * adding more Certs to it can't help. | |
2576 */ | |
2577 if (state->certLoopingDetected) { | |
2578 PKIX_DECREF(verifyError); | |
2579 PKIX_ERROR_CREATE(BUILD, | |
2580 PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, | |
2581 verifyError); | |
2582 PKIX_CHECK_FATAL( | |
2583 pkix_VerifyNode_SetError(state->verifyNode, | |
2584 verifyError, | |
2585 plContext), | |
2586 PKIX_VERIFYNODESETERRORFAILED); | |
2587 PKIX_DECREF(verifyError); | |
2588 } | |
2589 state->status = BUILD_GETNEXTCERT; | |
2590 } | |
2591 | |
2592 /* | |
2593 * This Cert was not trusted. Add it to our chain, and | |
2594 * continue building. If we don't reach a trust anchor, | |
2595 * we'll take it off later and continue without it. | |
2596 */ | |
2597 if (state->status == BUILD_ADDTOCHAIN) { | |
2598 PKIX_CHECK(PKIX_List_AppendItem | |
2599 (state->trustChain, | |
2600 (PKIX_PL_Object *)state->candidateCert, | |
2601 plContext), | |
2602 PKIX_LISTAPPENDITEMFAILED); | |
2603 | |
2604 state->status = BUILD_EXTENDCHAIN; | |
2605 } | |
2606 | |
2607 if (state->status == BUILD_EXTENDCHAIN) { | |
2608 | |
2609 /* Check whether we are allowed to extend the chain */ | |
2610 if ((state->buildConstants.maxDepth != 0) && | |
2611 (state->numDepth <= 1)) { | |
2612 | |
2613 if (state->verifyNode != NULL) { | |
2614 PKIX_ERROR_CREATE | |
2615 (BUILD, | |
2616 PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS, | |
2617 verifyError); | |
2618 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
2619 (verifyNode, verifyError, plContext), | |
2620 PKIX_VERIFYNODESETERRORFAILED); | |
2621 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2622 (state->verifyNode, verifyNode, plContext), | |
2623 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2624 PKIX_DECREF(verifyNode); | |
2625 PKIX_DECREF(finalError); | |
2626 finalError = verifyError; | |
2627 verifyError = NULL; | |
2628 } | |
2629 /* Even if error logged, still need to abort */ | |
2630 PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS); | |
2631 } | |
2632 | |
2633 PKIX_CHECK(pkix_IsCertSelfIssued | |
2634 (state->candidateCert, &isSelfIssued, plContext), | |
2635 PKIX_ISCERTSELFISSUEDFAILED); | |
2636 | |
2637 PKIX_CHECK(PKIX_PL_Object_Duplicate | |
2638 ((PKIX_PL_Object *)state->traversedSubjNames, | |
2639 (PKIX_PL_Object **)&childTraversedSubjNames, | |
2640 plContext), | |
2641 PKIX_OBJECTDUPLICATEFAILED); | |
2642 | |
2643 if (isSelfIssued) { | |
2644 childTraversedCACerts = state->traversedCACerts; | |
2645 } else { | |
2646 childTraversedCACerts = state->traversedCACerts + 1; | |
2647 | |
2648 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
2649 (state->candidateCert, | |
2650 &subjectNames, | |
2651 plContext), | |
2652 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
2653 | |
2654 if (subjectNames) { | |
2655 PKIX_CHECK(PKIX_List_GetLength | |
2656 (subjectNames, | |
2657 &numSubjectNames, | |
2658 plContext), | |
2659 PKIX_LISTGETLENGTHFAILED); | |
2660 | |
2661 } else { | |
2662 numSubjectNames = 0; | |
2663 } | |
2664 | |
2665 for (i = 0; i < numSubjectNames; i++) { | |
2666 PKIX_CHECK(PKIX_List_GetItem | |
2667 (subjectNames, | |
2668 i, | |
2669 &subjectName, | |
2670 plContext), | |
2671 PKIX_LISTGETITEMFAILED); | |
2672 PKIX_NULLCHECK_ONE | |
2673 (state->traversedSubjNames); | |
2674 PKIX_CHECK(PKIX_List_AppendItem | |
2675 (state->traversedSubjNames, | |
2676 subjectName, | |
2677 plContext), | |
2678 PKIX_LISTAPPENDITEMFAILED); | |
2679 PKIX_DECREF(subjectName); | |
2680 } | |
2681 PKIX_DECREF(subjectNames); | |
2682 } | |
2683 | |
2684 PKIX_CHECK(pkix_ForwardBuilderState_Create | |
2685 (childTraversedCACerts, | |
2686 state->buildConstants.maxFanout, | |
2687 state->numDepth - 1, | |
2688 state->revCheckDelayed, | |
2689 canBeCached, | |
2690 validityDate, | |
2691 state->candidateCert, | |
2692 childTraversedSubjNames, | |
2693 state->trustChain, | |
2694 state, | |
2695 &childState, | |
2696 plContext), | |
2697 PKIX_FORWARDBUILDSTATECREATEFAILED); | |
2698 | |
2699 PKIX_DECREF(childTraversedSubjNames); | |
2700 PKIX_DECREF(certSelParams); | |
2701 childState->verifyNode = verifyNode; | |
2702 verifyNode = NULL; | |
2703 PKIX_DECREF(state); | |
2704 state = childState; /* state->status == BUILD_INITIAL */ | |
2705 childState = NULL; | |
2706 continue; /* with while (!outOfOptions) */ | |
2707 } | |
2708 | |
2709 if (state->status == BUILD_GETNEXTCERT) { | |
2710 pkixTempErrorReceived = PKIX_FALSE; | |
2711 PKIX_DECREF(state->candidateCert); | |
2712 | |
2713 /* | |
2714 * If we were using a Cert from the callier-supplied partial | |
2715 * chain, delete it and go to the certStores. | |
2716 */ | |
2717 if (state->usingHintCerts == PKIX_TRUE) { | |
2718 PKIX_DECREF(state->candidateCerts); | |
2719 PKIX_CHECK(PKIX_List_Create | |
2720 (&state->candidateCerts, plContext), | |
2721 PKIX_LISTCREATEFAILED); | |
2722 | |
2723 state->numCerts = 0; | |
2724 state->usingHintCerts = PKIX_FALSE; | |
2725 state->status = BUILD_TRYAIA; | |
2726 continue; | |
2727 } else if (++(state->certIndex) < (state->numCerts)) { | |
2728 if ((state->buildConstants.maxFanout != 0) && | |
2729 (--(state->numFanout) == 0)) { | |
2730 | |
2731 if (state->verifyNode != NULL) { | |
2732 PKIX_ERROR_CREATE | |
2733 (BUILD, | |
2734 PKIX_FANOUTEXCEEDSRESOURCELIMITS, | |
2735 verifyError); | |
2736 PKIX_CHECK_FATAL | |
2737 (pkix_VerifyNode_SetError | |
2738 (state->verifyNode, | |
2739 verifyError, | |
2740 plContext), | |
2741 PKIX_VERIFYNODESETERRORFAILED); | |
2742 PKIX_DECREF(finalError); | |
2743 finalError = verifyError; | |
2744 verifyError = NULL; | |
2745 } | |
2746 /* Even if error logged, still need to abort */ | |
2747 PKIX_ERROR | |
2748 (PKIX_FANOUTEXCEEDSRESOURCELIMITS); | |
2749 } | |
2750 state->status = BUILD_CERTVALIDATING; | |
2751 continue; | |
2752 } | |
2753 } | |
2754 | |
2755 /* | |
2756 * Adding the current cert to the chain didn't help. If our search | |
2757 * has been restricted to local certStores, try opening up the | |
2758 * search and see whether that helps. Otherwise, back up to the | |
2759 * parent cert, and see if there are any more to try. | |
2760 */ | |
2761 if (state->useOnlyLocal == PKIX_TRUE) { | |
2762 pkix_PrepareForwardBuilderStateForAIA(state); | |
2763 } else do { | |
2764 if (state->parentState == NULL) { | |
2765 /* We are at the top level, and can't back up! */ | |
2766 outOfOptions = PKIX_TRUE; | |
2767 } else { | |
2768 /* | |
2769 * Try the next cert, if any, for this parent. | |
2770 * Otherwise keep backing up until we reach a | |
2771 * parent with more certs to try. | |
2772 */ | |
2773 PKIX_CHECK(PKIX_List_GetLength | |
2774 (state->trustChain, &numChained, plContext), | |
2775 PKIX_LISTGETLENGTHFAILED); | |
2776 PKIX_CHECK(PKIX_List_DeleteItem | |
2777 (state->trustChain, numChained - 1, plContext), | |
2778 PKIX_LISTDELETEITEMFAILED); | |
2779 | |
2780 /* local and aia fetching returned no good certs. | |
2781 * Creating a verify node in the parent that tells | |
2782 * us this. */ | |
2783 if (!state->verifyNode) { | |
2784 PKIX_CHECK_FATAL( | |
2785 pkix_VerifyNode_Create(state->prevCert, | |
2786 0, NULL, | |
2787 &state->verifyNode, | |
2788 plContext), | |
2789 PKIX_VERIFYNODECREATEFAILED); | |
2790 } | |
2791 /* Updating the log with the error. */ | |
2792 PKIX_DECREF(verifyError); | |
2793 PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, | |
2794 verifyError); | |
2795 PKIX_CHECK_FATAL( | |
2796 pkix_VerifyNode_SetError(state->verifyNode, | |
2797 verifyError, | |
2798 plContext), | |
2799 PKIX_VERIFYNODESETERRORFAILED); | |
2800 PKIX_DECREF(verifyError); | |
2801 | |
2802 PKIX_INCREF(state->parentState); | |
2803 parentState = state->parentState; | |
2804 PKIX_DECREF(verifyNode); | |
2805 verifyNode = state->verifyNode; | |
2806 state->verifyNode = NULL; | |
2807 PKIX_DECREF(state); | |
2808 state = parentState; | |
2809 parentState = NULL; | |
2810 if (state->verifyNode != NULL && verifyNode) { | |
2811 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2812 (state->verifyNode, | |
2813 verifyNode, | |
2814 plContext), | |
2815 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2816 PKIX_DECREF(verifyNode); | |
2817 } | |
2818 PKIX_DECREF(validityDate); | |
2819 PKIX_INCREF(state->validityDate); | |
2820 validityDate = state->validityDate; | |
2821 canBeCached = state->canBeCached; | |
2822 | |
2823 /* Are there any more Certs to try? */ | |
2824 if (++(state->certIndex) < (state->numCerts)) { | |
2825 state->status = BUILD_CERTVALIDATING; | |
2826 PKIX_DECREF(state->candidateCert); | |
2827 break; | |
2828 } | |
2829 if (state->useOnlyLocal == PKIX_TRUE) { | |
2830 /* Clean up and go for AIA round. */ | |
2831 pkix_PrepareForwardBuilderStateForAIA(state); | |
2832 break; | |
2833 } | |
2834 } | |
2835 PKIX_DECREF(state->candidateCert); | |
2836 } while (outOfOptions == PKIX_FALSE); | |
2837 | |
2838 } /* while (outOfOptions == PKIX_FALSE) */ | |
2839 | |
2840 cleanup: | |
2841 | |
2842 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
2843 goto fatal; | |
2844 } | |
2845 | |
2846 /* verifyNode should be equal to NULL at this point. Assert it. | |
2847 * Temporarelly use verifyError to store an error ref to which we | |
2848 * have in pkixErrorResult. This is done to prevent error cloberring | |
2849 * while using macros below. */ | |
2850 PORT_Assert(verifyError == NULL); | |
2851 verifyError = pkixErrorResult; | |
2852 | |
2853 /* | |
2854 * We were called with an initialState that had no parent. If we are | |
2855 * returning with an error or with a result, we must destroy any state | |
2856 * that we created (any state with a parent). | |
2857 */ | |
2858 | |
2859 PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending | |
2860 (state, &ioPending, plContext), | |
2861 PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED); | |
2862 | |
2863 if (ioPending == PKIX_FALSE) { | |
2864 while (state->parentState) { | |
2865 PKIX_INCREF(state->parentState); | |
2866 parentState = state->parentState; | |
2867 PKIX_DECREF(verifyNode); | |
2868 verifyNode = state->verifyNode; | |
2869 state->verifyNode = NULL; | |
2870 PKIX_DECREF(state); | |
2871 state = parentState; | |
2872 parentState = NULL; | |
2873 if (state->verifyNode != NULL && verifyNode) { | |
2874 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
2875 (state->verifyNode, | |
2876 verifyNode, | |
2877 plContext), | |
2878 PKIX_VERIFYNODEADDTOTREEFAILED); | |
2879 PKIX_DECREF(verifyNode); | |
2880 } | |
2881 } | |
2882 state->canBeCached = canBeCached; | |
2883 PKIX_DECREF(state->validityDate); | |
2884 state->validityDate = validityDate; | |
2885 validityDate = NULL; | |
2886 } | |
2887 if (!*pValResult && !verifyError) { | |
2888 if (!finalError) { | |
2889 PKIX_CHECK_FATAL( | |
2890 pkix_VerifyNode_FindError(state->verifyNode, | |
2891 &finalError, | |
2892 plContext), | |
2893 PKIX_VERIFYNODEFINDERRORFAILED); | |
2894 } | |
2895 if (finalError) { | |
2896 pkixErrorResult = finalError; | |
2897 pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED; | |
2898 finalError = NULL; | |
2899 goto fatal; | |
2900 } | |
2901 pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER; | |
2902 pkixErrorReceived = PKIX_TRUE; | |
2903 PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, | |
2904 verifyError); | |
2905 PKIX_CHECK_FATAL( | |
2906 pkix_VerifyNode_SetError(state->verifyNode, verifyError, | |
2907 plContext), | |
2908 PKIX_VERIFYNODESETERRORFAILED); | |
2909 } else { | |
2910 pkixErrorResult = verifyError; | |
2911 verifyError = NULL; | |
2912 } | |
2913 | |
2914 fatal: | |
2915 if (state->parentState) { | |
2916 /* parentState in "state" object should be NULL at this point. | |
2917 * If itn't, that means that we got fatal error(we have jumped to | |
2918 * "fatal" label) and we should destroy all state except the top one
. */ | |
2919 while (state->parentState) { | |
2920 PKIX_Error *error = NULL; | |
2921 PKIX_ForwardBuilderState *prntState = state->parentState; | |
2922 /* Dumb: need to increment parentState to avoid destruction | |
2923 * of "build constants"(they get destroyed when parentState is | |
2924 * set to NULL. */ | |
2925 PKIX_INCREF(prntState); | |
2926 error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext)
; | |
2927 if (error) { | |
2928 PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext); | |
2929 } | |
2930 /* No need to decref the parent state. It was already done by | |
2931 * pkix_ForwardBuilderState_Destroy function. */ | |
2932 state = prntState; | |
2933 } | |
2934 } | |
2935 PKIX_DECREF(parentState); | |
2936 PKIX_DECREF(childState); | |
2937 PKIX_DECREF(valResult); | |
2938 PKIX_DECREF(verifyError); | |
2939 PKIX_DECREF(finalError); | |
2940 PKIX_DECREF(verifyNode); | |
2941 PKIX_DECREF(childTraversedSubjNames); | |
2942 PKIX_DECREF(certSelParams); | |
2943 PKIX_DECREF(subjectNames); | |
2944 PKIX_DECREF(subjectName); | |
2945 PKIX_DECREF(trustAnchor); | |
2946 PKIX_DECREF(validityDate); | |
2947 PKIX_DECREF(revCheckerState); | |
2948 PKIX_DECREF(currTime); | |
2949 PKIX_DECREF(filteredCerts); | |
2950 PKIX_DECREF(unfilteredCerts); | |
2951 PKIX_DECREF(trustedCert); | |
2952 | |
2953 PKIX_RETURN(BUILD); | |
2954 } | |
2955 | |
2956 /* | |
2957 * FUNCTION: pkix_Build_CheckInCache | |
2958 * DESCRIPTION: | |
2959 * | |
2960 * The function tries to locate a chain for a cert in the cert chain cache. | |
2961 * If found, the chain goes through revocation chacking and returned back to | |
2962 * caller. Chains that fail revocation check get removed from cache. | |
2963 * | |
2964 * PARAMETERS: | |
2965 * "state" | |
2966 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
2967 * "pBuildResult" | |
2968 * Address at which the BuildResult is stored, after a successful build. | |
2969 * Must be non-NULL. | |
2970 * "pNBIOContext" | |
2971 * Address at which the NBIOContext is stored indicating whether the | |
2972 * validation is complete. Must be non-NULL. | |
2973 * "plContext" | |
2974 * Platform-specific context pointer. | |
2975 * THREAD SAFETY: | |
2976 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
2977 * RETURNS: | |
2978 * Returns NULL if the function succeeds. | |
2979 * Returns a Build Error if the function fails in a non-fatal way | |
2980 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
2981 */ | |
2982 static PKIX_Error* | |
2983 pkix_Build_CheckInCache( | |
2984 PKIX_ForwardBuilderState *state, | |
2985 PKIX_BuildResult **pBuildResult, | |
2986 void **pNBIOContext, | |
2987 void *plContext) | |
2988 { | |
2989 PKIX_PL_Cert *targetCert = NULL; | |
2990 PKIX_List *anchors = NULL; | |
2991 PKIX_PL_Date *testDate = NULL; | |
2992 PKIX_BuildResult *buildResult = NULL; | |
2993 PKIX_ValidateResult *valResult = NULL; | |
2994 PKIX_Error *buildError = NULL; | |
2995 PKIX_TrustAnchor *matchingAnchor = NULL; | |
2996 PKIX_PL_Cert *trustedCert = NULL; | |
2997 PKIX_List *certList = NULL; | |
2998 PKIX_Boolean cacheHit = PKIX_FALSE; | |
2999 PKIX_Boolean trusted = PKIX_FALSE; | |
3000 PKIX_Boolean stillValid = PKIX_FALSE; | |
3001 void *nbioContext = NULL; | |
3002 | |
3003 PKIX_ENTER(BUILD, "pkix_Build_CheckInCache"); | |
3004 | |
3005 nbioContext = *pNBIOContext; | |
3006 *pNBIOContext = NULL; | |
3007 | |
3008 targetCert = state->buildConstants.targetCert; | |
3009 anchors = state->buildConstants.anchors; | |
3010 testDate = state->buildConstants.testDate; | |
3011 | |
3012 /* Check whether this cert verification has been cached. */ | |
3013 PKIX_CHECK(pkix_CacheCertChain_Lookup | |
3014 (targetCert, | |
3015 anchors, | |
3016 testDate, | |
3017 &cacheHit, | |
3018 &buildResult, | |
3019 plContext), | |
3020 PKIX_CACHECERTCHAINLOOKUPFAILED); | |
3021 | |
3022 if (!cacheHit) { | |
3023 goto cleanup; | |
3024 } | |
3025 | |
3026 /* | |
3027 * We found something in cache. Verify that the anchor | |
3028 * cert is still trusted, | |
3029 */ | |
3030 PKIX_CHECK(PKIX_BuildResult_GetValidateResult | |
3031 (buildResult, &valResult, plContext), | |
3032 PKIX_BUILDRESULTGETVALIDATERESULTFAILED); | |
3033 | |
3034 PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor | |
3035 (valResult, &matchingAnchor, plContext), | |
3036 PKIX_VALIDATERESULTGETTRUSTANCHORFAILED); | |
3037 | |
3038 PKIX_DECREF(valResult); | |
3039 | |
3040 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
3041 (matchingAnchor, &trustedCert, plContext), | |
3042 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
3043 | |
3044 if (state->buildConstants.anchors && | |
3045 state->buildConstants.anchors->length) { | |
3046 /* Check if it is one of the trust anchors */ | |
3047 PKIX_CHECK( | |
3048 pkix_List_Contains(state->buildConstants.anchors, | |
3049 (PKIX_PL_Object *)matchingAnchor, | |
3050 &trusted, | |
3051 plContext), | |
3052 PKIX_LISTCONTAINSFAILED); | |
3053 } else { | |
3054 PKIX_CHECK(PKIX_PL_Cert_IsCertTrusted | |
3055 (trustedCert, PKIX_FALSE, &trusted, plContext), | |
3056 PKIX_CERTISCERTTRUSTEDFAILED); | |
3057 } | |
3058 | |
3059 if (!trusted) { | |
3060 goto cleanup; | |
3061 } | |
3062 /* | |
3063 * Since the key usage may vary for different | |
3064 * applications, we need to verify the chain again. | |
3065 * Reverification will be improved with a fix for 397805. | |
3066 */ | |
3067 PKIX_CHECK(PKIX_BuildResult_GetCertChain | |
3068 (buildResult, &certList, plContext), | |
3069 PKIX_BUILDRESULTGETCERTCHAINFAILED); | |
3070 | |
3071 PKIX_CHECK(pkix_Build_ValidationCheckers | |
3072 (state, | |
3073 certList, | |
3074 matchingAnchor, | |
3075 PKIX_TRUE, /* Chain revalidation stage. */ | |
3076 plContext), | |
3077 PKIX_BUILDVALIDATIONCHECKERSFAILED); | |
3078 | |
3079 PKIX_CHECK_ONLY_FATAL( | |
3080 pkix_Build_ValidateEntireChain(state, matchingAnchor, | |
3081 &nbioContext, &valResult, | |
3082 state->verifyNode, plContext), | |
3083 PKIX_BUILDVALIDATEENTIRECHAINFAILED); | |
3084 | |
3085 if (nbioContext != NULL) { | |
3086 /* IO still pending, resume later */ | |
3087 *pNBIOContext = nbioContext; | |
3088 goto cleanup; | |
3089 } | |
3090 if (!PKIX_ERROR_RECEIVED) { | |
3091 /* The result from cache is still valid. But we replace an old*/ | |
3092 *pBuildResult = buildResult; | |
3093 buildResult = NULL; | |
3094 stillValid = PKIX_TRUE; | |
3095 } | |
3096 | |
3097 cleanup: | |
3098 | |
3099 if (!nbioContext && cacheHit && !(trusted && stillValid)) { | |
3100 /* The anchor of this chain is no longer trusted or | |
3101 * chain cert(s) has been revoked. | |
3102 * Invalidate this result in the cache */ | |
3103 buildError = pkixErrorResult; | |
3104 PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove | |
3105 (targetCert, | |
3106 anchors, | |
3107 plContext), | |
3108 PKIX_CACHECERTCHAINREMOVEFAILED); | |
3109 pkixErrorResult = buildError; | |
3110 buildError = NULL; | |
3111 } | |
3112 | |
3113 fatal: | |
3114 PKIX_DECREF(buildResult); | |
3115 PKIX_DECREF(valResult); | |
3116 PKIX_DECREF(buildError); | |
3117 PKIX_DECREF(certList); | |
3118 PKIX_DECREF(matchingAnchor); | |
3119 PKIX_DECREF(trustedCert); | |
3120 | |
3121 | |
3122 PKIX_RETURN(BUILD); | |
3123 } | |
3124 | |
3125 /* | |
3126 * FUNCTION: pkix_Build_InitiateBuildChain | |
3127 * DESCRIPTION: | |
3128 * | |
3129 * This function initiates the search for a BuildChain, using the parameters | |
3130 * provided in "procParams" and, if continuing a search that was suspended | |
3131 * for I/O, using the ForwardBuilderState pointed to by "pState". | |
3132 * | |
3133 * If a successful chain is built, this function stores the BuildResult at | |
3134 * "pBuildResult". Alternatively, if an operation using non-blocking I/O | |
3135 * is in progress and the operation has not been completed, this function | |
3136 * stores the platform-dependent non-blocking I/O context (nbioContext) at | |
3137 * "pNBIOContext", the FowardBuilderState at "pState", and NULL at | |
3138 * "pBuildResult". Finally, if chain building was unsuccessful, this function | |
3139 * stores NULL at both "pState" and at "pBuildResult". | |
3140 * | |
3141 * Note: This function is re-entered only for the case of non-blocking I/O | |
3142 * in the "short-cut" attempt to build a chain using the target Certificate | |
3143 * directly with one of the trustAnchors. For all other cases, resumption | |
3144 * after non-blocking I/O is via pkix_Build_ResumeBuildChain. | |
3145 * | |
3146 * PARAMETERS: | |
3147 * "procParams" | |
3148 * Address of the ProcessingParams for the search. Must be non-NULL. | |
3149 * "pNBIOContext" | |
3150 * Address at which the NBIOContext is stored indicating whether the | |
3151 * validation is complete. Must be non-NULL. | |
3152 * "pState" | |
3153 * Address at which the ForwardBuilderState is stored, if the chain | |
3154 * building is suspended for waiting I/O; also, the address at which the | |
3155 * ForwardBuilderState is provided for resumption of the chain building | |
3156 * attempt. Must be non-NULL. | |
3157 * "pBuildResult" | |
3158 * Address at which the BuildResult is stored, after a successful build. | |
3159 * Must be non-NULL. | |
3160 * "pVerifyNode" | |
3161 * Address at which a VerifyNode chain is returned, if non-NULL. | |
3162 * "plContext" | |
3163 * Platform-specific context pointer. | |
3164 * THREAD SAFETY: | |
3165 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
3166 * RETURNS: | |
3167 * Returns NULL if the function succeeds. | |
3168 * Returns a Build Error if the function fails in a non-fatal way | |
3169 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
3170 */ | |
3171 static PKIX_Error * | |
3172 pkix_Build_InitiateBuildChain( | |
3173 PKIX_ProcessingParams *procParams, | |
3174 void **pNBIOContext, | |
3175 PKIX_ForwardBuilderState **pState, | |
3176 PKIX_BuildResult **pBuildResult, | |
3177 PKIX_VerifyNode **pVerifyNode, | |
3178 void *plContext) | |
3179 { | |
3180 PKIX_UInt32 numAnchors = 0; | |
3181 PKIX_UInt32 numCertStores = 0; | |
3182 PKIX_UInt32 numHintCerts = 0; | |
3183 PKIX_UInt32 i = 0; | |
3184 PKIX_Boolean isDuplicate = PKIX_FALSE; | |
3185 PKIX_PL_Cert *trustedCert = NULL; | |
3186 PKIX_CertSelector *targetConstraints = NULL; | |
3187 PKIX_ComCertSelParams *targetParams = NULL; | |
3188 PKIX_List *anchors = NULL; | |
3189 PKIX_List *targetSubjNames = NULL; | |
3190 PKIX_PL_Cert *targetCert = NULL; | |
3191 PKIX_PL_Object *firstHintCert = NULL; | |
3192 PKIX_RevocationChecker *revChecker = NULL; | |
3193 PKIX_List *certStores = NULL; | |
3194 PKIX_CertStore *certStore = NULL; | |
3195 PKIX_List *userCheckers = NULL; | |
3196 PKIX_List *hintCerts = NULL; | |
3197 PKIX_PL_Date *testDate = NULL; | |
3198 PKIX_PL_PublicKey *targetPubKey = NULL; | |
3199 void *nbioContext = NULL; | |
3200 BuildConstants buildConstants; | |
3201 | |
3202 PKIX_List *tentativeChain = NULL; | |
3203 PKIX_ValidateResult *valResult = NULL; | |
3204 PKIX_BuildResult *buildResult = NULL; | |
3205 PKIX_List *certList = NULL; | |
3206 PKIX_ForwardBuilderState *state = NULL; | |
3207 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; | |
3208 PKIX_CertSelector_MatchCallback selectorCallback = NULL; | |
3209 PKIX_Boolean trusted = PKIX_FALSE; | |
3210 PKIX_PL_AIAMgr *aiaMgr = NULL; | |
3211 | |
3212 PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain"); | |
3213 PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); | |
3214 | |
3215 nbioContext = *pNBIOContext; | |
3216 *pNBIOContext = NULL; | |
3217 | |
3218 state = *pState; | |
3219 *pState = NULL; /* no net change in reference count */ | |
3220 | |
3221 if (state == NULL) { | |
3222 PKIX_CHECK(PKIX_ProcessingParams_GetDate | |
3223 (procParams, &testDate, plContext), | |
3224 PKIX_PROCESSINGPARAMSGETDATEFAILED); | |
3225 | |
3226 PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors | |
3227 (procParams, &anchors, plContext), | |
3228 PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); | |
3229 | |
3230 PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext), | |
3231 PKIX_LISTGETLENGTHFAILED); | |
3232 | |
3233 /* retrieve stuff from targetCertConstraints */ | |
3234 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
3235 (procParams, &targetConstraints, plContext), | |
3236 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
3237 | |
3238 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
3239 (targetConstraints, &targetParams, plContext), | |
3240 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
3241 | |
3242 PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate | |
3243 (targetParams, &targetCert, plContext), | |
3244 PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED); | |
3245 | |
3246 PKIX_CHECK( | |
3247 PKIX_ComCertSelParams_SetLeafCertFlag(targetParams, | |
3248 PKIX_TRUE, plContext), | |
3249 PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED); | |
3250 | |
3251 PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts | |
3252 (procParams, &hintCerts, plContext), | |
3253 PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED); | |
3254 | |
3255 if (hintCerts != NULL) { | |
3256 PKIX_CHECK(PKIX_List_GetLength | |
3257 (hintCerts, &numHintCerts, plContext), | |
3258 PKIX_LISTGETLENGTHFAILED); | |
3259 } | |
3260 | |
3261 /* | |
3262 * Caller must provide either a target Cert | |
3263 * (in ComCertSelParams->Certificate) or a partial Cert | |
3264 * chain (in ProcParams->HintCerts). | |
3265 */ | |
3266 | |
3267 if (targetCert == NULL) { | |
3268 | |
3269 /* Use first cert of hintCerts as the targetCert */ | |
3270 if (numHintCerts == 0) { | |
3271 PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); | |
3272 } | |
3273 | |
3274 PKIX_CHECK(PKIX_List_GetItem | |
3275 (hintCerts, | |
3276 0, | |
3277 (PKIX_PL_Object **)&targetCert, | |
3278 plContext), | |
3279 PKIX_LISTGETITEMFAILED); | |
3280 | |
3281 PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext), | |
3282 PKIX_LISTGETITEMFAILED); | |
3283 } else { | |
3284 | |
3285 /* | |
3286 * If the first hintCert is the same as the targetCert, | |
3287 * delete it from hintCerts. | |
3288 */ | |
3289 if (numHintCerts != 0) { | |
3290 PKIX_CHECK(PKIX_List_GetItem | |
3291 (hintCerts, 0, &firstHintCert, plContext), | |
3292 PKIX_LISTGETITEMFAILED); | |
3293 | |
3294 PKIX_CHECK(PKIX_PL_Object_Equals | |
3295 ((PKIX_PL_Object *)targetCert, | |
3296 firstHintCert, | |
3297 &isDuplicate, | |
3298 plContext), | |
3299 PKIX_OBJECTEQUALSFAILED); | |
3300 | |
3301 if (isDuplicate) { | |
3302 PKIX_CHECK(PKIX_List_DeleteItem | |
3303 (hintCerts, 0, plContext), | |
3304 PKIX_LISTGETITEMFAILED); | |
3305 } | |
3306 PKIX_DECREF(firstHintCert); | |
3307 } | |
3308 | |
3309 } | |
3310 | |
3311 if (targetCert == NULL) { | |
3312 PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); | |
3313 } | |
3314 | |
3315 PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted | |
3316 (targetCert, | |
3317 &trusted, | |
3318 plContext), | |
3319 PKIX_CERTISCERTTRUSTEDFAILED); | |
3320 | |
3321 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
3322 (targetCert, | |
3323 &targetSubjNames, | |
3324 plContext), | |
3325 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
3326 | |
3327 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
3328 (targetCert, &targetPubKey, plContext), | |
3329 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
3330 | |
3331 PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext), | |
3332 PKIX_LISTCREATEFAILED); | |
3333 | |
3334 PKIX_CHECK(PKIX_List_AppendItem | |
3335 (tentativeChain, (PKIX_PL_Object *)targetCert, plContext), | |
3336 PKIX_LISTAPPENDITEMFAILED); | |
3337 | |
3338 if (procParams->qualifyTargetCert) { | |
3339 /* EE cert validation */ | |
3340 /* Sync up the time on the target selector parameter struct. */ | |
3341 PKIX_CHECK( | |
3342 PKIX_ComCertSelParams_SetCertificateValid(targetParams, | |
3343 testDate, | |
3344 plContext), | |
3345 PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); | |
3346 | |
3347 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback | |
3348 (targetConstraints, &selectorCallback, plContext), | |
3349 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); | |
3350 | |
3351 pkixErrorResult = | |
3352 (*selectorCallback)(targetConstraints, targetCert, | |
3353 plContext); | |
3354 if (pkixErrorResult) { | |
3355 pkixErrorClass = pkixErrorResult->errClass; | |
3356 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
3357 goto cleanup; | |
3358 } | |
3359 if (pVerifyNode != NULL) { | |
3360 PKIX_Error *tempResult = | |
3361 pkix_VerifyNode_Create(targetCert, 0, | |
3362 pkixErrorResult, | |
3363 pVerifyNode, | |
3364 plContext); | |
3365 if (tempResult) { | |
3366 PKIX_DECREF(pkixErrorResult); | |
3367 pkixErrorResult = tempResult; | |
3368 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
3369 pkixErrorClass = PKIX_FATAL_ERROR; | |
3370 goto cleanup; | |
3371 } | |
3372 } | |
3373 pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED; | |
3374 goto cleanup; | |
3375 } | |
3376 } | |
3377 | |
3378 /* If the EE cert is trusted, force success. We only want to do | |
3379 * this if we aren't validating against a policy (like EV). */ | |
3380 if (trusted && procParams->initialPolicies == NULL) { | |
3381 if (pVerifyNode != NULL) { | |
3382 PKIX_Error *tempResult = | |
3383 pkix_VerifyNode_Create(targetCert, 0, NULL, | |
3384 pVerifyNode, | |
3385 plContext); | |
3386 if (tempResult) { | |
3387 pkixErrorResult = tempResult; | |
3388 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
3389 pkixErrorClass = PKIX_FATAL_ERROR; | |
3390 goto cleanup; | |
3391 } | |
3392 } | |
3393 PKIX_CHECK(pkix_ValidateResult_Create | |
3394 (targetPubKey, NULL /* anchor */, | |
3395 NULL /* policyTree */, &valResult, plContext), | |
3396 PKIX_VALIDATERESULTCREATEFAILED); | |
3397 PKIX_CHECK( | |
3398 pkix_BuildResult_Create(valResult, tentativeChain, | |
3399 &buildResult, plContext), | |
3400 PKIX_BUILDRESULTCREATEFAILED); | |
3401 *pBuildResult = buildResult; | |
3402 /* Note that *pState is NULL. The only side effect is that | |
3403 * the cert chain won't be cached in PKIX_BuildChain, which | |
3404 * is fine. */ | |
3405 goto cleanup; | |
3406 } | |
3407 | |
3408 PKIX_CHECK(PKIX_ProcessingParams_GetCertStores | |
3409 (procParams, &certStores, plContext), | |
3410 PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); | |
3411 | |
3412 PKIX_CHECK(PKIX_List_GetLength | |
3413 (certStores, &numCertStores, plContext), | |
3414 PKIX_LISTGETLENGTHFAILED); | |
3415 | |
3416 /* Reorder CertStores so trusted are at front of the List */ | |
3417 if (numCertStores > 1) { | |
3418 for (i = numCertStores - 1; i > 0; i--) { | |
3419 PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem | |
3420 (certStores, | |
3421 i, | |
3422 (PKIX_PL_Object **)&certStore, | |
3423 plContext), | |
3424 PKIX_LISTGETITEMFAILED); | |
3425 PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback | |
3426 (certStore, &trustCallback, plContext), | |
3427 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); | |
3428 | |
3429 if (trustCallback != NULL) { | |
3430 /* Is a trusted Cert, move CertStore to front */ | |
3431 PKIX_CHECK(PKIX_List_DeleteItem | |
3432 (certStores, i, plContext), | |
3433 PKIX_LISTDELETEITEMFAILED); | |
3434 PKIX_CHECK(PKIX_List_InsertItem | |
3435 (certStores, | |
3436 0, | |
3437 (PKIX_PL_Object *)certStore, | |
3438 plContext), | |
3439 PKIX_LISTINSERTITEMFAILED); | |
3440 | |
3441 } | |
3442 | |
3443 PKIX_DECREF(certStore); | |
3444 } | |
3445 } | |
3446 | |
3447 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers | |
3448 (procParams, &userCheckers, plContext), | |
3449 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); | |
3450 | |
3451 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker | |
3452 (procParams, &revChecker, plContext), | |
3453 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); | |
3454 /* Do not initialize AIA manager if we are not going to fetch | |
3455 * cert using aia url. */ | |
3456 if (procParams->useAIAForCertFetching) { | |
3457 PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext), | |
3458 PKIX_AIAMGRCREATEFAILED); | |
3459 } | |
3460 | |
3461 /* | |
3462 * We initialize all the fields of buildConstants here, in one place
, | |
3463 * just to help keep track and ensure that we got everything. | |
3464 */ | |
3465 | |
3466 buildConstants.numAnchors = numAnchors; | |
3467 buildConstants.numCertStores = numCertStores; | |
3468 buildConstants.numHintCerts = numHintCerts; | |
3469 buildConstants.procParams = procParams; | |
3470 buildConstants.testDate = testDate; | |
3471 buildConstants.timeLimit = NULL; | |
3472 buildConstants.targetCert = targetCert; | |
3473 buildConstants.targetPubKey = targetPubKey; | |
3474 buildConstants.certStores = certStores; | |
3475 buildConstants.anchors = anchors; | |
3476 buildConstants.userCheckers = userCheckers; | |
3477 buildConstants.hintCerts = hintCerts; | |
3478 buildConstants.revChecker = revChecker; | |
3479 buildConstants.aiaMgr = aiaMgr; | |
3480 buildConstants.trustOnlyUserAnchors = | |
3481 procParams->useOnlyTrustAnchors; | |
3482 | |
3483 PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext), | |
3484 PKIX_BUILDGETRESOURCELIMITSFAILED); | |
3485 | |
3486 PKIX_CHECK(pkix_ForwardBuilderState_Create | |
3487 (0, /* PKIX_UInt32 traversedCACerts */ | |
3488 buildConstants.maxFanout, | |
3489 buildConstants.maxDepth, | |
3490 PKIX_FALSE, /* PKIX_Boolean revCheckDelayed */ | |
3491 PKIX_TRUE, /* PKIX_Boolean canBeCached */ | |
3492 NULL, /* PKIX_Date *validityDate */ | |
3493 targetCert, /* PKIX_PL_Cert *prevCert */ | |
3494 targetSubjNames, /* PKIX_List *traversedSubjNames */ | |
3495 tentativeChain, /* PKIX_List *trustChain */ | |
3496 NULL, /* PKIX_ForwardBuilderState *parent */ | |
3497 &state, /* PKIX_ForwardBuilderState **pState */ | |
3498 plContext), | |
3499 PKIX_BUILDSTATECREATEFAILED); | |
3500 | |
3501 state->buildConstants.numAnchors = buildConstants.numAnchors; | |
3502 state->buildConstants.numCertStores = buildConstants.numCertStores; | |
3503 state->buildConstants.numHintCerts = buildConstants.numHintCerts; | |
3504 state->buildConstants.maxFanout = buildConstants.maxFanout; | |
3505 state->buildConstants.maxDepth = buildConstants.maxDepth; | |
3506 state->buildConstants.maxTime = buildConstants.maxTime; | |
3507 state->buildConstants.procParams = buildConstants.procParams; | |
3508 PKIX_INCREF(buildConstants.testDate); | |
3509 state->buildConstants.testDate = buildConstants.testDate; | |
3510 state->buildConstants.timeLimit = buildConstants.timeLimit; | |
3511 PKIX_INCREF(buildConstants.targetCert); | |
3512 state->buildConstants.targetCert = buildConstants.targetCert; | |
3513 PKIX_INCREF(buildConstants.targetPubKey); | |
3514 state->buildConstants.targetPubKey = | |
3515 buildConstants.targetPubKey; | |
3516 PKIX_INCREF(buildConstants.certStores); | |
3517 state->buildConstants.certStores = buildConstants.certStores; | |
3518 PKIX_INCREF(buildConstants.anchors); | |
3519 state->buildConstants.anchors = buildConstants.anchors; | |
3520 PKIX_INCREF(buildConstants.userCheckers); | |
3521 state->buildConstants.userCheckers = | |
3522 buildConstants.userCheckers; | |
3523 PKIX_INCREF(buildConstants.hintCerts); | |
3524 state->buildConstants.hintCerts = buildConstants.hintCerts; | |
3525 PKIX_INCREF(buildConstants.revChecker); | |
3526 state->buildConstants.revChecker = buildConstants.revChecker; | |
3527 state->buildConstants.aiaMgr = buildConstants.aiaMgr; | |
3528 aiaMgr = NULL; | |
3529 state->buildConstants.trustOnlyUserAnchors = | |
3530 buildConstants.trustOnlyUserAnchors; | |
3531 | |
3532 if (buildConstants.maxTime != 0) { | |
3533 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds | |
3534 (buildConstants.maxTime, | |
3535 &state->buildConstants.timeLimit, | |
3536 plContext), | |
3537 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); | |
3538 } | |
3539 | |
3540 if (pVerifyNode != NULL) { | |
3541 PKIX_Error *tempResult = | |
3542 pkix_VerifyNode_Create(targetCert, 0, NULL, | |
3543 &(state->verifyNode), | |
3544 plContext); | |
3545 if (tempResult) { | |
3546 pkixErrorResult = tempResult; | |
3547 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
3548 pkixErrorClass = PKIX_FATAL_ERROR; | |
3549 goto cleanup; | |
3550 } | |
3551 } | |
3552 | |
3553 PKIX_CHECK_ONLY_FATAL( | |
3554 pkix_Build_CheckInCache(state, &buildResult, | |
3555 &nbioContext, plContext), | |
3556 PKIX_UNABLETOBUILDCHAIN); | |
3557 if (nbioContext) { | |
3558 *pNBIOContext = nbioContext; | |
3559 *pState = state; | |
3560 state = NULL; | |
3561 goto cleanup; | |
3562 } | |
3563 if (buildResult) { | |
3564 *pBuildResult = buildResult; | |
3565 if (pVerifyNode != NULL) { | |
3566 *pVerifyNode = state->verifyNode; | |
3567 state->verifyNode = NULL; | |
3568 } | |
3569 goto cleanup; | |
3570 } | |
3571 } | |
3572 | |
3573 /* If we're resuming after non-blocking I/O we need to get SubjNames */ | |
3574 if (targetSubjNames == NULL) { | |
3575 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
3576 (state->buildConstants.targetCert, | |
3577 &targetSubjNames, | |
3578 plContext), | |
3579 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
3580 } | |
3581 | |
3582 state->status = BUILD_INITIAL; | |
3583 | |
3584 pkixErrorResult = | |
3585 pkix_BuildForwardDepthFirstSearch(&nbioContext, state, | |
3586 &valResult, plContext); | |
3587 | |
3588 /* non-null nbioContext means the build would block */ | |
3589 if (pkixErrorResult == NULL && nbioContext != NULL) { | |
3590 | |
3591 *pNBIOContext = nbioContext; | |
3592 *pBuildResult = NULL; | |
3593 | |
3594 /* no valResult means the build has failed */ | |
3595 } else { | |
3596 if (pVerifyNode != NULL) { | |
3597 PKIX_INCREF(state->verifyNode); | |
3598 *pVerifyNode = state->verifyNode; | |
3599 } | |
3600 | |
3601 if (valResult == NULL || pkixErrorResult) | |
3602 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
3603 PKIX_CHECK( | |
3604 pkix_BuildResult_Create(valResult, state->trustChain, | |
3605 &buildResult, plContext), | |
3606 PKIX_BUILDRESULTCREATEFAILED); | |
3607 *pBuildResult = buildResult; | |
3608 } | |
3609 | |
3610 *pState = state; | |
3611 state = NULL; | |
3612 | |
3613 cleanup: | |
3614 | |
3615 PKIX_DECREF(targetConstraints); | |
3616 PKIX_DECREF(targetParams); | |
3617 PKIX_DECREF(anchors); | |
3618 PKIX_DECREF(targetSubjNames); | |
3619 PKIX_DECREF(targetCert); | |
3620 PKIX_DECREF(revChecker); | |
3621 PKIX_DECREF(certStores); | |
3622 PKIX_DECREF(certStore); | |
3623 PKIX_DECREF(userCheckers); | |
3624 PKIX_DECREF(hintCerts); | |
3625 PKIX_DECREF(firstHintCert); | |
3626 PKIX_DECREF(testDate); | |
3627 PKIX_DECREF(targetPubKey); | |
3628 PKIX_DECREF(tentativeChain); | |
3629 PKIX_DECREF(valResult); | |
3630 PKIX_DECREF(certList); | |
3631 PKIX_DECREF(trustedCert); | |
3632 PKIX_DECREF(state); | |
3633 PKIX_DECREF(aiaMgr); | |
3634 | |
3635 PKIX_RETURN(BUILD); | |
3636 } | |
3637 | |
3638 /* | |
3639 * FUNCTION: pkix_Build_ResumeBuildChain | |
3640 * DESCRIPTION: | |
3641 * | |
3642 * This function continues the search for a BuildChain, using the parameters | |
3643 * provided in "procParams" and the ForwardBuilderState pointed to by "state". | |
3644 * | |
3645 * If a successful chain is built, this function stores the BuildResult at | |
3646 * "pBuildResult". Alternatively, if an operation using non-blocking I/O | |
3647 * is in progress and the operation has not been completed, this function | |
3648 * stores the FowardBuilderState at "pState" and NULL at "pBuildResult". | |
3649 * Finally, if chain building was unsuccessful, this function stores NULL | |
3650 * at both "pState" and at "pBuildResult". | |
3651 * | |
3652 * PARAMETERS: | |
3653 * "pNBIOContext" | |
3654 * Address at which the NBIOContext is stored indicating whether the | |
3655 * validation is complete. Must be non-NULL. | |
3656 * "pState" | |
3657 * Address at which the ForwardBuilderState is provided for resumption of | |
3658 * the chain building attempt; also, the address at which the | |
3659 * ForwardBuilderStateis stored, if the chain building is suspended for | |
3660 * waiting I/O. Must be non-NULL. | |
3661 * "pBuildResult" | |
3662 * Address at which the BuildResult is stored, after a successful build. | |
3663 * Must be non-NULL. | |
3664 * "plContext" | |
3665 * Platform-specific context pointer. | |
3666 * THREAD SAFETY: | |
3667 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
3668 * RETURNS: | |
3669 * Returns NULL if the function succeeds. | |
3670 * Returns a Build Error if the function fails in a non-fatal way | |
3671 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
3672 */ | |
3673 static PKIX_Error * | |
3674 pkix_Build_ResumeBuildChain( | |
3675 void **pNBIOContext, | |
3676 PKIX_ForwardBuilderState *state, | |
3677 PKIX_BuildResult **pBuildResult, | |
3678 PKIX_VerifyNode **pVerifyNode, | |
3679 void *plContext) | |
3680 { | |
3681 PKIX_ValidateResult *valResult = NULL; | |
3682 PKIX_BuildResult *buildResult = NULL; | |
3683 void *nbioContext = NULL; | |
3684 | |
3685 PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain"); | |
3686 PKIX_NULLCHECK_TWO(state, pBuildResult); | |
3687 | |
3688 nbioContext = *pNBIOContext; | |
3689 *pNBIOContext = NULL; | |
3690 | |
3691 pkixErrorResult = | |
3692 pkix_BuildForwardDepthFirstSearch(&nbioContext, state, | |
3693 &valResult, plContext); | |
3694 | |
3695 /* non-null nbioContext means the build would block */ | |
3696 if (pkixErrorResult == NULL && nbioContext != NULL) { | |
3697 | |
3698 *pNBIOContext = nbioContext; | |
3699 *pBuildResult = NULL; | |
3700 | |
3701 /* no valResult means the build has failed */ | |
3702 } else { | |
3703 if (pVerifyNode != NULL) { | |
3704 PKIX_INCREF(state->verifyNode); | |
3705 *pVerifyNode = state->verifyNode; | |
3706 } | |
3707 | |
3708 if (valResult == NULL || pkixErrorResult) | |
3709 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
3710 | |
3711 PKIX_CHECK( | |
3712 pkix_BuildResult_Create(valResult, state->trustChain, | |
3713 &buildResult, plContext), | |
3714 PKIX_BUILDRESULTCREATEFAILED); | |
3715 *pBuildResult = buildResult; | |
3716 } | |
3717 | |
3718 cleanup: | |
3719 | |
3720 PKIX_DECREF(valResult); | |
3721 | |
3722 PKIX_RETURN(BUILD); | |
3723 } | |
3724 | |
3725 /* --Public-Functions--------------------------------------------- */ | |
3726 | |
3727 /* | |
3728 * FUNCTION: PKIX_BuildChain (see comments in pkix.h) | |
3729 */ | |
3730 PKIX_Error * | |
3731 PKIX_BuildChain( | |
3732 PKIX_ProcessingParams *procParams, | |
3733 void **pNBIOContext, | |
3734 void **pState, | |
3735 PKIX_BuildResult **pBuildResult, | |
3736 PKIX_VerifyNode **pVerifyNode, | |
3737 void *plContext) | |
3738 { | |
3739 PKIX_ForwardBuilderState *state = NULL; | |
3740 PKIX_BuildResult *buildResult = NULL; | |
3741 void *nbioContext = NULL; | |
3742 | |
3743 PKIX_ENTER(BUILD, "PKIX_BuildChain"); | |
3744 PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); | |
3745 | |
3746 nbioContext = *pNBIOContext; | |
3747 *pNBIOContext = NULL; | |
3748 | |
3749 if (*pState == NULL) { | |
3750 PKIX_CHECK(pkix_Build_InitiateBuildChain | |
3751 (procParams, | |
3752 &nbioContext, | |
3753 &state, | |
3754 &buildResult, | |
3755 pVerifyNode, | |
3756 plContext), | |
3757 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
3758 } else { | |
3759 state = (PKIX_ForwardBuilderState *)(*pState); | |
3760 *pState = NULL; /* no net change in reference count */ | |
3761 if (state->status == BUILD_SHORTCUTPENDING) { | |
3762 PKIX_CHECK(pkix_Build_InitiateBuildChain | |
3763 (procParams, | |
3764 &nbioContext, | |
3765 &state, | |
3766 &buildResult, | |
3767 pVerifyNode, | |
3768 plContext), | |
3769 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
3770 } else { | |
3771 PKIX_CHECK(pkix_Build_ResumeBuildChain | |
3772 (&nbioContext, | |
3773 state, | |
3774 &buildResult, | |
3775 pVerifyNode, | |
3776 plContext), | |
3777 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
3778 } | |
3779 } | |
3780 | |
3781 /* non-null nbioContext means the build would block */ | |
3782 if (nbioContext != NULL) { | |
3783 | |
3784 *pNBIOContext = nbioContext; | |
3785 *pState = state; | |
3786 state = NULL; | |
3787 *pBuildResult = NULL; | |
3788 | |
3789 /* no buildResult means the build has failed */ | |
3790 } else if (buildResult == NULL) { | |
3791 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
3792 } else { | |
3793 /* | |
3794 * If we made a successful chain by combining the target Cert | |
3795 * with one of the Trust Anchors, we may have never created a | |
3796 * validityDate. We treat this situation as | |
3797 * canBeCached = PKIX_FALSE. | |
3798 */ | |
3799 if ((state != NULL) && | |
3800 ((state->validityDate) != NULL) && | |
3801 (state->canBeCached)) { | |
3802 PKIX_CHECK(pkix_CacheCertChain_Add | |
3803 (state->buildConstants.targetCert, | |
3804 state->buildConstants.anchors, | |
3805 state->validityDate, | |
3806 buildResult, | |
3807 plContext), | |
3808 PKIX_CACHECERTCHAINADDFAILED); | |
3809 } | |
3810 | |
3811 *pState = NULL; | |
3812 *pBuildResult = buildResult; | |
3813 buildResult = NULL; | |
3814 } | |
3815 | |
3816 cleanup: | |
3817 PKIX_DECREF(buildResult); | |
3818 PKIX_DECREF(state); | |
3819 | |
3820 PKIX_RETURN(BUILD); | |
3821 } | |
OLD | NEW |