diff nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,516 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_targetcertchecker.c
+ *
+ * Functions for target cert validation
+ *
+ */
+
+
+#include "pkix_targetcertchecker.h"
+
+/* --Private-TargetCertCheckerState-Functions------------------------------- */
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TargetCertCheckerState_Destroy(
+        PKIX_PL_Object *object,
+        void *plContext)
+{
+        pkix_TargetCertCheckerState *state = NULL;
+
+        PKIX_ENTER(TARGETCERTCHECKERSTATE,
+                    "pkix_TargetCertCheckerState_Destroy");
+        PKIX_NULLCHECK_ONE(object);
+
+        /* Check that this object is a target cert checker state */
+        PKIX_CHECK(pkix_CheckType
+                    (object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
+                    PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
+
+        state = (pkix_TargetCertCheckerState *)object;
+
+        PKIX_DECREF(state->certSelector);
+        PKIX_DECREF(state->extKeyUsageOID);
+        PKIX_DECREF(state->subjAltNameOID);
+        PKIX_DECREF(state->pathToNameList);
+        PKIX_DECREF(state->extKeyUsageList);
+        PKIX_DECREF(state->subjAltNameList);
+
+cleanup:
+
+        PKIX_RETURN(TARGETCERTCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
+ * DESCRIPTION:
+ *  Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
+ *  systemClasses[]
+ * THREAD SAFETY:
+ *  Not Thread Safe - for performance and complexity reasons
+ *
+ *  Since this function is only called by PKIX_PL_Initialize, which should
+ *  only be called once, it is acceptable that this function is not
+ *  thread-safe.
+ */
+PKIX_Error *
+pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
+{
+        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+        pkix_ClassTable_Entry entry;
+
+        PKIX_ENTER(TARGETCERTCHECKERSTATE,
+                    "pkix_TargetCertCheckerState_RegisterSelf");
+
+        entry.description = "TargetCertCheckerState";
+        entry.objCounter = 0;
+        entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
+        entry.destructor = pkix_TargetCertCheckerState_Destroy;
+        entry.equalsFunction = NULL;
+        entry.hashcodeFunction = NULL;
+        entry.toStringFunction = NULL;
+        entry.comparator = NULL;
+        entry.duplicateFunction = NULL;
+
+        systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
+
+        PKIX_RETURN(TARGETCERTCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_Create
+ * DESCRIPTION:
+ *
+ *  Creates a new TargetCertCheckerState using the CertSelector pointed to
+ *  by "certSelector" and the number of certs represented by "certsRemaining"
+ *  and stores it at "pState".
+ *
+ * PARAMETERS:
+ *  "certSelector"
+ *      Address of CertSelector representing the criteria against which the
+ *      final certificate in a chain is to be matched. Must be non-NULL.
+ *  "certsRemaining"
+ *      Number of certificates remaining in the chain.
+ *  "pState"
+ *      Address where object pointer will be stored. Must be non-NULL.
+ *  "plContext"
+ *      Platform-specific context pointer.
+ * THREAD SAFETY:
+ *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ *  Returns NULL if the function succeeds.
+ *  Returns a TargetCertCheckerState Error if the function fails in a
+ *      non-fatal way.
+ *  Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_TargetCertCheckerState_Create(
+    PKIX_CertSelector *certSelector,
+    PKIX_UInt32 certsRemaining,
+    pkix_TargetCertCheckerState **pState,
+    void *plContext)
+{
+        pkix_TargetCertCheckerState *state = NULL;
+        PKIX_ComCertSelParams *certSelectorParams = NULL;
+        PKIX_List *pathToNameList = NULL;
+        PKIX_List *extKeyUsageList = NULL;
+        PKIX_List *subjAltNameList = NULL;
+        PKIX_PL_OID *extKeyUsageOID = NULL;
+        PKIX_PL_OID *subjAltNameOID = NULL;
+        PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
+
+        PKIX_ENTER(TARGETCERTCHECKERSTATE,
+                    "pkix_TargetCertCheckerState_Create");
+        PKIX_NULLCHECK_ONE(pState);
+
+        PKIX_CHECK(PKIX_PL_OID_Create
+                    (PKIX_EXTENDEDKEYUSAGE_OID,
+                    &extKeyUsageOID,
+                    plContext),
+                    PKIX_OIDCREATEFAILED);
+
+        PKIX_CHECK(PKIX_PL_OID_Create
+                    (PKIX_CERTSUBJALTNAME_OID,
+                    &subjAltNameOID,
+                    plContext),
+                    PKIX_OIDCREATEFAILED);
+
+        PKIX_CHECK(PKIX_PL_Object_Alloc
+                    (PKIX_TARGETCERTCHECKERSTATE_TYPE,
+                    sizeof (pkix_TargetCertCheckerState),
+                    (PKIX_PL_Object **)&state,
+                    plContext),
+                    PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
+
+        /* initialize fields */
+
+        if (certSelector != NULL) {
+
+                PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+                        (certSelector, &certSelectorParams, plContext),
+                        PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
+
+                if (certSelectorParams != NULL) {
+
+                        PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
+                            (certSelectorParams,
+                            &pathToNameList,
+                            plContext),
+                            PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
+
+                        PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+                            (certSelectorParams,
+                            &extKeyUsageList,
+                            plContext),
+                            PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+                        PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
+                            (certSelectorParams,
+                            &subjAltNameList,
+                            plContext),
+                            PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+
+                        PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+                            (certSelectorParams,
+                            &subjAltNameMatchAll,
+                            plContext),
+                            PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+                }
+        }
+
+        state->certsRemaining = certsRemaining;
+        state->subjAltNameMatchAll = subjAltNameMatchAll;
+
+        PKIX_INCREF(certSelector);
+        state->certSelector = certSelector;
+
+        state->pathToNameList = pathToNameList;
+        pathToNameList = NULL;
+
+        state->extKeyUsageList = extKeyUsageList;
+        extKeyUsageList = NULL;
+
+        state->subjAltNameList = subjAltNameList;
+        subjAltNameList = NULL;
+
+        state->extKeyUsageOID = extKeyUsageOID;
+        extKeyUsageOID = NULL;
+
+        state->subjAltNameOID = subjAltNameOID;
+        subjAltNameOID = NULL;
+
+        *pState = state;
+        state = NULL;
+
+cleanup:
+        
+        PKIX_DECREF(extKeyUsageOID);
+        PKIX_DECREF(subjAltNameOID);
+        PKIX_DECREF(pathToNameList);
+        PKIX_DECREF(extKeyUsageList);
+        PKIX_DECREF(subjAltNameList);
+        PKIX_DECREF(state);
+
+        PKIX_DECREF(certSelectorParams);
+
+        PKIX_RETURN(TARGETCERTCHECKERSTATE);
+
+}
+
+/* --Private-TargetCertChecker-Functions------------------------------- */
+
+/*
+ * FUNCTION: pkix_TargetCertChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_TargetCertChecker_Check(
+        PKIX_CertChainChecker *checker,
+        PKIX_PL_Cert *cert,
+        PKIX_List *unresolvedCriticalExtensions,
+        void **pNBIOContext,
+        void *plContext)
+{
+        pkix_TargetCertCheckerState *state = NULL;
+        PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
+        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+        PKIX_List *certSubjAltNames = NULL;
+        PKIX_List *certExtKeyUsageList = NULL;
+        PKIX_PL_GeneralName *name = NULL;
+        PKIX_PL_X500Name *certSubjectName = NULL;
+        PKIX_Boolean checkPassed = PKIX_FALSE;
+        PKIX_UInt32 numItems, i;
+        PKIX_UInt32 matchCount = 0;
+
+        PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
+        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+        *pNBIOContext = NULL; /* we never block on pending I/O */
+
+        PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+                    (checker, (PKIX_PL_Object **)&state, plContext),
+                    PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+        (state->certsRemaining)--;
+
+        if (state->pathToNameList != NULL) {
+
+                PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+                    (cert, &nameConstraints, plContext),
+                    PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+                /*
+                 * XXX We should either make the following call a public one
+                 * so it is legal to call from the portability layer or we
+                 * should try to create pathToNameList as CertNameConstraints
+                 * then call the existing check function.
+                 */
+                PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+                    (state->pathToNameList,
+                    nameConstraints,
+                    &checkPassed,
+                    plContext),
+                    PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
+
+                if (checkPassed != PKIX_TRUE) {
+                    PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
+                }
+
+        }
+
+        PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+                    (cert, &certSubjAltNames, plContext),
+                    PKIX_CERTGETSUBJALTNAMESFAILED);
+
+        if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
+
+                PKIX_CHECK(PKIX_List_GetLength
+                        (state->subjAltNameList, &numItems, plContext),
+                        PKIX_LISTGETLENGTHFAILED);
+
+                for (i = 0; i < numItems; i++) {
+
+                        PKIX_CHECK(PKIX_List_GetItem
+                            (state->subjAltNameList,
+                            i,
+                            (PKIX_PL_Object **) &name,
+                            plContext),
+                            PKIX_LISTGETITEMFAILED);
+
+                        PKIX_CHECK(pkix_List_Contains
+                            (certSubjAltNames,
+                            (PKIX_PL_Object *) name,
+                            &checkPassed,
+                            plContext),
+                            PKIX_LISTCONTAINSFAILED);
+
+                        PKIX_DECREF(name);
+
+                        if (checkPassed == PKIX_TRUE) {
+
+                            if (state->subjAltNameMatchAll == PKIX_FALSE) {
+                                matchCount = numItems;
+                                break;
+                            } else {
+                                /* else continue checking next */
+                                matchCount++;
+                            }
+
+                        }
+                }
+
+                if (matchCount != numItems) {
+                        PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
+
+                }
+        }
+
+        if (state->certsRemaining == 0) {
+
+            if (state->certSelector != NULL) {
+                PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+                           (state->certSelector,
+                            &certSelectorMatch,
+                            plContext),
+                           PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+                PKIX_CHECK(certSelectorMatch
+                           (state->certSelector,
+                            cert,
+                            plContext),
+                           PKIX_CERTSELECTORMATCHFAILED);
+            } else {
+                /* Check at least cert/key usages if target cert selector
+                 * is not set. */
+                PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
+                                         PKIX_FALSE  /* is chain cert*/,
+                                         plContext),
+                           PKIX_CERTVERIFYCERTTYPEFAILED);
+            }
+            /*
+             * There are two Extended Key Usage Checkings
+             * available :
+             * 1) here at the targetcertchecker where we
+             *    verify the Extended Key Usage OIDs application
+             *    specifies via ComCertSelParams are included
+             *    in Cert's Extended Key Usage OID's. Note,
+             *    this is an OID to OID comparison and only last
+             *    Cert is checked.
+             * 2) at user defined ekuchecker where checking
+             *    is applied to all Certs on the chain and
+             *    the NSS Extended Key Usage algorithm is
+             *    used. In order to invoke this checking, not
+             *    only does the ComCertSelparams needs to be
+             *    set, the EKU initialize call is required to
+             *    activate the checking.
+             *
+             * XXX We use the same ComCertSelParams Set/Get
+             * functions to set the parameters for both cases.
+             * We may want to separate them in the future.
+             */
+            
+            PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+                       (cert, &certExtKeyUsageList, plContext),
+                       PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+            
+            
+            if (state->extKeyUsageList != NULL &&
+                certExtKeyUsageList != NULL) {
+                
+                PKIX_CHECK(PKIX_List_GetLength
+                           (state->extKeyUsageList, &numItems, plContext),
+                           PKIX_LISTGETLENGTHFAILED);
+                
+                for (i = 0; i < numItems; i++) {
+                    
+                    PKIX_CHECK(PKIX_List_GetItem
+                               (state->extKeyUsageList,
+                                i,
+                                (PKIX_PL_Object **) &name,
+                                plContext),
+                               PKIX_LISTGETITEMFAILED);
+                    
+                    PKIX_CHECK(pkix_List_Contains
+                               (certExtKeyUsageList,
+                                (PKIX_PL_Object *) name,
+                                &checkPassed,
+                                plContext),
+                               PKIX_LISTCONTAINSFAILED);
+                    
+                    PKIX_DECREF(name);
+                    
+                    if (checkPassed != PKIX_TRUE) {
+                        PKIX_ERROR
+                            (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
+                        
+                    }
+                }
+            }
+        } else {
+            /* Check key usage and cert type based on certificate usage. */
+            PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
+                                                         plContext),
+                       PKIX_CERTVERIFYCERTTYPEFAILED);
+        }
+
+        /* Remove Critical Extension OID from list */
+        if (unresolvedCriticalExtensions != NULL) {
+
+                PKIX_CHECK(pkix_List_Remove
+                            (unresolvedCriticalExtensions,
+                            (PKIX_PL_Object *) state->extKeyUsageOID,
+                            plContext),
+                            PKIX_LISTREMOVEFAILED);
+
+                PKIX_CHECK(PKIX_PL_Cert_GetSubject
+                            (cert, &certSubjectName, plContext),
+                            PKIX_CERTGETSUBJECTFAILED);
+
+                if (certSubjAltNames != NULL) {
+                        PKIX_CHECK(pkix_List_Remove
+                            (unresolvedCriticalExtensions,
+                            (PKIX_PL_Object *) state->subjAltNameOID,
+                            plContext),
+                            PKIX_LISTREMOVEFAILED);
+                }
+
+        }
+
+cleanup:
+
+        PKIX_DECREF(name);
+        PKIX_DECREF(nameConstraints);
+        PKIX_DECREF(certSubjAltNames);
+        PKIX_DECREF(certExtKeyUsageList);
+        PKIX_DECREF(certSubjectName);
+        PKIX_DECREF(state);
+
+        PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_TargetCertChecker_Initialize
+ * DESCRIPTION:
+ *
+ *  Creates a new CertChainChecker and stores it at "pChecker", where it will
+ *  used by pkix_TargetCertChecker_Check to check that the final certificate
+ *  of a chain meets the criteria of the CertSelector pointed to by
+ *  "certSelector". The number of certs remaining in the chain, represented by
+ *  "certsRemaining" is used to initialize the checker's state.
+ *
+ * PARAMETERS:
+ *  "certSelector"
+ *      Address of CertSelector representing the criteria against which the
+ *      final certificate in a chain is to be matched. May be NULL.
+ *  "certsRemaining"
+ *      Number of certificates remaining in the chain.
+ *  "pChecker"
+ *      Address where object pointer will be stored. Must be non-NULL.
+ *  "plContext"
+ *      Platform-specific context pointer.
+ * THREAD SAFETY:
+ *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ *  Returns NULL if the function succeeds.
+ *  Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ *  Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_TargetCertChecker_Initialize(
+        PKIX_CertSelector *certSelector,
+        PKIX_UInt32 certsRemaining,
+        PKIX_CertChainChecker **pChecker,
+        void *plContext)
+{
+        pkix_TargetCertCheckerState *state = NULL;
+
+        PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
+        PKIX_NULLCHECK_ONE(pChecker);
+
+        PKIX_CHECK(pkix_TargetCertCheckerState_Create
+                    (certSelector, certsRemaining, &state, plContext),
+                    PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
+
+        PKIX_CHECK(PKIX_CertChainChecker_Create
+                    (pkix_TargetCertChecker_Check,
+                    PKIX_FALSE,
+                    PKIX_FALSE,
+                    NULL,
+                    (PKIX_PL_Object *)state,
+                    pChecker,
+                    plContext),
+                    PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+        PKIX_DECREF(state);
+
+        PKIX_RETURN(CERTCHAINCHECKER);
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)