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