Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix/top/pkix_validate.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_validate.c | |
6 * | |
7 * Top level validateChain function | |
8 * | |
9 */ | |
10 | |
11 #include "pkix_validate.h" | |
12 #include "pkix_pl_common.h" | |
13 | |
14 /* --Private-Functions-------------------------------------------- */ | |
15 | |
16 /* | |
17 * FUNCTION: pkix_AddToVerifyLog | |
18 * DESCRIPTION: | |
19 * | |
20 * This function returns immediately if the address for the VerifyNode tree | |
21 * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode | |
22 * from the Cert pointed to by "cert" and the Error pointed to by "error", | |
23 * and inserts it at the depth in the VerifyNode tree determined by "depth". A | |
24 * depth of zero means that this function creates the root node of a new tree. | |
25 * | |
26 * Note: this function does not include the means of choosing among branches | |
27 * of a tree. It is intended for non-branching trees, that is, where each | |
28 * parent node has only a single child node. | |
29 * | |
30 * PARAMETERS: | |
31 * "cert" | |
32 * The address of the Cert to be included in the new VerifyNode. Must be | |
33 * non-NULL. | |
34 * "depth" | |
35 * The UInt32 value of the depth. | |
36 * "error" | |
37 * The address of the Error to be included in the new VerifyNode. | |
38 * "pVerifyTree" | |
39 * The address of the VerifyNode tree into which the created VerifyNode | |
40 * is to be inserted. The node is not created if VerifyTree is NULL. | |
41 * "plContext" | |
42 * Platform-specific context pointer. | |
43 * THREAD SAFETY: | |
44 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
45 * RETURNS: | |
46 * Returns NULL if the function succeeds. | |
47 * Returns a Validate Error if the function fails in a non-fatal way. | |
48 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
49 */ | |
50 static PKIX_Error * | |
51 pkix_AddToVerifyLog( | |
52 PKIX_PL_Cert *cert, | |
53 PKIX_UInt32 depth, | |
54 PKIX_Error *error, | |
55 PKIX_VerifyNode **pVerifyTree, | |
56 void *plContext) | |
57 { | |
58 | |
59 PKIX_VerifyNode *verifyNode = NULL; | |
60 | |
61 PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog"); | |
62 PKIX_NULLCHECK_ONE(cert); | |
63 | |
64 if (pVerifyTree) { /* nothing to do if no address given for log */ | |
65 | |
66 PKIX_CHECK(pkix_VerifyNode_Create | |
67 (cert, depth, error, &verifyNode, plContext), | |
68 PKIX_VERIFYNODECREATEFAILED); | |
69 | |
70 if (depth == 0) { | |
71 /* We just created the root node */ | |
72 *pVerifyTree = verifyNode; | |
73 } else { | |
74 PKIX_CHECK(pkix_VerifyNode_AddToChain | |
75 (*pVerifyTree, verifyNode, plContext), | |
76 PKIX_VERIFYNODEADDTOCHAINFAILED); | |
77 } | |
78 } | |
79 | |
80 cleanup: | |
81 | |
82 PKIX_RETURN(VALIDATE); | |
83 | |
84 } | |
85 | |
86 /* | |
87 * FUNCTION: pkix_CheckCert | |
88 * DESCRIPTION: | |
89 * | |
90 * Checks whether the Cert pointed to by "cert" successfully validates | |
91 * using the List of CertChainCheckers pointed to by "checkers". If the | |
92 * certificate does not validate, an Error pointer is returned. | |
93 * | |
94 * This function should be called initially with the UInt32 pointed to by | |
95 * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext" | |
96 * containing NULL. If a checker does non-blocking I/O, this function will | |
97 * return with the index of that checker stored at "pCheckerIndex" and a | |
98 * platform-dependent non-blocking I/O context stored at "pNBIOContext". | |
99 * A subsequent call to this function with those values intact will allow the | |
100 * checking to resume where it left off. This should be repeated until the | |
101 * function returns with NULL stored at "pNBIOContext". | |
102 * | |
103 * PARAMETERS: | |
104 * "cert" | |
105 * Address of Cert to validate. Must be non-NULL. | |
106 * "checkers" | |
107 * List of CertChainCheckers which must each validate the certificate. | |
108 * Must be non-NULL. | |
109 * "checkedExtOIDs" | |
110 * List of PKIX_PL_OID that has been processed. If called from building | |
111 * chain, it is the list of critical extension OIDs that has been | |
112 * processed prior to validation. May be NULL. | |
113 * "pCheckerIndex" | |
114 * Address at which is stored the the index, within the List "checkers", | |
115 * of a checker whose processing was interrupted by non-blocking I/O. | |
116 * Must be non-NULL. | |
117 * "pNBIOContext" | |
118 * Address at which is stored platform-specific non-blocking I/O context. | |
119 * Must be non-NULL. | |
120 * "plContext" | |
121 * Platform-specific context pointer. | |
122 * THREAD SAFETY: | |
123 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
124 * RETURNS: | |
125 * Returns NULL if the function succeeds. | |
126 * Returns a Validate Error if the function fails in a non-fatal way. | |
127 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
128 */ | |
129 static PKIX_Error * | |
130 pkix_CheckCert( | |
131 PKIX_PL_Cert *cert, | |
132 PKIX_List *checkers, | |
133 PKIX_List *checkedExtOIDsList, | |
134 PKIX_UInt32 *pCheckerIndex, | |
135 void **pNBIOContext, | |
136 void *plContext) | |
137 { | |
138 PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; | |
139 PKIX_CertChainChecker *checker = NULL; | |
140 PKIX_List *unresCritExtOIDs = NULL; | |
141 PKIX_UInt32 numCheckers; | |
142 PKIX_UInt32 numUnresCritExtOIDs = 0; | |
143 PKIX_UInt32 checkerIndex = 0; | |
144 void *nbioContext = NULL; | |
145 | |
146 PKIX_ENTER(VALIDATE, "pkix_CheckCert"); | |
147 PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext); | |
148 | |
149 nbioContext = *pNBIOContext; | |
150 *pNBIOContext = NULL; /* prepare for case of error exit */ | |
151 | |
152 PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs | |
153 (cert, &unresCritExtOIDs, plContext), | |
154 PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED); | |
155 | |
156 PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), | |
157 PKIX_LISTGETLENGTHFAILED); | |
158 | |
159 for (checkerIndex = *pCheckerIndex; | |
160 checkerIndex < numCheckers; | |
161 checkerIndex++) { | |
162 | |
163 PKIX_CHECK(PKIX_List_GetItem | |
164 (checkers, | |
165 checkerIndex, | |
166 (PKIX_PL_Object **)&checker, | |
167 plContext), | |
168 PKIX_LISTGETITEMFAILED); | |
169 | |
170 PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback | |
171 (checker, &checkerCheck, plContext), | |
172 PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); | |
173 | |
174 PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs, | |
175 &nbioContext, plContext), | |
176 PKIX_CERTCHAINCHECKERCHECKFAILED); | |
177 | |
178 if (nbioContext != NULL) { | |
179 *pCheckerIndex = checkerIndex; | |
180 *pNBIOContext = nbioContext; | |
181 goto cleanup; | |
182 } | |
183 | |
184 PKIX_DECREF(checker); | |
185 } | |
186 | |
187 if (unresCritExtOIDs){ | |
188 | |
189 #ifdef PKIX_VALIDATEDEBUG | |
190 { | |
191 PKIX_PL_String *oidString = NULL; | |
192 PKIX_UInt32 length; | |
193 char *oidAscii = NULL; | |
194 PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext, | |
195 PKIX_LISTTOSTRINGFAILED); | |
196 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
197 (oidString, | |
198 PKIX_ESCASCII, | |
199 (void **) &oidAscii, | |
200 &length, | |
201 plContext), | |
202 PKIX_STRINGGETENCODEDFAILED); | |
203 PKIX_VALIDATE_DEBUG_ARG | |
204 ("unrecognized critical extension OIDs:" | |
205 " %s\n", oidAscii); | |
206 PKIX_DECREF(oidString); | |
207 PKIX_PL_Free(oidAscii, plContext); | |
208 } | |
209 #endif | |
210 | |
211 if (checkedExtOIDsList != NULL) { | |
212 /* Take out OID's that had been processed, if any */ | |
213 PKIX_CHECK(pkix_List_RemoveItems | |
214 (unresCritExtOIDs, | |
215 checkedExtOIDsList, | |
216 plContext), | |
217 PKIX_LISTREMOVEITEMSFAILED); | |
218 } | |
219 | |
220 PKIX_CHECK(PKIX_List_GetLength | |
221 (unresCritExtOIDs, &numUnresCritExtOIDs, plContext), | |
222 PKIX_LISTGETLENGTHFAILED); | |
223 | |
224 if (numUnresCritExtOIDs != 0){ | |
225 PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION); | |
226 } | |
227 | |
228 } | |
229 | |
230 cleanup: | |
231 | |
232 PKIX_DECREF(checker); | |
233 PKIX_DECREF(unresCritExtOIDs); | |
234 | |
235 PKIX_RETURN(VALIDATE); | |
236 | |
237 } | |
238 | |
239 /* | |
240 * FUNCTION: pkix_InitializeCheckers | |
241 * DESCRIPTION: | |
242 * | |
243 * Creates several checkers and initializes them with values derived from the | |
244 * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by | |
245 * "procParams", and the number of Certs in the Chain, represented by | |
246 * "numCerts". The List of checkers is stored at "pCheckers". | |
247 * | |
248 * PARAMETERS: | |
249 * "anchor" | |
250 * Address of TrustAnchor used to initialize the SignatureChecker and | |
251 * NameChainingChecker. Must be non-NULL. | |
252 * "procParams" | |
253 * Address of ProcessingParams used to initialize the ExpirationChecker | |
254 * and TargetCertChecker. Must be non-NULL. | |
255 * "numCerts" | |
256 * Number of certificates in the CertChain. | |
257 * "pCheckers" | |
258 * Address where object pointer will be stored. Must be non-NULL. | |
259 * "plContext" | |
260 * Platform-specific context pointer. | |
261 * THREAD SAFETY: | |
262 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
263 * RETURNS: | |
264 * Returns NULL if the function succeeds. | |
265 * Returns a Validate Error if the function fails in a non-fatal way. | |
266 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
267 */ | |
268 static PKIX_Error * | |
269 pkix_InitializeCheckers( | |
270 PKIX_TrustAnchor *anchor, | |
271 PKIX_ProcessingParams *procParams, | |
272 PKIX_UInt32 numCerts, | |
273 PKIX_List **pCheckers, | |
274 void *plContext) | |
275 { | |
276 PKIX_CertChainChecker *targetCertChecker = NULL; | |
277 PKIX_CertChainChecker *expirationChecker = NULL; | |
278 PKIX_CertChainChecker *nameChainingChecker = NULL; | |
279 PKIX_CertChainChecker *nameConstraintsChecker = NULL; | |
280 PKIX_CertChainChecker *basicConstraintsChecker = NULL; | |
281 PKIX_CertChainChecker *policyChecker = NULL; | |
282 PKIX_CertChainChecker *sigChecker = NULL; | |
283 PKIX_CertChainChecker *defaultCrlChecker = NULL; | |
284 PKIX_CertChainChecker *userChecker = NULL; | |
285 PKIX_PL_X500Name *trustedCAName = NULL; | |
286 PKIX_PL_PublicKey *trustedPubKey = NULL; | |
287 PKIX_List *checkers = NULL; | |
288 PKIX_PL_Date *testDate = NULL; | |
289 PKIX_CertSelector *certSelector = NULL; | |
290 PKIX_PL_Cert *trustedCert = NULL; | |
291 PKIX_PL_CertNameConstraints *trustedNC = NULL; | |
292 PKIX_List *initialPolicies = NULL; | |
293 PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; | |
294 PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; | |
295 PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; | |
296 PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; | |
297 PKIX_List *userCheckersList = NULL; | |
298 PKIX_List *certStores = NULL; | |
299 PKIX_UInt32 numCertCheckers = 0; | |
300 PKIX_UInt32 i; | |
301 | |
302 PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers"); | |
303 PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers); | |
304 PKIX_CHECK(PKIX_List_Create(&checkers, plContext), | |
305 PKIX_LISTCREATEFAILED); | |
306 | |
307 /* | |
308 * The TrustAnchor may have been created using CreateWithCert | |
309 * (in which case GetCAPublicKey and GetCAName will return NULL) | |
310 * or may have been created using CreateWithNameKeyPair (in which | |
311 * case GetTrustedCert will return NULL. So we call GetTrustedCert | |
312 * and populate trustedPubKey and trustedCAName accordingly. | |
313 */ | |
314 | |
315 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
316 (anchor, &trustedCert, plContext), | |
317 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
318 | |
319 if (trustedCert){ | |
320 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
321 (trustedCert, &trustedPubKey, plContext), | |
322 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
323 | |
324 PKIX_CHECK(PKIX_PL_Cert_GetSubject | |
325 (trustedCert, &trustedCAName, plContext), | |
326 PKIX_CERTGETSUBJECTFAILED); | |
327 } else { | |
328 PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey | |
329 (anchor, &trustedPubKey, plContext), | |
330 PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED); | |
331 | |
332 PKIX_CHECK(PKIX_TrustAnchor_GetCAName | |
333 (anchor, &trustedCAName, plContext), | |
334 PKIX_TRUSTANCHORGETCANAMEFAILED); | |
335 } | |
336 | |
337 PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName); | |
338 | |
339 PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints | |
340 (anchor, &trustedNC, plContext), | |
341 PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); | |
342 | |
343 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
344 (procParams, &certSelector, plContext), | |
345 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
346 | |
347 PKIX_CHECK(PKIX_ProcessingParams_GetDate | |
348 (procParams, &testDate, plContext), | |
349 PKIX_PROCESSINGPARAMSGETDATEFAILED); | |
350 | |
351 PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies | |
352 (procParams, &initialPolicies, plContext), | |
353 PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); | |
354 | |
355 PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected | |
356 (procParams, &policyQualifiersRejected, plContext), | |
357 PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); | |
358 | |
359 PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited | |
360 (procParams, &initialPolicyMappingInhibit, plContext), | |
361 PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); | |
362 | |
363 PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited | |
364 (procParams, &initialAnyPolicyInhibit, plContext), | |
365 PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); | |
366 | |
367 PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired | |
368 (procParams, &initialExplicitPolicy, plContext), | |
369 PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); | |
370 | |
371 PKIX_CHECK(PKIX_ProcessingParams_GetCertStores | |
372 (procParams, &certStores, plContext), | |
373 PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); | |
374 | |
375 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers | |
376 (procParams, &userCheckersList, plContext), | |
377 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); | |
378 | |
379 /* now, initialize all the checkers */ | |
380 PKIX_CHECK(pkix_TargetCertChecker_Initialize | |
381 (certSelector, numCerts, &targetCertChecker, plContext), | |
382 PKIX_TARGETCERTCHECKERINITIALIZEFAILED); | |
383 | |
384 PKIX_CHECK(pkix_ExpirationChecker_Initialize | |
385 (testDate, &expirationChecker, plContext), | |
386 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); | |
387 | |
388 PKIX_CHECK(pkix_NameChainingChecker_Initialize | |
389 (trustedCAName, &nameChainingChecker, plContext), | |
390 PKIX_NAMECHAININGCHECKERINITIALIZEFAILED); | |
391 | |
392 PKIX_CHECK(pkix_NameConstraintsChecker_Initialize | |
393 (trustedNC, numCerts, &nameConstraintsChecker, plContext), | |
394 PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); | |
395 | |
396 PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize | |
397 (numCerts, &basicConstraintsChecker, plContext), | |
398 PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED); | |
399 | |
400 PKIX_CHECK(pkix_PolicyChecker_Initialize | |
401 (initialPolicies, | |
402 policyQualifiersRejected, | |
403 initialPolicyMappingInhibit, | |
404 initialExplicitPolicy, | |
405 initialAnyPolicyInhibit, | |
406 numCerts, | |
407 &policyChecker, | |
408 plContext), | |
409 PKIX_POLICYCHECKERINITIALIZEFAILED); | |
410 | |
411 PKIX_CHECK(pkix_SignatureChecker_Initialize | |
412 (trustedPubKey, numCerts, &sigChecker, plContext), | |
413 PKIX_SIGNATURECHECKERINITIALIZEFAILED); | |
414 | |
415 if (userCheckersList != NULL) { | |
416 | |
417 PKIX_CHECK(PKIX_List_GetLength | |
418 (userCheckersList, &numCertCheckers, plContext), | |
419 PKIX_LISTGETLENGTHFAILED); | |
420 | |
421 for (i = 0; i < numCertCheckers; i++) { | |
422 | |
423 PKIX_CHECK(PKIX_List_GetItem | |
424 (userCheckersList, | |
425 i, | |
426 (PKIX_PL_Object **) &userChecker, | |
427 plContext), | |
428 PKIX_LISTGETITEMFAILED); | |
429 | |
430 PKIX_CHECK(PKIX_List_AppendItem | |
431 (checkers, | |
432 (PKIX_PL_Object *)userChecker, | |
433 plContext), | |
434 PKIX_LISTAPPENDITEMFAILED); | |
435 | |
436 PKIX_DECREF(userChecker); | |
437 } | |
438 } | |
439 | |
440 PKIX_CHECK(PKIX_List_AppendItem | |
441 (checkers, (PKIX_PL_Object *)targetCertChecker, plContext), | |
442 PKIX_LISTAPPENDITEMFAILED); | |
443 | |
444 PKIX_CHECK(PKIX_List_AppendItem | |
445 (checkers, (PKIX_PL_Object *)expirationChecker, plContext), | |
446 PKIX_LISTAPPENDITEMFAILED); | |
447 | |
448 PKIX_CHECK(PKIX_List_AppendItem | |
449 (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext), | |
450 PKIX_LISTAPPENDITEMFAILED); | |
451 | |
452 PKIX_CHECK(PKIX_List_AppendItem | |
453 (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext), | |
454 PKIX_LISTAPPENDITEMFAILED); | |
455 | |
456 PKIX_CHECK(PKIX_List_AppendItem | |
457 (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext), | |
458 PKIX_LISTAPPENDITEMFAILED); | |
459 | |
460 PKIX_CHECK(PKIX_List_AppendItem | |
461 (checkers, (PKIX_PL_Object *)policyChecker, plContext), | |
462 PKIX_LISTAPPENDITEMFAILED); | |
463 | |
464 PKIX_CHECK(PKIX_List_AppendItem | |
465 (checkers, (PKIX_PL_Object *)sigChecker, plContext), | |
466 PKIX_LISTAPPENDITEMFAILED); | |
467 | |
468 *pCheckers = checkers; | |
469 | |
470 cleanup: | |
471 | |
472 if (PKIX_ERROR_RECEIVED){ | |
473 PKIX_DECREF(checkers); | |
474 } | |
475 | |
476 PKIX_DECREF(certSelector); | |
477 PKIX_DECREF(testDate); | |
478 PKIX_DECREF(initialPolicies); | |
479 PKIX_DECREF(targetCertChecker); | |
480 PKIX_DECREF(expirationChecker); | |
481 PKIX_DECREF(nameChainingChecker); | |
482 PKIX_DECREF(nameConstraintsChecker); | |
483 PKIX_DECREF(basicConstraintsChecker); | |
484 PKIX_DECREF(policyChecker); | |
485 PKIX_DECREF(sigChecker); | |
486 PKIX_DECREF(trustedCAName); | |
487 PKIX_DECREF(trustedPubKey); | |
488 PKIX_DECREF(trustedNC); | |
489 PKIX_DECREF(trustedCert); | |
490 PKIX_DECREF(defaultCrlChecker); | |
491 PKIX_DECREF(userCheckersList); | |
492 PKIX_DECREF(certStores); | |
493 PKIX_DECREF(userChecker); | |
494 | |
495 PKIX_RETURN(VALIDATE); | |
496 } | |
497 | |
498 /* | |
499 * FUNCTION: pkix_RetrieveOutputs | |
500 * DESCRIPTION: | |
501 * | |
502 * This function queries the respective states of the List of checkers in | |
503 * "checkers" to to obtain the final public key from the SignatureChecker | |
504 * and the policy tree from the PolicyChecker, storing those values at | |
505 * "pFinalSubjPubKey" and "pPolicyTree", respectively. | |
506 * | |
507 * PARAMETERS: | |
508 * "checkers" | |
509 * Address of List of checkers to be queried. Must be non-NULL. | |
510 * "pFinalSubjPubKey" | |
511 * Address where final public key will be stored. Must be non-NULL. | |
512 * "pPolicyTree" | |
513 * Address where policy tree will be stored. Must be non-NULL. | |
514 * "plContext" | |
515 * Platform-specific context pointer. | |
516 * THREAD SAFETY: | |
517 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
518 * RETURNS: | |
519 * Returns NULL if the function succeeds. | |
520 * Returns a Validate Error if the function fails in a non-fatal way. | |
521 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
522 */ | |
523 static PKIX_Error * | |
524 pkix_RetrieveOutputs( | |
525 PKIX_List *checkers, | |
526 PKIX_PL_PublicKey **pFinalSubjPubKey, | |
527 PKIX_PolicyNode **pPolicyTree, | |
528 void *plContext) | |
529 { | |
530 PKIX_PL_PublicKey *finalSubjPubKey = NULL; | |
531 PKIX_PolicyNode *validPolicyTree = NULL; | |
532 PKIX_CertChainChecker *checker = NULL; | |
533 PKIX_PL_Object *state = NULL; | |
534 PKIX_UInt32 numCheckers = 0; | |
535 PKIX_UInt32 type; | |
536 PKIX_Int32 j; | |
537 | |
538 PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs"); | |
539 | |
540 PKIX_NULLCHECK_TWO(checkers, pPolicyTree); | |
541 | |
542 /* | |
543 * To optimize the search, we guess that the sigChecker is | |
544 * last in the tree and is preceded by the policyChecker. We | |
545 * search toward the front of the chain. Remember that List | |
546 * items are indexed 0..(numItems - 1). | |
547 */ | |
548 | |
549 PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext), | |
550 PKIX_LISTGETLENGTHFAILED); | |
551 | |
552 for (j = numCheckers - 1; j >= 0; j--){ | |
553 PKIX_CHECK(PKIX_List_GetItem | |
554 (checkers, j, (PKIX_PL_Object **)&checker, plContext), | |
555 PKIX_LISTGETITEMFAILED); | |
556 | |
557 PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState | |
558 (checker, &state, plContext), | |
559 PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); | |
560 | |
561 /* user defined checker may have no state */ | |
562 if (state != NULL) { | |
563 | |
564 PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext), | |
565 PKIX_OBJECTGETTYPEFAILED); | |
566 | |
567 if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){ | |
568 /* final pubKey will include any inherited DSA params */ | |
569 finalSubjPubKey = | |
570 ((pkix_SignatureCheckerState *)state)-> | |
571 prevPublicKey; | |
572 PKIX_INCREF(finalSubjPubKey); | |
573 *pFinalSubjPubKey = finalSubjPubKey; | |
574 } | |
575 | |
576 if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) { | |
577 validPolicyTree = | |
578 ((PKIX_PolicyCheckerState *)state)->validPolicyTree; | |
579 break; | |
580 } | |
581 } | |
582 | |
583 PKIX_DECREF(checker); | |
584 PKIX_DECREF(state); | |
585 } | |
586 | |
587 PKIX_INCREF(validPolicyTree); | |
588 *pPolicyTree = validPolicyTree; | |
589 | |
590 cleanup: | |
591 | |
592 PKIX_DECREF(checker); | |
593 PKIX_DECREF(state); | |
594 | |
595 PKIX_RETURN(VALIDATE); | |
596 | |
597 } | |
598 | |
599 /* | |
600 * FUNCTION: pkix_CheckChain | |
601 * DESCRIPTION: | |
602 * | |
603 * Checks whether the List of Certs pointed to by "certs", containing | |
604 * "numCerts" entries, successfully validates using each CertChainChecker in | |
605 * the List pointed to by "checkers" and has not been revoked, according to any | |
606 * of the Revocation Checkers in the List pointed to by "revChecker". Checkers | |
607 * are expected to remove from "removeCheckedExtOIDs" and extensions that they | |
608 * process. Indices to the certChain and the checkerChain are obtained and | |
609 * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These | |
610 * should be set to zero prior to the initial call, but may be changed (and | |
611 * must be supplied on subsequent calls) if processing is suspended for non- | |
612 * blocking I/O. Each time a Cert passes from being validated by one of the | |
613 * CertChainCheckers to being checked by a Revocation Checker, the Boolean | |
614 * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is | |
615 * rejected by a Revocation Checker, its reason code is returned at | |
616 * "pReasonCode. If the List of Certs successfully validates, the public key i | |
617 * the final certificate is obtained and stored at "pFinalSubjPubKey" and the | |
618 * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List | |
619 * of Certs fails to validate, an Error pointer is returned. | |
620 * | |
621 * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which | |
622 * tracks the results of the validation. That is, either each node in the | |
623 * chain has a NULL Error component, or the last node contains an Error | |
624 * which indicates why the validation failed. | |
625 * | |
626 * The number of Certs in the List, represented by "numCerts", is used to | |
627 * determine which Cert is the final Cert. | |
628 * | |
629 * PARAMETERS: | |
630 * "certs" | |
631 * Address of List of Certs to validate. Must be non-NULL. | |
632 * "numCerts" | |
633 * Number of certificates in the List of certificates. | |
634 * "checkers" | |
635 * List of CertChainCheckers which must each validate the List of | |
636 * certificates. Must be non-NULL. | |
637 * "revChecker" | |
638 * List of RevocationCheckers which must each not reject the List of | |
639 * certificates. May be empty, but must be non-NULL. | |
640 * "removeCheckedExtOIDs" | |
641 * List of PKIX_PL_OID that has been processed. If called from building | |
642 * chain, it is the list of critical extension OIDs that has been | |
643 * processed prior to validation. Extension OIDs that may be processed by | |
644 * user defined checker processes are also in the list. May be NULL. | |
645 * "procParams" | |
646 * Address of ProcessingParams used to initialize various checkers. Must | |
647 * be non-NULL. | |
648 * "pCertCheckedIndex" | |
649 * Address where Int32 index to the Cert chain is obtained and | |
650 * returned. Must be non-NULL. | |
651 * "pCheckerIndex" | |
652 * Address where Int32 index to the CheckerChain is obtained and | |
653 * returned. Must be non-NULL. | |
654 * "pRevChecking" | |
655 * Address where Boolean is obtained and returned, indicating, if FALSE, | |
656 * that CertChainCheckers are being called; or, if TRUE, that RevChecker | |
657 * are being called. Must be non-NULL. | |
658 * "pReasonCode" | |
659 * Address where UInt32 results of revocation checking are stored. Must be | |
660 * non-NULL. | |
661 * "pNBIOContext" | |
662 * Address where platform-dependent context is stored if checking is | |
663 * suspended for non-blocking I/O. Must be non-NULL. | |
664 * "pFinalSubjPubKey" | |
665 * Address where the final public key will be stored. Must be non-NULL. | |
666 * "pPolicyTree" | |
667 * Address where the final validPolicyTree is stored. Must be non-NULL. | |
668 * "pVerifyTree" | |
669 * Address where a VerifyTree is stored, if non-NULL. | |
670 * "plContext" | |
671 * Platform-specific context pointer. | |
672 * THREAD SAFETY: | |
673 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
674 * RETURNS: | |
675 * Returns NULL if the function succeeds. | |
676 * Returns a Validate Error if the function fails in a non-fatal way. | |
677 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
678 */ | |
679 PKIX_Error * | |
680 pkix_CheckChain( | |
681 PKIX_List *certs, | |
682 PKIX_UInt32 numCerts, | |
683 PKIX_TrustAnchor *anchor, | |
684 PKIX_List *checkers, | |
685 PKIX_RevocationChecker *revChecker, | |
686 PKIX_List *removeCheckedExtOIDs, | |
687 PKIX_ProcessingParams *procParams, | |
688 PKIX_UInt32 *pCertCheckedIndex, | |
689 PKIX_UInt32 *pCheckerIndex, | |
690 PKIX_Boolean *pRevChecking, | |
691 PKIX_UInt32 *pReasonCode, | |
692 void **pNBIOContext, | |
693 PKIX_PL_PublicKey **pFinalSubjPubKey, | |
694 PKIX_PolicyNode **pPolicyTree, | |
695 PKIX_VerifyNode **pVerifyTree, | |
696 void *plContext) | |
697 { | |
698 PKIX_UInt32 j = 0; | |
699 PKIX_Boolean revChecking = PKIX_FALSE; | |
700 PKIX_Error *checkCertError = NULL; | |
701 void *nbioContext = NULL; | |
702 PKIX_PL_Cert *cert = NULL; | |
703 PKIX_PL_Cert *issuer = NULL; | |
704 PKIX_PL_NssContext *nssContext = NULL; | |
705 CERTCertList *certList = NULL; | |
706 const CERTChainVerifyCallback *chainVerifyCallback = NULL; | |
707 CERTCertificate *nssCert = NULL; | |
708 | |
709 PKIX_ENTER(VALIDATE, "pkix_CheckChain"); | |
710 PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex); | |
711 PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor); | |
712 PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree); | |
713 | |
714 nbioContext = *pNBIOContext; | |
715 *pNBIOContext = NULL; | |
716 revChecking = *pRevChecking; | |
717 nssContext = (PKIX_PL_NssContext *)plContext; | |
718 chainVerifyCallback = &nssContext->chainVerifyCallback; | |
719 | |
720 if (chainVerifyCallback->isChainValid != NULL) { | |
721 PRBool chainOK = PR_FALSE; /*assume failure*/ | |
722 SECStatus rv; | |
723 | |
724 certList = CERT_NewCertList(); | |
725 if (certList == NULL) { | |
726 PKIX_ERROR_ALLOC_ERROR(); | |
727 } | |
728 | |
729 /* Add the trust anchor to the list */ | |
730 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
731 (anchor, &cert, plContext), | |
732 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
733 | |
734 PKIX_CHECK( | |
735 PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), | |
736 PKIX_CERTGETCERTCERTIFICATEFAILED); | |
737 | |
738 rv = CERT_AddCertToListHead(certList, nssCert); | |
739 if (rv != SECSuccess) { | |
740 PKIX_ERROR_ALLOC_ERROR(); | |
741 } | |
742 /* the certList takes ownership of nssCert on success */ | |
743 nssCert = NULL; | |
744 PKIX_DECREF(cert); | |
745 | |
746 /* Add the rest of the chain to the list */ | |
747 for (j = *pCertCheckedIndex; j < numCerts; j++) { | |
748 PKIX_CHECK(PKIX_List_GetItem( | |
749 certs, j, (PKIX_PL_Object **)&cert, plContext), | |
750 PKIX_LISTGETITEMFAILED); | |
751 | |
752 PKIX_CHECK( | |
753 PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext), | |
754 PKIX_CERTGETCERTCERTIFICATEFAILED); | |
755 | |
756 rv = CERT_AddCertToListHead(certList, nssCert); | |
757 if (rv != SECSuccess) { | |
758 PKIX_ERROR_ALLOC_ERROR(); | |
759 } | |
760 /* the certList takes ownership of nssCert on success */ | |
761 nssCert = NULL; | |
762 PKIX_DECREF(cert); | |
763 } | |
764 | |
765 rv = (*chainVerifyCallback->isChainValid) | |
766 (chainVerifyCallback->isChainValidArg, certList, &chainOK); | |
767 if (rv != SECSuccess) { | |
768 PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED); | |
769 } | |
770 | |
771 if (!chainOK) { | |
772 PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED); | |
773 } | |
774 | |
775 } | |
776 | |
777 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
778 (anchor, &cert, plContext), | |
779 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
780 | |
781 for (j = *pCertCheckedIndex; j < numCerts; j++) { | |
782 | |
783 PORT_Assert(cert); | |
784 PKIX_DECREF(issuer); | |
785 issuer = cert; | |
786 cert = NULL; | |
787 | |
788 PKIX_CHECK(PKIX_List_GetItem( | |
789 certs, j, (PKIX_PL_Object **)&cert, plContext), | |
790 PKIX_LISTGETITEMFAILED); | |
791 | |
792 /* check if cert pointer is valid */ | |
793 PORT_Assert(cert); | |
794 if (cert == NULL) { | |
795 continue; | |
796 } | |
797 | |
798 if (revChecking == PKIX_FALSE) { | |
799 | |
800 PKIX_CHECK(pkix_CheckCert | |
801 (cert, | |
802 checkers, | |
803 removeCheckedExtOIDs, | |
804 pCheckerIndex, | |
805 &nbioContext, | |
806 plContext), | |
807 PKIX_CHECKCERTFAILED); | |
808 | |
809 if (nbioContext != NULL) { | |
810 *pCertCheckedIndex = j; | |
811 *pRevChecking = revChecking; | |
812 *pNBIOContext = nbioContext; | |
813 goto cleanup; | |
814 } | |
815 | |
816 revChecking = PKIX_TRUE; | |
817 *pCheckerIndex = 0; | |
818 } | |
819 | |
820 if (revChecking == PKIX_TRUE) { | |
821 PKIX_RevocationStatus revStatus; | |
822 pkixErrorResult = | |
823 PKIX_RevocationChecker_Check( | |
824 cert, issuer, revChecker, | |
825 procParams, PKIX_TRUE, | |
826 (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE, | |
827 &revStatus, pReasonCode, | |
828 &nbioContext, plContext); | |
829 if (nbioContext != NULL) { | |
830 *pCertCheckedIndex = j; | |
831 *pRevChecking = revChecking; | |
832 *pNBIOContext = nbioContext; | |
833 goto cleanup; | |
834 } | |
835 if (revStatus == PKIX_RevStatus_Revoked || | |
836 pkixErrorResult) { | |
837 if (!pkixErrorResult) { | |
838 /* if pkixErrorResult is returned then | |
839 * use it as it has a detailed revocation | |
840 * error code. Otherwise create a new error */ | |
841 PKIX_ERROR_CREATE(VALIDATE, | |
842 PKIX_CERTIFICATEREVOKED, | |
843 pkixErrorResult); | |
844 } | |
845 goto cleanup; | |
846 } | |
847 revChecking = PKIX_FALSE; | |
848 *pCheckerIndex = 0; | |
849 } | |
850 | |
851 PKIX_CHECK(pkix_AddToVerifyLog | |
852 (cert, j, NULL, pVerifyTree, plContext), | |
853 PKIX_ADDTOVERIFYLOGFAILED); | |
854 } | |
855 | |
856 PKIX_CHECK(pkix_RetrieveOutputs | |
857 (checkers, pFinalSubjPubKey, pPolicyTree, plContext), | |
858 PKIX_RETRIEVEOUTPUTSFAILED); | |
859 | |
860 *pNBIOContext = NULL; | |
861 | |
862 cleanup: | |
863 if (PKIX_ERROR_RECEIVED && cert) { | |
864 checkCertError = pkixErrorResult; | |
865 | |
866 PKIX_CHECK_FATAL( | |
867 pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree, | |
868 plContext), | |
869 PKIX_ADDTOVERIFYLOGFAILED); | |
870 pkixErrorResult = checkCertError; | |
871 pkixErrorCode = pkixErrorResult->errCode; | |
872 checkCertError = NULL; | |
873 } | |
874 | |
875 fatal: | |
876 if (nssCert) { | |
877 CERT_DestroyCertificate(nssCert); | |
878 } | |
879 | |
880 if (certList) { | |
881 CERT_DestroyCertList(certList); | |
882 } | |
883 | |
884 PKIX_DECREF(checkCertError); | |
885 PKIX_DECREF(cert); | |
886 PKIX_DECREF(issuer); | |
887 | |
888 PKIX_RETURN(VALIDATE); | |
889 } | |
890 | |
891 /* | |
892 * FUNCTION: pkix_ExtractParameters | |
893 * DESCRIPTION: | |
894 * | |
895 * Extracts several parameters from the ValidateParams object pointed to by | |
896 * "valParams" and stores the CertChain at "pChain", the List of Certs at | |
897 * "pCerts", the number of Certs in the chain at "pNumCerts", the | |
898 * ProcessingParams object at "pProcParams", the List of TrustAnchors at | |
899 * "pAnchors", and the number of TrustAnchors at "pNumAnchors". | |
900 * | |
901 * PARAMETERS: | |
902 * "valParams" | |
903 * Address of ValidateParams from which the parameters are extracted. | |
904 * Must be non-NULL. | |
905 * "pCerts" | |
906 * Address where object pointer for List of Certs will be stored. | |
907 * Must be non-NULL. | |
908 * "pNumCerts" | |
909 * Address where number of Certs will be stored. Must be non-NULL. | |
910 * "pProcParams" | |
911 * Address where object pointer for ProcessingParams will be stored. | |
912 * Must be non-NULL. | |
913 * "pAnchors" | |
914 * Address where object pointer for List of Anchors will be stored. | |
915 * Must be non-NULL. | |
916 * "pNumAnchors" | |
917 * Address where number of Anchors will be stored. Must be non-NULL. | |
918 * "plContext" | |
919 * Platform-specific context pointer. | |
920 * THREAD SAFETY: | |
921 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
922 * RETURNS: | |
923 * Returns NULL if the function succeeds. | |
924 * Returns a Validate Error if the function fails in a non-fatal way. | |
925 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
926 */ | |
927 static PKIX_Error * | |
928 pkix_ExtractParameters( | |
929 PKIX_ValidateParams *valParams, | |
930 PKIX_List **pCerts, | |
931 PKIX_UInt32 *pNumCerts, | |
932 PKIX_ProcessingParams **pProcParams, | |
933 PKIX_List **pAnchors, | |
934 PKIX_UInt32 *pNumAnchors, | |
935 void *plContext) | |
936 { | |
937 PKIX_ENTER(VALIDATE, "pkix_ExtractParameters"); | |
938 PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts); | |
939 PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors); | |
940 | |
941 /* extract relevant parameters from chain */ | |
942 PKIX_CHECK(PKIX_ValidateParams_GetCertChain | |
943 (valParams, pCerts, plContext), | |
944 PKIX_VALIDATEPARAMSGETCERTCHAINFAILED); | |
945 | |
946 PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext), | |
947 PKIX_LISTGETLENGTHFAILED); | |
948 | |
949 /* extract relevant parameters from procParams */ | |
950 PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams | |
951 (valParams, pProcParams, plContext), | |
952 PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED); | |
953 | |
954 PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors | |
955 (*pProcParams, pAnchors, plContext), | |
956 PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); | |
957 | |
958 PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext), | |
959 PKIX_LISTGETLENGTHFAILED); | |
960 | |
961 cleanup: | |
962 | |
963 PKIX_RETURN(VALIDATE); | |
964 } | |
965 | |
966 /* --Public-Functions--------------------------------------------- */ | |
967 | |
968 /* | |
969 * FUNCTION: PKIX_ValidateChain (see comments in pkix.h) | |
970 */ | |
971 PKIX_Error * | |
972 PKIX_ValidateChain( | |
973 PKIX_ValidateParams *valParams, | |
974 PKIX_ValidateResult **pResult, | |
975 PKIX_VerifyNode **pVerifyTree, | |
976 void *plContext) | |
977 { | |
978 PKIX_Error *chainFailed = NULL; | |
979 | |
980 PKIX_ProcessingParams *procParams = NULL; | |
981 PKIX_CertChainChecker *userChecker = NULL; | |
982 PKIX_RevocationChecker *revChecker = NULL; | |
983 PKIX_List *certs = NULL; | |
984 PKIX_List *checkers = NULL; | |
985 PKIX_List *anchors = NULL; | |
986 PKIX_List *userCheckers = NULL; | |
987 PKIX_List *userCheckerExtOIDs = NULL; | |
988 PKIX_List *validateCheckedCritExtOIDsList = NULL; | |
989 PKIX_TrustAnchor *anchor = NULL; | |
990 PKIX_ValidateResult *valResult = NULL; | |
991 PKIX_PL_PublicKey *finalPubKey = NULL; | |
992 PKIX_PolicyNode *validPolicyTree = NULL; | |
993 PKIX_Boolean supportForwarding = PKIX_FALSE; | |
994 PKIX_Boolean revChecking = PKIX_FALSE; | |
995 PKIX_UInt32 i, numCerts, numAnchors; | |
996 PKIX_UInt32 numUserCheckers = 0; | |
997 PKIX_UInt32 certCheckedIndex = 0; | |
998 PKIX_UInt32 checkerIndex = 0; | |
999 PKIX_UInt32 reasonCode = 0; | |
1000 void *nbioContext = NULL; | |
1001 | |
1002 PKIX_ENTER(VALIDATE, "PKIX_ValidateChain"); | |
1003 PKIX_NULLCHECK_TWO(valParams, pResult); | |
1004 | |
1005 /* extract various parameters from valParams */ | |
1006 PKIX_CHECK(pkix_ExtractParameters | |
1007 (valParams, | |
1008 &certs, | |
1009 &numCerts, | |
1010 &procParams, | |
1011 &anchors, | |
1012 &numAnchors, | |
1013 plContext), | |
1014 PKIX_EXTRACTPARAMETERSFAILED); | |
1015 | |
1016 /* | |
1017 * setup an extension OID list that user had defined for his checker | |
1018 * processing. User checker is not responsible for taking out OIDs | |
1019 * from unresolved critical extension list as the libpkix checker | |
1020 * is doing. Here we add those user checkers' OIDs to the removal | |
1021 * list to be taken out by CheckChain | |
1022 */ | |
1023 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers | |
1024 (procParams, &userCheckers, plContext), | |
1025 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); | |
1026 | |
1027 if (userCheckers != NULL) { | |
1028 | |
1029 PKIX_CHECK(PKIX_List_Create | |
1030 (&validateCheckedCritExtOIDsList, | |
1031 plContext), | |
1032 PKIX_LISTCREATEFAILED); | |
1033 | |
1034 PKIX_CHECK(PKIX_List_GetLength | |
1035 (userCheckers, &numUserCheckers, plContext), | |
1036 PKIX_LISTGETLENGTHFAILED); | |
1037 | |
1038 for (i = 0; i < numUserCheckers; i++) { | |
1039 | |
1040 PKIX_CHECK(PKIX_List_GetItem | |
1041 (userCheckers, | |
1042 i, | |
1043 (PKIX_PL_Object **) &userChecker, | |
1044 plContext), | |
1045 PKIX_LISTGETITEMFAILED); | |
1046 | |
1047 PKIX_CHECK | |
1048 (PKIX_CertChainChecker_IsForwardCheckingSupported | |
1049 (userChecker, &supportForwarding, plContext), | |
1050 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); | |
1051 | |
1052 if (supportForwarding == PKIX_FALSE) { | |
1053 | |
1054 PKIX_CHECK | |
1055 (PKIX_CertChainChecker_GetSupportedExtensions | |
1056 (userChecker, &userCheckerExtOIDs, plContext), | |
1057 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
1058 | |
1059 if (userCheckerExtOIDs != NULL) { | |
1060 PKIX_CHECK(pkix_List_AppendList | |
1061 (validateCheckedCritExtOIDsList, | |
1062 userCheckerExtOIDs, | |
1063 plContext), | |
1064 PKIX_LISTAPPENDLISTFAILED); | |
1065 } | |
1066 } | |
1067 | |
1068 PKIX_DECREF(userCheckerExtOIDs); | |
1069 PKIX_DECREF(userChecker); | |
1070 } | |
1071 } | |
1072 | |
1073 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker | |
1074 (procParams, &revChecker, plContext), | |
1075 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); | |
1076 | |
1077 /* try to validate the chain with each anchor */ | |
1078 for (i = 0; i < numAnchors; i++){ | |
1079 | |
1080 /* get trust anchor */ | |
1081 PKIX_CHECK(PKIX_List_GetItem | |
1082 (anchors, i, (PKIX_PL_Object **)&anchor, plContext), | |
1083 PKIX_LISTGETITEMFAILED); | |
1084 | |
1085 /* initialize checkers using information from trust anchor */ | |
1086 PKIX_CHECK(pkix_InitializeCheckers | |
1087 (anchor, procParams, numCerts, &checkers, plContext), | |
1088 PKIX_INITIALIZECHECKERSFAILED); | |
1089 | |
1090 /* | |
1091 * Validate the chain using this trust anchor and these | |
1092 * checkers. (WARNING: checkers that use non-blocking I/O | |
1093 * are not currently supported.) | |
1094 */ | |
1095 certCheckedIndex = 0; | |
1096 checkerIndex = 0; | |
1097 revChecking = PKIX_FALSE; | |
1098 chainFailed = pkix_CheckChain | |
1099 (certs, | |
1100 numCerts, | |
1101 anchor, | |
1102 checkers, | |
1103 revChecker, | |
1104 validateCheckedCritExtOIDsList, | |
1105 procParams, | |
1106 &certCheckedIndex, | |
1107 &checkerIndex, | |
1108 &revChecking, | |
1109 &reasonCode, | |
1110 &nbioContext, | |
1111 &finalPubKey, | |
1112 &validPolicyTree, | |
1113 pVerifyTree, | |
1114 plContext); | |
1115 | |
1116 if (chainFailed) { | |
1117 | |
1118 /* cert chain failed to validate */ | |
1119 | |
1120 PKIX_DECREF(chainFailed); | |
1121 PKIX_DECREF(anchor); | |
1122 PKIX_DECREF(checkers); | |
1123 PKIX_DECREF(validPolicyTree); | |
1124 | |
1125 /* if last anchor, we fail; else, we try next anchor */ | |
1126 if (i == (numAnchors - 1)) { /* last anchor */ | |
1127 PKIX_ERROR(PKIX_VALIDATECHAINFAILED); | |
1128 } | |
1129 | |
1130 } else { | |
1131 | |
1132 /* XXX Remove this assertion after 2014-12-31. | |
1133 * See bug 946984. */ | |
1134 PORT_Assert(reasonCode == 0); | |
1135 | |
1136 /* cert chain successfully validated! */ | |
1137 PKIX_CHECK(pkix_ValidateResult_Create | |
1138 (finalPubKey, | |
1139 anchor, | |
1140 validPolicyTree, | |
1141 &valResult, | |
1142 plContext), | |
1143 PKIX_VALIDATERESULTCREATEFAILED); | |
1144 | |
1145 *pResult = valResult; | |
1146 | |
1147 /* no need to try any more anchors in the loop */ | |
1148 goto cleanup; | |
1149 } | |
1150 } | |
1151 | |
1152 cleanup: | |
1153 | |
1154 PKIX_DECREF(finalPubKey); | |
1155 PKIX_DECREF(certs); | |
1156 PKIX_DECREF(anchors); | |
1157 PKIX_DECREF(anchor); | |
1158 PKIX_DECREF(checkers); | |
1159 PKIX_DECREF(revChecker); | |
1160 PKIX_DECREF(validPolicyTree); | |
1161 PKIX_DECREF(chainFailed); | |
1162 PKIX_DECREF(procParams); | |
1163 PKIX_DECREF(userCheckers); | |
1164 PKIX_DECREF(validateCheckedCritExtOIDsList); | |
1165 | |
1166 PKIX_RETURN(VALIDATE); | |
1167 } | |
1168 | |
1169 /* | |
1170 * FUNCTION: pkix_Validate_BuildUserOIDs | |
1171 * DESCRIPTION: | |
1172 * | |
1173 * This function creates a List of the OIDs that are processed by the user | |
1174 * checkers in the List pointed to by "userCheckers", storing the resulting | |
1175 * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output | |
1176 * List will be NULL. Otherwise the output List will be non-NULL, but may be | |
1177 * empty. | |
1178 * | |
1179 * PARAMETERS: | |
1180 * "userCheckers" | |
1181 * The address of the List of userCheckers. | |
1182 * "pUserCritOIDs" | |
1183 * The address at which the List is stored. Must be non-NULL. | |
1184 * "plContext" | |
1185 * Platform-specific context pointer. | |
1186 * THREAD SAFETY: | |
1187 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1188 * RETURNS: | |
1189 * Returns NULL if the function succeeds. | |
1190 * Returns a VALIDATE Error if the function fails in a non-fatal way. | |
1191 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1192 */ | |
1193 static PKIX_Error * | |
1194 pkix_Validate_BuildUserOIDs( | |
1195 PKIX_List *userCheckers, | |
1196 PKIX_List **pUserCritOIDs, | |
1197 void *plContext) | |
1198 { | |
1199 PKIX_UInt32 numUserCheckers = 0; | |
1200 PKIX_UInt32 i = 0; | |
1201 PKIX_List *userCritOIDs = NULL; | |
1202 PKIX_List *userCheckerExtOIDs = NULL; | |
1203 PKIX_Boolean supportForwarding = PKIX_FALSE; | |
1204 PKIX_CertChainChecker *userChecker = NULL; | |
1205 | |
1206 PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs"); | |
1207 PKIX_NULLCHECK_ONE(pUserCritOIDs); | |
1208 | |
1209 if (userCheckers != NULL) { | |
1210 PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext), | |
1211 PKIX_LISTCREATEFAILED); | |
1212 | |
1213 PKIX_CHECK(PKIX_List_GetLength | |
1214 (userCheckers, &numUserCheckers, plContext), | |
1215 PKIX_LISTGETLENGTHFAILED); | |
1216 | |
1217 for (i = 0; i < numUserCheckers; i++) { | |
1218 PKIX_CHECK(PKIX_List_GetItem | |
1219 (userCheckers, | |
1220 i, | |
1221 (PKIX_PL_Object **) &userChecker, | |
1222 plContext), | |
1223 PKIX_LISTGETITEMFAILED); | |
1224 | |
1225 PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported | |
1226 (userChecker, &supportForwarding, plContext), | |
1227 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); | |
1228 | |
1229 if (supportForwarding == PKIX_FALSE) { | |
1230 | |
1231 PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions | |
1232 (userChecker, &userCheckerExtOIDs, plContext), | |
1233 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
1234 | |
1235 if (userCheckerExtOIDs != NULL) { | |
1236 PKIX_CHECK(pkix_List_AppendList | |
1237 (userCritOIDs, userCheckerExtOIDs, plContext), | |
1238 PKIX_LISTAPPENDLISTFAILED); | |
1239 } | |
1240 } | |
1241 | |
1242 PKIX_DECREF(userCheckerExtOIDs); | |
1243 PKIX_DECREF(userChecker); | |
1244 } | |
1245 } | |
1246 | |
1247 *pUserCritOIDs = userCritOIDs; | |
1248 | |
1249 cleanup: | |
1250 | |
1251 if (PKIX_ERROR_RECEIVED){ | |
1252 PKIX_DECREF(userCritOIDs); | |
1253 } | |
1254 | |
1255 PKIX_DECREF(userCheckerExtOIDs); | |
1256 PKIX_DECREF(userChecker); | |
1257 | |
1258 PKIX_RETURN(VALIDATE); | |
1259 } | |
1260 | |
1261 /* | |
1262 * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h) | |
1263 */ | |
1264 PKIX_Error * | |
1265 PKIX_ValidateChain_NB( | |
1266 PKIX_ValidateParams *valParams, | |
1267 PKIX_UInt32 *pCertIndex, | |
1268 PKIX_UInt32 *pAnchorIndex, | |
1269 PKIX_UInt32 *pCheckerIndex, | |
1270 PKIX_Boolean *pRevChecking, | |
1271 PKIX_List **pCheckers, | |
1272 void **pNBIOContext, | |
1273 PKIX_ValidateResult **pResult, | |
1274 PKIX_VerifyNode **pVerifyTree, | |
1275 void *plContext) | |
1276 { | |
1277 PKIX_UInt32 numCerts = 0; | |
1278 PKIX_UInt32 numAnchors = 0; | |
1279 PKIX_UInt32 i = 0; | |
1280 PKIX_UInt32 certIndex = 0; | |
1281 PKIX_UInt32 anchorIndex = 0; | |
1282 PKIX_UInt32 checkerIndex = 0; | |
1283 PKIX_UInt32 reasonCode = 0; | |
1284 PKIX_Boolean revChecking = PKIX_FALSE; | |
1285 PKIX_List *certs = NULL; | |
1286 PKIX_List *anchors = NULL; | |
1287 PKIX_List *checkers = NULL; | |
1288 PKIX_List *userCheckers = NULL; | |
1289 PKIX_List *validateCheckedCritExtOIDsList = NULL; | |
1290 PKIX_TrustAnchor *anchor = NULL; | |
1291 PKIX_ValidateResult *valResult = NULL; | |
1292 PKIX_PL_PublicKey *finalPubKey = NULL; | |
1293 PKIX_PolicyNode *validPolicyTree = NULL; | |
1294 PKIX_ProcessingParams *procParams = NULL; | |
1295 PKIX_RevocationChecker *revChecker = NULL; | |
1296 PKIX_Error *chainFailed = NULL; | |
1297 void *nbioContext = NULL; | |
1298 | |
1299 PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB"); | |
1300 PKIX_NULLCHECK_FOUR | |
1301 (valParams, pCertIndex, pAnchorIndex, pCheckerIndex); | |
1302 PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult); | |
1303 | |
1304 nbioContext = *pNBIOContext; | |
1305 *pNBIOContext = NULL; | |
1306 | |
1307 /* extract various parameters from valParams */ | |
1308 PKIX_CHECK(pkix_ExtractParameters | |
1309 (valParams, | |
1310 &certs, | |
1311 &numCerts, | |
1312 &procParams, | |
1313 &anchors, | |
1314 &numAnchors, | |
1315 plContext), | |
1316 PKIX_EXTRACTPARAMETERSFAILED); | |
1317 | |
1318 /* | |
1319 * Create a List of the OIDs that will be processed by the user | |
1320 * checkers. User checkers are not responsible for removing OIDs from | |
1321 * the List of unresolved critical extensions, as libpkix checkers are. | |
1322 * So we add those user checkers' OIDs to the removal list to be taken | |
1323 * out by CheckChain. | |
1324 */ | |
1325 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers | |
1326 (procParams, &userCheckers, plContext), | |
1327 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); | |
1328 | |
1329 PKIX_CHECK(pkix_Validate_BuildUserOIDs | |
1330 (userCheckers, &validateCheckedCritExtOIDsList, plContext), | |
1331 PKIX_VALIDATEBUILDUSEROIDSFAILED); | |
1332 | |
1333 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker | |
1334 (procParams, &revChecker, plContext), | |
1335 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); | |
1336 | |
1337 /* Are we resuming after a WOULDBLOCK return, or starting anew ? */ | |
1338 if (nbioContext != NULL) { | |
1339 /* Resuming */ | |
1340 certIndex = *pCertIndex; | |
1341 anchorIndex = *pAnchorIndex; | |
1342 checkerIndex = *pCheckerIndex; | |
1343 revChecking = *pRevChecking; | |
1344 checkers = *pCheckers; | |
1345 *pCheckers = NULL; | |
1346 } | |
1347 | |
1348 /* try to validate the chain with each anchor */ | |
1349 for (i = anchorIndex; i < numAnchors; i++) { | |
1350 | |
1351 /* get trust anchor */ | |
1352 PKIX_CHECK(PKIX_List_GetItem | |
1353 (anchors, i, (PKIX_PL_Object **)&anchor, plContext), | |
1354 PKIX_LISTGETITEMFAILED); | |
1355 | |
1356 /* initialize checkers using information from trust anchor */ | |
1357 if (nbioContext == NULL) { | |
1358 PKIX_CHECK(pkix_InitializeCheckers | |
1359 (anchor, | |
1360 procParams, | |
1361 numCerts, | |
1362 &checkers, | |
1363 plContext), | |
1364 PKIX_INITIALIZECHECKERSFAILED); | |
1365 } | |
1366 | |
1367 /* | |
1368 * Validate the chain using this trust anchor and these | |
1369 * checkers. | |
1370 */ | |
1371 chainFailed = pkix_CheckChain | |
1372 (certs, | |
1373 numCerts, | |
1374 anchor, | |
1375 checkers, | |
1376 revChecker, | |
1377 validateCheckedCritExtOIDsList, | |
1378 procParams, | |
1379 &certIndex, | |
1380 &checkerIndex, | |
1381 &revChecking, | |
1382 &reasonCode, | |
1383 &nbioContext, | |
1384 &finalPubKey, | |
1385 &validPolicyTree, | |
1386 pVerifyTree, | |
1387 plContext); | |
1388 | |
1389 if (nbioContext != NULL) { | |
1390 *pCertIndex = certIndex; | |
1391 *pAnchorIndex = anchorIndex; | |
1392 *pCheckerIndex = checkerIndex; | |
1393 *pRevChecking = revChecking; | |
1394 PKIX_INCREF(checkers); | |
1395 *pCheckers = checkers; | |
1396 *pNBIOContext = nbioContext; | |
1397 goto cleanup; | |
1398 } | |
1399 | |
1400 if (chainFailed) { | |
1401 | |
1402 /* cert chain failed to validate */ | |
1403 | |
1404 PKIX_DECREF(chainFailed); | |
1405 PKIX_DECREF(anchor); | |
1406 PKIX_DECREF(checkers); | |
1407 PKIX_DECREF(validPolicyTree); | |
1408 | |
1409 /* if last anchor, we fail; else, we try next anchor */ | |
1410 if (i == (numAnchors - 1)) { /* last anchor */ | |
1411 PKIX_ERROR(PKIX_VALIDATECHAINFAILED); | |
1412 } | |
1413 | |
1414 } else { | |
1415 | |
1416 /* XXX Remove this assertion after 2014-12-31. | |
1417 * See bug 946984. */ | |
1418 PORT_Assert(reasonCode == 0); | |
1419 | |
1420 /* cert chain successfully validated! */ | |
1421 PKIX_CHECK(pkix_ValidateResult_Create | |
1422 (finalPubKey, | |
1423 anchor, | |
1424 validPolicyTree, | |
1425 &valResult, | |
1426 plContext), | |
1427 PKIX_VALIDATERESULTCREATEFAILED); | |
1428 | |
1429 *pResult = valResult; | |
1430 | |
1431 /* no need to try any more anchors in the loop */ | |
1432 goto cleanup; | |
1433 } | |
1434 } | |
1435 | |
1436 cleanup: | |
1437 | |
1438 PKIX_DECREF(finalPubKey); | |
1439 PKIX_DECREF(certs); | |
1440 PKIX_DECREF(anchors); | |
1441 PKIX_DECREF(anchor); | |
1442 PKIX_DECREF(checkers); | |
1443 PKIX_DECREF(revChecker); | |
1444 PKIX_DECREF(validPolicyTree); | |
1445 PKIX_DECREF(chainFailed); | |
1446 PKIX_DECREF(procParams); | |
1447 PKIX_DECREF(userCheckers); | |
1448 PKIX_DECREF(validateCheckedCritExtOIDsList); | |
1449 | |
1450 PKIX_RETURN(VALIDATE); | |
1451 } |