PageRenderTime 46ms CodeModel.GetById 16ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c

http://github.com/zpao/v8monkey
C | 549 lines | 305 code | 93 blank | 151 comment | 36 complexity | 5d6d3205b2275afc04f18a40e9368815 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the PKIX-C library.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Sun Microsystems, Inc.
 18 * Portions created by the Initial Developer are
 19 * Copyright 2004-2007 Sun Microsystems, Inc.  All Rights Reserved.
 20 *
 21 * Contributor(s):
 22 *   Sun Microsystems, Inc.
 23 *
 24 * Alternatively, the contents of this file may be used under the terms of
 25 * either the GNU General Public License Version 2 or later (the "GPL"), or
 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 27 * in which case the provisions of the GPL or the LGPL are applicable instead
 28 * of those above. If you wish to allow use of your version of this file only
 29 * under the terms of either the GPL or the LGPL, and not to allow others to
 30 * use your version of this file under the terms of the MPL, indicate your
 31 * decision by deleting the provisions above and replace them with the notice
 32 * and other provisions required by the GPL or the LGPL. If you do not delete
 33 * the provisions above, a recipient may use your version of this file under
 34 * the terms of any one of the MPL, the GPL or the LGPL.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37/*
 38 * pkix_targetcertchecker.c
 39 *
 40 * Functions for target cert validation
 41 *
 42 */
 43
 44
 45#include "pkix_targetcertchecker.h"
 46
 47/* --Private-TargetCertCheckerState-Functions------------------------------- */
 48
 49/*
 50 * FUNCTION: pkix_TargetCertCheckerState_Destroy
 51 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 52 */
 53static PKIX_Error *
 54pkix_TargetCertCheckerState_Destroy(
 55        PKIX_PL_Object *object,
 56        void *plContext)
 57{
 58        pkix_TargetCertCheckerState *state = NULL;
 59
 60        PKIX_ENTER(TARGETCERTCHECKERSTATE,
 61                    "pkix_TargetCertCheckerState_Destroy");
 62        PKIX_NULLCHECK_ONE(object);
 63
 64        /* Check that this object is a target cert checker state */
 65        PKIX_CHECK(pkix_CheckType
 66                    (object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
 67                    PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
 68
 69        state = (pkix_TargetCertCheckerState *)object;
 70
 71        PKIX_DECREF(state->certSelector);
 72        PKIX_DECREF(state->extKeyUsageOID);
 73        PKIX_DECREF(state->subjAltNameOID);
 74        PKIX_DECREF(state->pathToNameList);
 75        PKIX_DECREF(state->extKeyUsageList);
 76        PKIX_DECREF(state->subjAltNameList);
 77
 78cleanup:
 79
 80        PKIX_RETURN(TARGETCERTCHECKERSTATE);
 81}
 82
 83/*
 84 * FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
 85 * DESCRIPTION:
 86 *  Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
 87 *  systemClasses[]
 88 * THREAD SAFETY:
 89 *  Not Thread Safe - for performance and complexity reasons
 90 *
 91 *  Since this function is only called by PKIX_PL_Initialize, which should
 92 *  only be called once, it is acceptable that this function is not
 93 *  thread-safe.
 94 */
 95PKIX_Error *
 96pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
 97{
 98        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
 99        pkix_ClassTable_Entry entry;
100
101        PKIX_ENTER(TARGETCERTCHECKERSTATE,
102                    "pkix_TargetCertCheckerState_RegisterSelf");
103
104        entry.description = "TargetCertCheckerState";
105        entry.objCounter = 0;
106        entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
107        entry.destructor = pkix_TargetCertCheckerState_Destroy;
108        entry.equalsFunction = NULL;
109        entry.hashcodeFunction = NULL;
110        entry.toStringFunction = NULL;
111        entry.comparator = NULL;
112        entry.duplicateFunction = NULL;
113
114        systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
115
116        PKIX_RETURN(TARGETCERTCHECKERSTATE);
117}
118
119/*
120 * FUNCTION: pkix_TargetCertCheckerState_Create
121 * DESCRIPTION:
122 *
123 *  Creates a new TargetCertCheckerState using the CertSelector pointed to
124 *  by "certSelector" and the number of certs represented by "certsRemaining"
125 *  and stores it at "pState".
126 *
127 * PARAMETERS:
128 *  "certSelector"
129 *      Address of CertSelector representing the criteria against which the
130 *      final certificate in a chain is to be matched. Must be non-NULL.
131 *  "certsRemaining"
132 *      Number of certificates remaining in the chain.
133 *  "pState"
134 *      Address where object pointer will be stored. Must be non-NULL.
135 *  "plContext"
136 *      Platform-specific context pointer.
137 * THREAD SAFETY:
138 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
139 * RETURNS:
140 *  Returns NULL if the function succeeds.
141 *  Returns a TargetCertCheckerState Error if the function fails in a
142 *      non-fatal way.
143 *  Returns a Fatal Error if the function fails in an unrecoverable way.
144 */
145PKIX_Error *
146pkix_TargetCertCheckerState_Create(
147    PKIX_CertSelector *certSelector,
148    PKIX_UInt32 certsRemaining,
149    pkix_TargetCertCheckerState **pState,
150    void *plContext)
151{
152        pkix_TargetCertCheckerState *state = NULL;
153        PKIX_ComCertSelParams *certSelectorParams = NULL;
154        PKIX_List *pathToNameList = NULL;
155        PKIX_List *extKeyUsageList = NULL;
156        PKIX_List *subjAltNameList = NULL;
157        PKIX_PL_OID *extKeyUsageOID = NULL;
158        PKIX_PL_OID *subjAltNameOID = NULL;
159        PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
160
161        PKIX_ENTER(TARGETCERTCHECKERSTATE,
162                    "pkix_TargetCertCheckerState_Create");
163        PKIX_NULLCHECK_ONE(pState);
164
165        PKIX_CHECK(PKIX_PL_OID_Create
166                    (PKIX_EXTENDEDKEYUSAGE_OID,
167                    &extKeyUsageOID,
168                    plContext),
169                    PKIX_OIDCREATEFAILED);
170
171        PKIX_CHECK(PKIX_PL_OID_Create
172                    (PKIX_CERTSUBJALTNAME_OID,
173                    &subjAltNameOID,
174                    plContext),
175                    PKIX_OIDCREATEFAILED);
176
177        PKIX_CHECK(PKIX_PL_Object_Alloc
178                    (PKIX_TARGETCERTCHECKERSTATE_TYPE,
179                    sizeof (pkix_TargetCertCheckerState),
180                    (PKIX_PL_Object **)&state,
181                    plContext),
182                    PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
183
184        /* initialize fields */
185
186        if (certSelector != NULL) {
187
188                PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
189                        (certSelector, &certSelectorParams, plContext),
190                        PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
191
192                if (certSelectorParams != NULL) {
193
194                        PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
195                            (certSelectorParams,
196                            &pathToNameList,
197                            plContext),
198                            PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
199
200                        PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
201                            (certSelectorParams,
202                            &extKeyUsageList,
203                            plContext),
204                            PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
205
206                        PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
207                            (certSelectorParams,
208                            &subjAltNameList,
209                            plContext),
210                            PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
211
212                        PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
213                            (certSelectorParams,
214                            &subjAltNameMatchAll,
215                            plContext),
216                            PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
217                }
218        }
219
220        state->certsRemaining = certsRemaining;
221        state->subjAltNameMatchAll = subjAltNameMatchAll;
222
223        PKIX_INCREF(certSelector);
224        state->certSelector = certSelector;
225
226        state->pathToNameList = pathToNameList;
227        pathToNameList = NULL;
228
229        state->extKeyUsageList = extKeyUsageList;
230        extKeyUsageList = NULL;
231
232        state->subjAltNameList = subjAltNameList;
233        subjAltNameList = NULL;
234
235        state->extKeyUsageOID = extKeyUsageOID;
236        extKeyUsageOID = NULL;
237
238        state->subjAltNameOID = subjAltNameOID;
239        subjAltNameOID = NULL;
240
241        *pState = state;
242        state = NULL;
243
244cleanup:
245        
246        PKIX_DECREF(extKeyUsageOID);
247        PKIX_DECREF(subjAltNameOID);
248        PKIX_DECREF(pathToNameList);
249        PKIX_DECREF(extKeyUsageList);
250        PKIX_DECREF(subjAltNameList);
251        PKIX_DECREF(state);
252
253        PKIX_DECREF(certSelectorParams);
254
255        PKIX_RETURN(TARGETCERTCHECKERSTATE);
256
257}
258
259/* --Private-TargetCertChecker-Functions------------------------------- */
260
261/*
262 * FUNCTION: pkix_TargetCertChecker_Check
263 * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
264 */
265PKIX_Error *
266pkix_TargetCertChecker_Check(
267        PKIX_CertChainChecker *checker,
268        PKIX_PL_Cert *cert,
269        PKIX_List *unresolvedCriticalExtensions,
270        void **pNBIOContext,
271        void *plContext)
272{
273        pkix_TargetCertCheckerState *state = NULL;
274        PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
275        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
276        PKIX_List *certSubjAltNames = NULL;
277        PKIX_List *certExtKeyUsageList = NULL;
278        PKIX_PL_GeneralName *name = NULL;
279        PKIX_PL_X500Name *certSubjectName = NULL;
280        PKIX_Boolean checkPassed = PKIX_FALSE;
281        PKIX_UInt32 numItems, i;
282        PKIX_UInt32 matchCount = 0;
283
284        PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
285        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
286
287        *pNBIOContext = NULL; /* we never block on pending I/O */
288
289        PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
290                    (checker, (PKIX_PL_Object **)&state, plContext),
291                    PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
292
293        (state->certsRemaining)--;
294
295        if (state->pathToNameList != NULL) {
296
297                PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
298                    (cert, &nameConstraints, plContext),
299                    PKIX_CERTGETNAMECONSTRAINTSFAILED);
300
301                /*
302                 * XXX We should either make the following call a public one
303                 * so it is legal to call from the portability layer or we
304                 * should try to create pathToNameList as CertNameConstraints
305                 * then call the existing check function.
306                 */
307                PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
308                    (state->pathToNameList,
309                    nameConstraints,
310                    &checkPassed,
311                    plContext),
312                    PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
313
314                if (checkPassed != PKIX_TRUE) {
315                    PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
316                }
317
318        }
319
320        PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
321                    (cert, &certSubjAltNames, plContext),
322                    PKIX_CERTGETSUBJALTNAMESFAILED);
323
324        if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
325
326                PKIX_CHECK(PKIX_List_GetLength
327                        (state->subjAltNameList, &numItems, plContext),
328                        PKIX_LISTGETLENGTHFAILED);
329
330                for (i = 0; i < numItems; i++) {
331
332                        PKIX_CHECK(PKIX_List_GetItem
333                            (state->subjAltNameList,
334                            i,
335                            (PKIX_PL_Object **) &name,
336                            plContext),
337                            PKIX_LISTGETITEMFAILED);
338
339                        PKIX_CHECK(pkix_List_Contains
340                            (certSubjAltNames,
341                            (PKIX_PL_Object *) name,
342                            &checkPassed,
343                            plContext),
344                            PKIX_LISTCONTAINSFAILED);
345
346                        PKIX_DECREF(name);
347
348                        if (checkPassed == PKIX_TRUE) {
349
350                            if (state->subjAltNameMatchAll == PKIX_FALSE) {
351                                matchCount = numItems;
352                                break;
353                            } else {
354                                /* else continue checking next */
355                                matchCount++;
356                            }
357
358                        }
359                }
360
361                if (matchCount != numItems) {
362                        PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
363
364                }
365        }
366
367        if (state->certsRemaining == 0) {
368
369            if (state->certSelector != NULL) {
370                PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
371                           (state->certSelector,
372                            &certSelectorMatch,
373                            plContext),
374                           PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
375
376                PKIX_CHECK(certSelectorMatch
377                           (state->certSelector,
378                            cert,
379                            plContext),
380                           PKIX_CERTSELECTORMATCHFAILED);
381            } else {
382                /* Check at least cert/key usages if target cert selector
383                 * is not set. */
384                PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
385                                         PKIX_FALSE  /* is chain cert*/,
386                                         plContext),
387                           PKIX_CERTVERIFYCERTTYPEFAILED);
388            }
389            /*
390             * There are two Extended Key Usage Checkings
391             * available :
392             * 1) here at the targetcertchecker where we
393             *    verify the Extended Key Usage OIDs application
394             *    specifies via ComCertSelParams are included
395             *    in Cert's Extended Key Usage OID's. Note,
396             *    this is an OID to OID comparison and only last
397             *    Cert is checked.
398             * 2) at user defined ekuchecker where checking
399             *    is applied to all Certs on the chain and
400             *    the NSS Extended Key Usage algorithm is
401             *    used. In order to invoke this checking, not
402             *    only does the ComCertSelparams needs to be
403             *    set, the EKU initialize call is required to
404             *    activate the checking.
405             *
406             * XXX We use the same ComCertSelParams Set/Get
407             * functions to set the parameters for both cases.
408             * We may want to separate them in the future.
409             */
410            
411            PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
412                       (cert, &certExtKeyUsageList, plContext),
413                       PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
414            
415            
416            if (state->extKeyUsageList != NULL &&
417                certExtKeyUsageList != NULL) {
418                
419                PKIX_CHECK(PKIX_List_GetLength
420                           (state->extKeyUsageList, &numItems, plContext),
421                           PKIX_LISTGETLENGTHFAILED);
422                
423                for (i = 0; i < numItems; i++) {
424                    
425                    PKIX_CHECK(PKIX_List_GetItem
426                               (state->extKeyUsageList,
427                                i,
428                                (PKIX_PL_Object **) &name,
429                                plContext),
430                               PKIX_LISTGETITEMFAILED);
431                    
432                    PKIX_CHECK(pkix_List_Contains
433                               (certExtKeyUsageList,
434                                (PKIX_PL_Object *) name,
435                                &checkPassed,
436                                plContext),
437                               PKIX_LISTCONTAINSFAILED);
438                    
439                    PKIX_DECREF(name);
440                    
441                    if (checkPassed != PKIX_TRUE) {
442                        PKIX_ERROR
443                            (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
444                        
445                    }
446                }
447            }
448        } else {
449            /* Check key usage and cert type based on certificate usage. */
450            PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
451                                                         plContext),
452                       PKIX_CERTVERIFYCERTTYPEFAILED);
453        }
454
455        /* Remove Critical Extension OID from list */
456        if (unresolvedCriticalExtensions != NULL) {
457
458                PKIX_CHECK(pkix_List_Remove
459                            (unresolvedCriticalExtensions,
460                            (PKIX_PL_Object *) state->extKeyUsageOID,
461                            plContext),
462                            PKIX_LISTREMOVEFAILED);
463
464                PKIX_CHECK(PKIX_PL_Cert_GetSubject
465                            (cert, &certSubjectName, plContext),
466                            PKIX_CERTGETSUBJECTFAILED);
467
468                if (certSubjAltNames != NULL) {
469                        PKIX_CHECK(pkix_List_Remove
470                            (unresolvedCriticalExtensions,
471                            (PKIX_PL_Object *) state->subjAltNameOID,
472                            plContext),
473                            PKIX_LISTREMOVEFAILED);
474                }
475
476        }
477
478cleanup:
479
480        PKIX_DECREF(name);
481        PKIX_DECREF(nameConstraints);
482        PKIX_DECREF(certSubjAltNames);
483        PKIX_DECREF(certExtKeyUsageList);
484        PKIX_DECREF(certSubjectName);
485        PKIX_DECREF(state);
486
487        PKIX_RETURN(CERTCHAINCHECKER);
488
489}
490
491/*
492 * FUNCTION: pkix_TargetCertChecker_Initialize
493 * DESCRIPTION:
494 *
495 *  Creates a new CertChainChecker and stores it at "pChecker", where it will
496 *  used by pkix_TargetCertChecker_Check to check that the final certificate
497 *  of a chain meets the criteria of the CertSelector pointed to by
498 *  "certSelector". The number of certs remaining in the chain, represented by
499 *  "certsRemaining" is used to initialize the checker's state.
500 *
501 * PARAMETERS:
502 *  "certSelector"
503 *      Address of CertSelector representing the criteria against which the
504 *      final certificate in a chain is to be matched. May be NULL.
505 *  "certsRemaining"
506 *      Number of certificates remaining in the chain.
507 *  "pChecker"
508 *      Address where object pointer will be stored. Must be non-NULL.
509 *  "plContext"
510 *      Platform-specific context pointer.
511 * THREAD SAFETY:
512 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
513 * RETURNS:
514 *  Returns NULL if the function succeeds.
515 *  Returns a CertChainChecker Error if the function fails in a non-fatal way.
516 *  Returns a Fatal Error if the function fails in an unrecoverable way.
517 */
518PKIX_Error *
519pkix_TargetCertChecker_Initialize(
520        PKIX_CertSelector *certSelector,
521        PKIX_UInt32 certsRemaining,
522        PKIX_CertChainChecker **pChecker,
523        void *plContext)
524{
525        pkix_TargetCertCheckerState *state = NULL;
526
527        PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
528        PKIX_NULLCHECK_ONE(pChecker);
529
530        PKIX_CHECK(pkix_TargetCertCheckerState_Create
531                    (certSelector, certsRemaining, &state, plContext),
532                    PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
533
534        PKIX_CHECK(PKIX_CertChainChecker_Create
535                    (pkix_TargetCertChecker_Check,
536                    PKIX_FALSE,
537                    PKIX_FALSE,
538                    NULL,
539                    (PKIX_PL_Object *)state,
540                    pChecker,
541                    plContext),
542                    PKIX_CERTCHAINCHECKERCREATEFAILED);
543
544cleanup:
545
546        PKIX_DECREF(state);
547
548        PKIX_RETURN(CERTCHAINCHECKER);
549}