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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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_targetcertchecker.c
     6  *
     7  * Functions for target cert validation
     8  *
     9  */
    12 #include "pkix_targetcertchecker.h"
    14 /* --Private-TargetCertCheckerState-Functions------------------------------- */
    16 /*
    17  * FUNCTION: pkix_TargetCertCheckerState_Destroy
    18  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    19  */
    20 static PKIX_Error *
    21 pkix_TargetCertCheckerState_Destroy(
    22         PKIX_PL_Object *object,
    23         void *plContext)
    24 {
    25         pkix_TargetCertCheckerState *state = NULL;
    27         PKIX_ENTER(TARGETCERTCHECKERSTATE,
    28                     "pkix_TargetCertCheckerState_Destroy");
    29         PKIX_NULLCHECK_ONE(object);
    31         /* Check that this object is a target cert checker state */
    32         PKIX_CHECK(pkix_CheckType
    33                     (object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
    34                     PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
    36         state = (pkix_TargetCertCheckerState *)object;
    38         PKIX_DECREF(state->certSelector);
    39         PKIX_DECREF(state->extKeyUsageOID);
    40         PKIX_DECREF(state->subjAltNameOID);
    41         PKIX_DECREF(state->pathToNameList);
    42         PKIX_DECREF(state->extKeyUsageList);
    43         PKIX_DECREF(state->subjAltNameList);
    45 cleanup:
    47         PKIX_RETURN(TARGETCERTCHECKERSTATE);
    48 }
    50 /*
    51  * FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
    52  * DESCRIPTION:
    53  *  Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
    54  *  systemClasses[]
    55  * THREAD SAFETY:
    56  *  Not Thread Safe - for performance and complexity reasons
    57  *
    58  *  Since this function is only called by PKIX_PL_Initialize, which should
    59  *  only be called once, it is acceptable that this function is not
    60  *  thread-safe.
    61  */
    62 PKIX_Error *
    63 pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
    64 {
    65         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    66         pkix_ClassTable_Entry entry;
    68         PKIX_ENTER(TARGETCERTCHECKERSTATE,
    69                     "pkix_TargetCertCheckerState_RegisterSelf");
    71         entry.description = "TargetCertCheckerState";
    72         entry.objCounter = 0;
    73         entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
    74         entry.destructor = pkix_TargetCertCheckerState_Destroy;
    75         entry.equalsFunction = NULL;
    76         entry.hashcodeFunction = NULL;
    77         entry.toStringFunction = NULL;
    78         entry.comparator = NULL;
    79         entry.duplicateFunction = NULL;
    81         systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
    83         PKIX_RETURN(TARGETCERTCHECKERSTATE);
    84 }
    86 /*
    87  * FUNCTION: pkix_TargetCertCheckerState_Create
    88  * DESCRIPTION:
    89  *
    90  *  Creates a new TargetCertCheckerState using the CertSelector pointed to
    91  *  by "certSelector" and the number of certs represented by "certsRemaining"
    92  *  and stores it at "pState".
    93  *
    94  * PARAMETERS:
    95  *  "certSelector"
    96  *      Address of CertSelector representing the criteria against which the
    97  *      final certificate in a chain is to be matched. Must be non-NULL.
    98  *  "certsRemaining"
    99  *      Number of certificates remaining in the chain.
   100  *  "pState"
   101  *      Address where object pointer will be stored. Must be non-NULL.
   102  *  "plContext"
   103  *      Platform-specific context pointer.
   104  * THREAD SAFETY:
   105  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   106  * RETURNS:
   107  *  Returns NULL if the function succeeds.
   108  *  Returns a TargetCertCheckerState Error if the function fails in a
   109  *      non-fatal way.
   110  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   111  */
   112 PKIX_Error *
   113 pkix_TargetCertCheckerState_Create(
   114     PKIX_CertSelector *certSelector,
   115     PKIX_UInt32 certsRemaining,
   116     pkix_TargetCertCheckerState **pState,
   117     void *plContext)
   118 {
   119         pkix_TargetCertCheckerState *state = NULL;
   120         PKIX_ComCertSelParams *certSelectorParams = NULL;
   121         PKIX_List *pathToNameList = NULL;
   122         PKIX_List *extKeyUsageList = NULL;
   123         PKIX_List *subjAltNameList = NULL;
   124         PKIX_PL_OID *extKeyUsageOID = NULL;
   125         PKIX_PL_OID *subjAltNameOID = NULL;
   126         PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
   128         PKIX_ENTER(TARGETCERTCHECKERSTATE,
   129                     "pkix_TargetCertCheckerState_Create");
   130         PKIX_NULLCHECK_ONE(pState);
   132         PKIX_CHECK(PKIX_PL_OID_Create
   133                     (PKIX_EXTENDEDKEYUSAGE_OID,
   134                     &extKeyUsageOID,
   135                     plContext),
   136                     PKIX_OIDCREATEFAILED);
   138         PKIX_CHECK(PKIX_PL_OID_Create
   139                     (PKIX_CERTSUBJALTNAME_OID,
   140                     &subjAltNameOID,
   141                     plContext),
   142                     PKIX_OIDCREATEFAILED);
   144         PKIX_CHECK(PKIX_PL_Object_Alloc
   145                     (PKIX_TARGETCERTCHECKERSTATE_TYPE,
   146                     sizeof (pkix_TargetCertCheckerState),
   147                     (PKIX_PL_Object **)&state,
   148                     plContext),
   149                     PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
   151         /* initialize fields */
   153         if (certSelector != NULL) {
   155                 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
   156                         (certSelector, &certSelectorParams, plContext),
   157                         PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
   159                 if (certSelectorParams != NULL) {
   161                         PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
   162                             (certSelectorParams,
   163                             &pathToNameList,
   164                             plContext),
   165                             PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
   167                         PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
   168                             (certSelectorParams,
   169                             &extKeyUsageList,
   170                             plContext),
   171                             PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
   173                         PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
   174                             (certSelectorParams,
   175                             &subjAltNameList,
   176                             plContext),
   177                             PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
   179                         PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
   180                             (certSelectorParams,
   181                             &subjAltNameMatchAll,
   182                             plContext),
   183                             PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
   184                 }
   185         }
   187         state->certsRemaining = certsRemaining;
   188         state->subjAltNameMatchAll = subjAltNameMatchAll;
   190         PKIX_INCREF(certSelector);
   191         state->certSelector = certSelector;
   193         state->pathToNameList = pathToNameList;
   194         pathToNameList = NULL;
   196         state->extKeyUsageList = extKeyUsageList;
   197         extKeyUsageList = NULL;
   199         state->subjAltNameList = subjAltNameList;
   200         subjAltNameList = NULL;
   202         state->extKeyUsageOID = extKeyUsageOID;
   203         extKeyUsageOID = NULL;
   205         state->subjAltNameOID = subjAltNameOID;
   206         subjAltNameOID = NULL;
   208         *pState = state;
   209         state = NULL;
   211 cleanup:
   213         PKIX_DECREF(extKeyUsageOID);
   214         PKIX_DECREF(subjAltNameOID);
   215         PKIX_DECREF(pathToNameList);
   216         PKIX_DECREF(extKeyUsageList);
   217         PKIX_DECREF(subjAltNameList);
   218         PKIX_DECREF(state);
   220         PKIX_DECREF(certSelectorParams);
   222         PKIX_RETURN(TARGETCERTCHECKERSTATE);
   224 }
   226 /* --Private-TargetCertChecker-Functions------------------------------- */
   228 /*
   229  * FUNCTION: pkix_TargetCertChecker_Check
   230  * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
   231  */
   232 PKIX_Error *
   233 pkix_TargetCertChecker_Check(
   234         PKIX_CertChainChecker *checker,
   235         PKIX_PL_Cert *cert,
   236         PKIX_List *unresolvedCriticalExtensions,
   237         void **pNBIOContext,
   238         void *plContext)
   239 {
   240         pkix_TargetCertCheckerState *state = NULL;
   241         PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
   242         PKIX_PL_CertNameConstraints *nameConstraints = NULL;
   243         PKIX_List *certSubjAltNames = NULL;
   244         PKIX_List *certExtKeyUsageList = NULL;
   245         PKIX_PL_GeneralName *name = NULL;
   246         PKIX_PL_X500Name *certSubjectName = NULL;
   247         PKIX_Boolean checkPassed = PKIX_FALSE;
   248         PKIX_UInt32 numItems, i;
   249         PKIX_UInt32 matchCount = 0;
   251         PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
   252         PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
   254         *pNBIOContext = NULL; /* we never block on pending I/O */
   256         PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
   257                     (checker, (PKIX_PL_Object **)&state, plContext),
   258                     PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
   260         (state->certsRemaining)--;
   262         if (state->pathToNameList != NULL) {
   264                 PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
   265                     (cert, &nameConstraints, plContext),
   266                     PKIX_CERTGETNAMECONSTRAINTSFAILED);
   268                 /*
   269                  * XXX We should either make the following call a public one
   270                  * so it is legal to call from the portability layer or we
   271                  * should try to create pathToNameList as CertNameConstraints
   272                  * then call the existing check function.
   273                  */
   274                 PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
   275                     (state->pathToNameList,
   276                     nameConstraints,
   277                     &checkPassed,
   278                     plContext),
   279                     PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
   281                 if (checkPassed != PKIX_TRUE) {
   282                     PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
   283                 }
   285         }
   287         PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
   288                     (cert, &certSubjAltNames, plContext),
   289                     PKIX_CERTGETSUBJALTNAMESFAILED);
   291         if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
   293                 PKIX_CHECK(PKIX_List_GetLength
   294                         (state->subjAltNameList, &numItems, plContext),
   295                         PKIX_LISTGETLENGTHFAILED);
   297                 for (i = 0; i < numItems; i++) {
   299                         PKIX_CHECK(PKIX_List_GetItem
   300                             (state->subjAltNameList,
   301                             i,
   302                             (PKIX_PL_Object **) &name,
   303                             plContext),
   304                             PKIX_LISTGETITEMFAILED);
   306                         PKIX_CHECK(pkix_List_Contains
   307                             (certSubjAltNames,
   308                             (PKIX_PL_Object *) name,
   309                             &checkPassed,
   310                             plContext),
   311                             PKIX_LISTCONTAINSFAILED);
   313                         PKIX_DECREF(name);
   315                         if (checkPassed == PKIX_TRUE) {
   317                             if (state->subjAltNameMatchAll == PKIX_FALSE) {
   318                                 matchCount = numItems;
   319                                 break;
   320                             } else {
   321                                 /* else continue checking next */
   322                                 matchCount++;
   323                             }
   325                         }
   326                 }
   328                 if (matchCount != numItems) {
   329                         PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
   331                 }
   332         }
   334         if (state->certsRemaining == 0) {
   336             if (state->certSelector != NULL) {
   337                 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
   338                            (state->certSelector,
   339                             &certSelectorMatch,
   340                             plContext),
   341                            PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
   343                 PKIX_CHECK(certSelectorMatch
   344                            (state->certSelector,
   345                             cert,
   346                             plContext),
   347                            PKIX_CERTSELECTORMATCHFAILED);
   348             } else {
   349                 /* Check at least cert/key usages if target cert selector
   350                  * is not set. */
   351                 PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
   352                                          PKIX_FALSE  /* is chain cert*/,
   353                                          plContext),
   354                            PKIX_CERTVERIFYCERTTYPEFAILED);
   355             }
   356             /*
   357              * There are two Extended Key Usage Checkings
   358              * available :
   359              * 1) here at the targetcertchecker where we
   360              *    verify the Extended Key Usage OIDs application
   361              *    specifies via ComCertSelParams are included
   362              *    in Cert's Extended Key Usage OID's. Note,
   363              *    this is an OID to OID comparison and only last
   364              *    Cert is checked.
   365              * 2) at user defined ekuchecker where checking
   366              *    is applied to all Certs on the chain and
   367              *    the NSS Extended Key Usage algorithm is
   368              *    used. In order to invoke this checking, not
   369              *    only does the ComCertSelparams needs to be
   370              *    set, the EKU initialize call is required to
   371              *    activate the checking.
   372              *
   373              * XXX We use the same ComCertSelParams Set/Get
   374              * functions to set the parameters for both cases.
   375              * We may want to separate them in the future.
   376              */
   378             PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
   379                        (cert, &certExtKeyUsageList, plContext),
   380                        PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
   383             if (state->extKeyUsageList != NULL &&
   384                 certExtKeyUsageList != NULL) {
   386                 PKIX_CHECK(PKIX_List_GetLength
   387                            (state->extKeyUsageList, &numItems, plContext),
   388                            PKIX_LISTGETLENGTHFAILED);
   390                 for (i = 0; i < numItems; i++) {
   392                     PKIX_CHECK(PKIX_List_GetItem
   393                                (state->extKeyUsageList,
   394                                 i,
   395                                 (PKIX_PL_Object **) &name,
   396                                 plContext),
   397                                PKIX_LISTGETITEMFAILED);
   399                     PKIX_CHECK(pkix_List_Contains
   400                                (certExtKeyUsageList,
   401                                 (PKIX_PL_Object *) name,
   402                                 &checkPassed,
   403                                 plContext),
   404                                PKIX_LISTCONTAINSFAILED);
   406                     PKIX_DECREF(name);
   408                     if (checkPassed != PKIX_TRUE) {
   409                         PKIX_ERROR
   410                             (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
   412                     }
   413                 }
   414             }
   415         } else {
   416             /* Check key usage and cert type based on certificate usage. */
   417             PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
   418                                                          plContext),
   419                        PKIX_CERTVERIFYCERTTYPEFAILED);
   420         }
   422         /* Remove Critical Extension OID from list */
   423         if (unresolvedCriticalExtensions != NULL) {
   425                 PKIX_CHECK(pkix_List_Remove
   426                             (unresolvedCriticalExtensions,
   427                             (PKIX_PL_Object *) state->extKeyUsageOID,
   428                             plContext),
   429                             PKIX_LISTREMOVEFAILED);
   431                 PKIX_CHECK(PKIX_PL_Cert_GetSubject
   432                             (cert, &certSubjectName, plContext),
   433                             PKIX_CERTGETSUBJECTFAILED);
   435                 if (certSubjAltNames != NULL) {
   436                         PKIX_CHECK(pkix_List_Remove
   437                             (unresolvedCriticalExtensions,
   438                             (PKIX_PL_Object *) state->subjAltNameOID,
   439                             plContext),
   440                             PKIX_LISTREMOVEFAILED);
   441                 }
   443         }
   445 cleanup:
   447         PKIX_DECREF(name);
   448         PKIX_DECREF(nameConstraints);
   449         PKIX_DECREF(certSubjAltNames);
   450         PKIX_DECREF(certExtKeyUsageList);
   451         PKIX_DECREF(certSubjectName);
   452         PKIX_DECREF(state);
   454         PKIX_RETURN(CERTCHAINCHECKER);
   456 }
   458 /*
   459  * FUNCTION: pkix_TargetCertChecker_Initialize
   460  * DESCRIPTION:
   461  *
   462  *  Creates a new CertChainChecker and stores it at "pChecker", where it will
   463  *  used by pkix_TargetCertChecker_Check to check that the final certificate
   464  *  of a chain meets the criteria of the CertSelector pointed to by
   465  *  "certSelector". The number of certs remaining in the chain, represented by
   466  *  "certsRemaining" is used to initialize the checker's state.
   467  *
   468  * PARAMETERS:
   469  *  "certSelector"
   470  *      Address of CertSelector representing the criteria against which the
   471  *      final certificate in a chain is to be matched. May be NULL.
   472  *  "certsRemaining"
   473  *      Number of certificates remaining in the chain.
   474  *  "pChecker"
   475  *      Address where object pointer will be stored. Must be non-NULL.
   476  *  "plContext"
   477  *      Platform-specific context pointer.
   478  * THREAD SAFETY:
   479  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   480  * RETURNS:
   481  *  Returns NULL if the function succeeds.
   482  *  Returns a CertChainChecker Error if the function fails in a non-fatal way.
   483  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   484  */
   485 PKIX_Error *
   486 pkix_TargetCertChecker_Initialize(
   487         PKIX_CertSelector *certSelector,
   488         PKIX_UInt32 certsRemaining,
   489         PKIX_CertChainChecker **pChecker,
   490         void *plContext)
   491 {
   492         pkix_TargetCertCheckerState *state = NULL;
   494         PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
   495         PKIX_NULLCHECK_ONE(pChecker);
   497         PKIX_CHECK(pkix_TargetCertCheckerState_Create
   498                     (certSelector, certsRemaining, &state, plContext),
   499                     PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
   501         PKIX_CHECK(PKIX_CertChainChecker_Create
   502                     (pkix_TargetCertChecker_Check,
   503                     PKIX_FALSE,
   504                     PKIX_FALSE,
   505                     NULL,
   506                     (PKIX_PL_Object *)state,
   507                     pChecker,
   508                     plContext),
   509                     PKIX_CERTCHAINCHECKERCREATEFAILED);
   511 cleanup:
   513         PKIX_DECREF(state);
   515         PKIX_RETURN(CERTCHAINCHECKER);
   516 }

mercurial