~ubuntu-branches/ubuntu/lucid/nss/lucid-security

« back to all changes in this revision

Viewing changes to nss/lib/libpkix/pkix/top/pkix_validate.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-15 08:08:08 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20131115080808-dba1asgnjl9tc66s
Tags: 3.15.3-0ubuntu0.10.04.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/01_dont_build_nspr.patch: removed, changed build
    options in debian/rules instead.
  - debian/libnss3-1d.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 || (reasonCode != 0)) {
 
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
                        /* cert chain successfully validated! */
 
1133
                        PKIX_CHECK(pkix_ValidateResult_Create
 
1134
                                (finalPubKey,
 
1135
                                anchor,
 
1136
                                validPolicyTree,
 
1137
                                &valResult,
 
1138
                                plContext),
 
1139
                                PKIX_VALIDATERESULTCREATEFAILED);
 
1140
 
 
1141
                        *pResult = valResult;
 
1142
 
 
1143
                        /* no need to try any more anchors in the loop */
 
1144
                        goto cleanup;
 
1145
                }
 
1146
        }
 
1147
 
 
1148
cleanup:
 
1149
 
 
1150
        PKIX_DECREF(finalPubKey);
 
1151
        PKIX_DECREF(certs);
 
1152
        PKIX_DECREF(anchors);
 
1153
        PKIX_DECREF(anchor);
 
1154
        PKIX_DECREF(checkers);
 
1155
        PKIX_DECREF(revChecker);
 
1156
        PKIX_DECREF(validPolicyTree);
 
1157
        PKIX_DECREF(chainFailed);
 
1158
        PKIX_DECREF(procParams);
 
1159
        PKIX_DECREF(userCheckers);
 
1160
        PKIX_DECREF(validateCheckedCritExtOIDsList);
 
1161
 
 
1162
        PKIX_RETURN(VALIDATE);
 
1163
}
 
1164
 
 
1165
/*
 
1166
 * FUNCTION: pkix_Validate_BuildUserOIDs
 
1167
 * DESCRIPTION:
 
1168
 *
 
1169
 *  This function creates a List of the OIDs that are processed by the user
 
1170
 *  checkers in the List pointed to by "userCheckers", storing the resulting
 
1171
 *  List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
 
1172
 *  List will be NULL. Otherwise the output List will be non-NULL, but may be
 
1173
 *  empty.
 
1174
 *
 
1175
 * PARAMETERS:
 
1176
 *  "userCheckers"
 
1177
 *      The address of the List of userCheckers.
 
1178
 *  "pUserCritOIDs"
 
1179
 *      The address at which the List is stored. Must be non-NULL.
 
1180
 *  "plContext"
 
1181
 *      Platform-specific context pointer.
 
1182
 * THREAD SAFETY:
 
1183
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 
1184
 * RETURNS:
 
1185
 *  Returns NULL if the function succeeds.
 
1186
 *  Returns a VALIDATE Error if the function fails in a non-fatal way.
 
1187
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 
1188
 */
 
1189
static PKIX_Error *
 
1190
pkix_Validate_BuildUserOIDs(
 
1191
        PKIX_List *userCheckers,
 
1192
        PKIX_List **pUserCritOIDs,
 
1193
        void *plContext)
 
1194
{
 
1195
        PKIX_UInt32 numUserCheckers = 0;
 
1196
        PKIX_UInt32 i = 0;
 
1197
        PKIX_List *userCritOIDs = NULL;
 
1198
        PKIX_List *userCheckerExtOIDs = NULL;
 
1199
        PKIX_Boolean supportForwarding = PKIX_FALSE;
 
1200
        PKIX_CertChainChecker *userChecker = NULL;
 
1201
 
 
1202
        PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
 
1203
        PKIX_NULLCHECK_ONE(pUserCritOIDs);
 
1204
 
 
1205
        if (userCheckers != NULL) {
 
1206
            PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
 
1207
                PKIX_LISTCREATEFAILED);
 
1208
 
 
1209
            PKIX_CHECK(PKIX_List_GetLength
 
1210
                (userCheckers, &numUserCheckers, plContext),
 
1211
                PKIX_LISTGETLENGTHFAILED);
 
1212
 
 
1213
            for (i = 0; i < numUserCheckers; i++) {
 
1214
                PKIX_CHECK(PKIX_List_GetItem
 
1215
                    (userCheckers,
 
1216
                    i,
 
1217
                    (PKIX_PL_Object **) &userChecker,
 
1218
                    plContext),
 
1219
                    PKIX_LISTGETITEMFAILED);
 
1220
 
 
1221
                PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
 
1222
                    (userChecker, &supportForwarding, plContext),
 
1223
                    PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
 
1224
 
 
1225
                if (supportForwarding == PKIX_FALSE) {
 
1226
 
 
1227
                    PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
 
1228
                        (userChecker, &userCheckerExtOIDs, plContext),
 
1229
                        PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
 
1230
 
 
1231
                    if (userCheckerExtOIDs != NULL) {
 
1232
                        PKIX_CHECK(pkix_List_AppendList
 
1233
                            (userCritOIDs, userCheckerExtOIDs, plContext),
 
1234
                            PKIX_LISTAPPENDLISTFAILED);
 
1235
                    }
 
1236
                }
 
1237
 
 
1238
                PKIX_DECREF(userCheckerExtOIDs);
 
1239
                PKIX_DECREF(userChecker);
 
1240
            }
 
1241
        }
 
1242
 
 
1243
        *pUserCritOIDs = userCritOIDs;
 
1244
 
 
1245
cleanup:
 
1246
 
 
1247
        if (PKIX_ERROR_RECEIVED){
 
1248
                PKIX_DECREF(userCritOIDs);
 
1249
        }
 
1250
 
 
1251
        PKIX_DECREF(userCheckerExtOIDs);
 
1252
        PKIX_DECREF(userChecker);
 
1253
 
 
1254
        PKIX_RETURN(VALIDATE);
 
1255
}
 
1256
 
 
1257
/*
 
1258
 * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
 
1259
 */
 
1260
PKIX_Error *
 
1261
PKIX_ValidateChain_NB(
 
1262
        PKIX_ValidateParams *valParams,
 
1263
        PKIX_UInt32 *pCertIndex,
 
1264
        PKIX_UInt32 *pAnchorIndex,
 
1265
        PKIX_UInt32 *pCheckerIndex,
 
1266
        PKIX_Boolean *pRevChecking,
 
1267
        PKIX_List **pCheckers,
 
1268
        void **pNBIOContext,
 
1269
        PKIX_ValidateResult **pResult,
 
1270
        PKIX_VerifyNode **pVerifyTree,
 
1271
        void *plContext)
 
1272
{
 
1273
        PKIX_UInt32 numCerts = 0;
 
1274
        PKIX_UInt32 numAnchors = 0;
 
1275
        PKIX_UInt32 i = 0;
 
1276
        PKIX_UInt32 certIndex = 0;
 
1277
        PKIX_UInt32 anchorIndex = 0;
 
1278
        PKIX_UInt32 checkerIndex = 0;
 
1279
        PKIX_UInt32 reasonCode = 0;
 
1280
        PKIX_Boolean revChecking = PKIX_FALSE;
 
1281
        PKIX_List *certs = NULL;
 
1282
        PKIX_List *anchors = NULL;
 
1283
        PKIX_List *checkers = NULL;
 
1284
        PKIX_List *userCheckers = NULL;
 
1285
        PKIX_List *validateCheckedCritExtOIDsList = NULL;
 
1286
        PKIX_TrustAnchor *anchor = NULL;
 
1287
        PKIX_ValidateResult *valResult = NULL;
 
1288
        PKIX_PL_PublicKey *finalPubKey = NULL;
 
1289
        PKIX_PolicyNode *validPolicyTree = NULL;
 
1290
        PKIX_ProcessingParams *procParams = NULL;
 
1291
        PKIX_RevocationChecker *revChecker = NULL;
 
1292
        PKIX_Error *chainFailed = NULL;
 
1293
        void *nbioContext = NULL;
 
1294
 
 
1295
        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
 
1296
        PKIX_NULLCHECK_FOUR
 
1297
                (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
 
1298
        PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
 
1299
 
 
1300
        nbioContext = *pNBIOContext;
 
1301
        *pNBIOContext = NULL;
 
1302
 
 
1303
        /* extract various parameters from valParams */
 
1304
        PKIX_CHECK(pkix_ExtractParameters
 
1305
                    (valParams,
 
1306
                    &certs,
 
1307
                    &numCerts,
 
1308
                    &procParams,
 
1309
                    &anchors,
 
1310
                    &numAnchors,
 
1311
                    plContext),
 
1312
                    PKIX_EXTRACTPARAMETERSFAILED);
 
1313
 
 
1314
        /*
 
1315
         * Create a List of the OIDs that will be processed by the user
 
1316
         * checkers. User checkers are not responsible for removing OIDs from
 
1317
         * the List of unresolved critical extensions, as libpkix checkers are.
 
1318
         * So we add those user checkers' OIDs to the removal list to be taken
 
1319
         * out by CheckChain.
 
1320
         */
 
1321
        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
 
1322
                (procParams, &userCheckers, plContext),
 
1323
                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
 
1324
 
 
1325
        PKIX_CHECK(pkix_Validate_BuildUserOIDs
 
1326
                (userCheckers, &validateCheckedCritExtOIDsList, plContext),
 
1327
                PKIX_VALIDATEBUILDUSEROIDSFAILED);
 
1328
 
 
1329
        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
 
1330
                (procParams, &revChecker, plContext),
 
1331
                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
 
1332
 
 
1333
        /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
 
1334
        if (nbioContext != NULL) {
 
1335
                /* Resuming */
 
1336
                certIndex = *pCertIndex;
 
1337
                anchorIndex = *pAnchorIndex;
 
1338
                checkerIndex = *pCheckerIndex;
 
1339
                revChecking = *pRevChecking;
 
1340
                checkers = *pCheckers;
 
1341
                *pCheckers = NULL;
 
1342
        }
 
1343
 
 
1344
        /* try to validate the chain with each anchor */
 
1345
        for (i = anchorIndex; i < numAnchors; i++) {
 
1346
 
 
1347
                /* get trust anchor */
 
1348
                PKIX_CHECK(PKIX_List_GetItem
 
1349
                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
 
1350
                        PKIX_LISTGETITEMFAILED);
 
1351
 
 
1352
                /* initialize checkers using information from trust anchor */
 
1353
                if (nbioContext == NULL) {
 
1354
                        PKIX_CHECK(pkix_InitializeCheckers
 
1355
                                (anchor,
 
1356
                                procParams,
 
1357
                                numCerts,
 
1358
                                &checkers,
 
1359
                                plContext),
 
1360
                                PKIX_INITIALIZECHECKERSFAILED);
 
1361
                }
 
1362
 
 
1363
                /*
 
1364
                 * Validate the chain using this trust anchor and these
 
1365
                 * checkers.
 
1366
                 */
 
1367
                chainFailed = pkix_CheckChain
 
1368
                        (certs,
 
1369
                        numCerts,
 
1370
                        anchor,
 
1371
                        checkers,
 
1372
                        revChecker,
 
1373
                        validateCheckedCritExtOIDsList,
 
1374
                        procParams,
 
1375
                        &certIndex,
 
1376
                        &checkerIndex,
 
1377
                        &revChecking,
 
1378
                        &reasonCode,
 
1379
                        &nbioContext,
 
1380
                        &finalPubKey,
 
1381
                        &validPolicyTree,
 
1382
                        pVerifyTree,
 
1383
                        plContext);
 
1384
 
 
1385
                if (nbioContext != NULL) {
 
1386
                        *pCertIndex = certIndex;
 
1387
                        *pAnchorIndex = anchorIndex;
 
1388
                        *pCheckerIndex = checkerIndex;
 
1389
                        *pRevChecking = revChecking;
 
1390
                        PKIX_INCREF(checkers);
 
1391
                        *pCheckers = checkers;
 
1392
                        *pNBIOContext = nbioContext;
 
1393
                        goto cleanup;
 
1394
                }
 
1395
 
 
1396
                if (chainFailed || (reasonCode != 0)) {
 
1397
 
 
1398
                        /* cert chain failed to validate */
 
1399
 
 
1400
                        PKIX_DECREF(chainFailed);
 
1401
                        PKIX_DECREF(anchor);
 
1402
                        PKIX_DECREF(checkers);
 
1403
                        PKIX_DECREF(validPolicyTree);
 
1404
 
 
1405
                        /* if last anchor, we fail; else, we try next anchor */
 
1406
                        if (i == (numAnchors - 1)) { /* last anchor */
 
1407
                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
 
1408
                        }
 
1409
 
 
1410
                } else {
 
1411
 
 
1412
                        /* cert chain successfully validated! */
 
1413
                        PKIX_CHECK(pkix_ValidateResult_Create
 
1414
                                (finalPubKey,
 
1415
                                anchor,
 
1416
                                validPolicyTree,
 
1417
                                &valResult,
 
1418
                                plContext),
 
1419
                                PKIX_VALIDATERESULTCREATEFAILED);
 
1420
 
 
1421
                        *pResult = valResult;
 
1422
 
 
1423
                        /* no need to try any more anchors in the loop */
 
1424
                        goto cleanup;
 
1425
                }
 
1426
        }
 
1427
 
 
1428
cleanup:
 
1429
 
 
1430
        PKIX_DECREF(finalPubKey);
 
1431
        PKIX_DECREF(certs);
 
1432
        PKIX_DECREF(anchors);
 
1433
        PKIX_DECREF(anchor);
 
1434
        PKIX_DECREF(checkers);
 
1435
        PKIX_DECREF(revChecker);
 
1436
        PKIX_DECREF(validPolicyTree);
 
1437
        PKIX_DECREF(chainFailed);
 
1438
        PKIX_DECREF(procParams);
 
1439
        PKIX_DECREF(userCheckers);
 
1440
        PKIX_DECREF(validateCheckedCritExtOIDsList);
 
1441
 
 
1442
        PKIX_RETURN(VALIDATE);
 
1443
}