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