diff nss/lib/libpkix/pkix/checker/pkix_revocationchecker.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_revocationchecker.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,467 @@
+/* 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_revocationchecker.c
+ *
+ * RevocationChecker Object Functions
+ *
+ */
+
+#include "pkix_revocationchecker.h"
+#include "pkix_tools.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_RevocationChecker_Destroy
+ *      (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_RevocationChecker_Destroy(
+        PKIX_PL_Object *object,
+        void *plContext)
+{
+        PKIX_RevocationChecker *checker = NULL;
+
+        PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Destroy");
+        PKIX_NULLCHECK_ONE(object);
+
+        /* Check that this object is a revocation checker */
+        PKIX_CHECK(pkix_CheckType
+                    (object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
+                    PKIX_OBJECTNOTREVOCATIONCHECKER);
+
+        checker = (PKIX_RevocationChecker *)object;
+
+        PKIX_DECREF(checker->leafMethodList);
+        PKIX_DECREF(checker->chainMethodList);
+        
+cleanup:
+
+        PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_RevocationChecker_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_RevocationChecker_Duplicate(
+        PKIX_PL_Object *object,
+        PKIX_PL_Object **pNewObject,
+        void *plContext)
+{
+        PKIX_RevocationChecker *checker = NULL;
+        PKIX_RevocationChecker *checkerDuplicate = NULL;
+        PKIX_List *dupLeafList = NULL;
+        PKIX_List *dupChainList = NULL;
+
+        PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Duplicate");
+        PKIX_NULLCHECK_TWO(object, pNewObject);
+
+        PKIX_CHECK(pkix_CheckType
+                    (object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
+                    PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+        checker = (PKIX_RevocationChecker *)object;
+
+        if (checker->leafMethodList){
+                PKIX_CHECK(PKIX_PL_Object_Duplicate
+                            ((PKIX_PL_Object *)checker->leafMethodList,
+                            (PKIX_PL_Object **)&dupLeafList,
+                            plContext),
+                            PKIX_OBJECTDUPLICATEFAILED);
+        }
+        if (checker->chainMethodList){
+                PKIX_CHECK(PKIX_PL_Object_Duplicate
+                            ((PKIX_PL_Object *)checker->chainMethodList,
+                            (PKIX_PL_Object **)&dupChainList,
+                            plContext),
+                            PKIX_OBJECTDUPLICATEFAILED);
+        }
+
+        PKIX_CHECK(
+            PKIX_RevocationChecker_Create(checker->leafMethodListFlags,
+                                          checker->chainMethodListFlags,
+                                          &checkerDuplicate,
+                                          plContext),
+            PKIX_REVOCATIONCHECKERCREATEFAILED);
+
+        checkerDuplicate->leafMethodList = dupLeafList;
+        checkerDuplicate->chainMethodList = dupChainList;
+        dupLeafList = NULL;
+        dupChainList = NULL;
+
+        *pNewObject = (PKIX_PL_Object *)checkerDuplicate;
+
+cleanup:
+        PKIX_DECREF(dupLeafList);
+        PKIX_DECREF(dupChainList);
+
+        PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_RevocationChecker_RegisterSelf
+ * DESCRIPTION:
+ *  Registers PKIX_REVOCATIONCHECKER_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_RevocationChecker_RegisterSelf(void *plContext)
+{
+        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+        pkix_ClassTable_Entry entry;
+
+        PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_RegisterSelf");
+
+        entry.description = "RevocationChecker";
+        entry.objCounter = 0;
+        entry.typeObjectSize = sizeof(PKIX_RevocationChecker);
+        entry.destructor = pkix_RevocationChecker_Destroy;
+        entry.equalsFunction = NULL;
+        entry.hashcodeFunction = NULL;
+        entry.toStringFunction = NULL;
+        entry.comparator = NULL;
+        entry.duplicateFunction = pkix_RevocationChecker_Duplicate;
+
+        systemClasses[PKIX_REVOCATIONCHECKER_TYPE] = entry;
+
+        PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/* Sort methods by theirs priorities */
+static PKIX_Error *
+pkix_RevocationChecker_SortComparator(
+        PKIX_PL_Object *obj1,
+        PKIX_PL_Object *obj2,
+        PKIX_Int32 *pResult,
+        void *plContext)
+{
+    pkix_RevocationMethod *method1 = NULL, *method2 = NULL;
+    
+    PKIX_ENTER(BUILD, "pkix_RevocationChecker_SortComparator");
+    
+    method1 = (pkix_RevocationMethod *)obj1;
+    method2 = (pkix_RevocationMethod *)obj2;
+    
+    *pResult = (method1->priority > method2->priority);
+    
+    PKIX_RETURN(BUILD);
+}
+
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Create (see comments in pkix_revchecker.h)
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Create(
+    PKIX_UInt32 leafMethodListFlags,
+    PKIX_UInt32 chainMethodListFlags,
+    PKIX_RevocationChecker **pChecker,
+    void *plContext)
+{
+    PKIX_RevocationChecker *checker = NULL;
+    
+    PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Create");
+    PKIX_NULLCHECK_ONE(pChecker);
+    
+    PKIX_CHECK(
+        PKIX_PL_Object_Alloc(PKIX_REVOCATIONCHECKER_TYPE,
+                             sizeof (PKIX_RevocationChecker),
+                             (PKIX_PL_Object **)&checker,
+                             plContext),
+        PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+    
+    checker->leafMethodListFlags = leafMethodListFlags;
+    checker->chainMethodListFlags = chainMethodListFlags;
+    checker->leafMethodList = NULL;
+    checker->chainMethodList = NULL;
+    
+    *pChecker = checker;
+    checker = NULL;
+    
+cleanup:
+    PKIX_DECREF(checker);
+    
+    PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod
+ */
+PKIX_Error *
+PKIX_RevocationChecker_CreateAndAddMethod(
+    PKIX_RevocationChecker *revChecker,
+    PKIX_ProcessingParams *params,
+    PKIX_RevocationMethodType methodType,
+    PKIX_UInt32 flags,
+    PKIX_UInt32 priority,
+    PKIX_PL_VerifyCallback verificationFn,
+    PKIX_Boolean isLeafMethod,
+    void *plContext)
+{
+    PKIX_List **methodList = NULL;
+    PKIX_List  *unsortedList = NULL;
+    PKIX_List  *certStores = NULL;
+    pkix_RevocationMethod *method = NULL;
+    pkix_LocalRevocationCheckFn *localRevChecker = NULL;
+    pkix_ExternalRevocationCheckFn *externRevChecker = NULL;
+    PKIX_UInt32 miFlags;
+    
+    PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod");
+    PKIX_NULLCHECK_ONE(revChecker);
+
+    /* If the caller has said "Either one is sufficient, then don't let the 
+     * absence of any one method's info lead to an overall failure.
+     */
+    miFlags = isLeafMethod ? revChecker->leafMethodListFlags 
+	                   : revChecker->chainMethodListFlags;
+    if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE)
+	flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
+
+    switch (methodType) {
+    case PKIX_RevocationMethod_CRL:
+        localRevChecker = pkix_CrlChecker_CheckLocal;
+        externRevChecker = pkix_CrlChecker_CheckExternal;
+        PKIX_CHECK(
+            PKIX_ProcessingParams_GetCertStores(params, &certStores,
+                                                plContext),
+            PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+        PKIX_CHECK(
+            pkix_CrlChecker_Create(methodType, flags, priority,
+                                   localRevChecker, externRevChecker,
+                                   certStores, verificationFn,
+                                   &method,
+                                   plContext),
+            PKIX_COULDNOTCREATECRLCHECKEROBJECT);
+        break;
+    case PKIX_RevocationMethod_OCSP:
+        localRevChecker = pkix_OcspChecker_CheckLocal;
+        externRevChecker = pkix_OcspChecker_CheckExternal;
+        PKIX_CHECK(
+            pkix_OcspChecker_Create(methodType, flags, priority,
+                                    localRevChecker, externRevChecker,
+                                    verificationFn,
+                                    &method,
+                                    plContext),
+            PKIX_COULDNOTCREATEOCSPCHECKEROBJECT);
+        break;
+    default:
+        PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD);
+    }
+
+    if (isLeafMethod) {
+        methodList = &revChecker->leafMethodList;
+    } else {
+        methodList = &revChecker->chainMethodList;
+    }
+    
+    if (*methodList == NULL) {
+        PKIX_CHECK(
+            PKIX_List_Create(methodList, plContext),
+            PKIX_LISTCREATEFAILED);
+    }
+    unsortedList = *methodList;
+    PKIX_CHECK(
+        PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext),
+        PKIX_LISTAPPENDITEMFAILED);
+    PKIX_CHECK(
+        pkix_List_BubbleSort(unsortedList, 
+                             pkix_RevocationChecker_SortComparator,
+                             methodList, plContext),
+        PKIX_LISTBUBBLESORTFAILED);
+
+cleanup:
+    PKIX_DECREF(method);
+    PKIX_DECREF(unsortedList);
+    PKIX_DECREF(certStores);
+    
+    PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Check
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Check(
+    PKIX_PL_Cert *cert,
+    PKIX_PL_Cert *issuer,
+    PKIX_RevocationChecker *revChecker,
+    PKIX_ProcessingParams *procParams,
+    PKIX_Boolean chainVerificationState,
+    PKIX_Boolean testingLeafCert,
+    PKIX_RevocationStatus *pRevStatus,
+    PKIX_UInt32 *pReasonCode,
+    void **pNbioContext,
+    void *plContext)
+{
+    PKIX_RevocationStatus overallStatus = PKIX_RevStatus_NoInfo;
+    PKIX_RevocationStatus methodStatus[PKIX_RevocationMethod_MAX];
+    PKIX_Boolean onlyUseRemoteMethods = PKIX_FALSE;
+    PKIX_UInt32 revFlags = 0;
+    PKIX_List *revList = NULL;
+    PKIX_PL_Date *date = NULL;
+    pkix_RevocationMethod *method = NULL;
+    void *nbioContext;
+    int tries;
+    
+    PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Check");
+    PKIX_NULLCHECK_TWO(revChecker, procParams);
+
+    nbioContext = *pNbioContext;
+    *pNbioContext = NULL;
+    
+    if (testingLeafCert) {
+        revList = revChecker->leafMethodList;
+        revFlags = revChecker->leafMethodListFlags;        
+    } else {
+        revList = revChecker->chainMethodList;
+        revFlags = revChecker->chainMethodListFlags;
+    }
+    if (!revList) {
+        /* Return NoInfo status */
+        goto cleanup;
+    }
+
+    PORT_Memset(methodStatus, PKIX_RevStatus_NoInfo,
+                sizeof(PKIX_RevocationStatus) * PKIX_RevocationMethod_MAX);
+
+    date = procParams->date;
+
+    /* Need to have two loops if we testing all local info first:
+     *    first we are going to test all local(cached) info
+     *    second, all remote info(fetching) */
+    for (tries = 0;tries < 2;tries++) {
+        int methodNum = 0;
+        for (;methodNum < revList->length;methodNum++) {
+            PKIX_UInt32 methodFlags = 0;
+
+            PKIX_DECREF(method);
+            PKIX_CHECK(
+                PKIX_List_GetItem(revList, methodNum,
+                                  (PKIX_PL_Object**)&method, plContext),
+                PKIX_LISTGETITEMFAILED);
+            methodFlags = method->flags;
+            if (!(methodFlags & PKIX_REV_M_TEST_USING_THIS_METHOD)) {
+                /* Will not check with this method. Skipping... */
+                continue;
+            }
+            if (!onlyUseRemoteMethods &&
+                methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
+                PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+                PKIX_CHECK_NO_GOTO(
+                    (*method->localRevChecker)(cert, issuer, date,
+                                               method, procParams,
+                                               methodFlags, 
+                                               chainVerificationState,
+                                               &revStatus,
+                                               pReasonCode, plContext),
+                    PKIX_REVCHECKERCHECKFAILED);
+                methodStatus[methodNum] = revStatus;
+                if (revStatus == PKIX_RevStatus_Revoked) {
+                    /* if error was generated use it as final error. */
+                    overallStatus = PKIX_RevStatus_Revoked;
+                    goto cleanup;
+                }
+                if (pkixErrorResult) {
+                    /* Disregard errors. Only returned revStatus matters. */
+                    PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+                                          plContext);
+                    pkixErrorResult = NULL;
+                }
+            }
+            if ((!(revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST) ||
+                 onlyUseRemoteMethods) &&
+                chainVerificationState &&
+                methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
+                if (!(methodFlags & PKIX_REV_M_FORBID_NETWORK_FETCHING)) {
+                    PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+                    PKIX_CHECK_NO_GOTO(
+                        (*method->externalRevChecker)(cert, issuer, date,
+                                                      method,
+                                                      procParams, methodFlags,
+                                                      &revStatus, pReasonCode,
+                                                      &nbioContext, plContext),
+                        PKIX_REVCHECKERCHECKFAILED);
+                    methodStatus[methodNum] = revStatus;
+                    if (revStatus == PKIX_RevStatus_Revoked) {
+                        /* if error was generated use it as final error. */
+                        overallStatus = PKIX_RevStatus_Revoked;
+                        goto cleanup;
+                    }
+                    if (pkixErrorResult) {
+                        /* Disregard errors. Only returned revStatus matters. */
+                        PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+                                              plContext);
+                        pkixErrorResult = NULL;
+                    }
+                } else if (methodFlags &
+                           PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+                    /* Info is not in the local cache. Network fetching is not
+                     * allowed. If need to fail on missing fresh info for the
+                     * the method, then we should fail right here.*/
+                    overallStatus = PKIX_RevStatus_Revoked;
+                    goto cleanup;
+                }
+            }
+            /* If success and we should not check the next method, then
+             * return a success. */
+            if (methodStatus[methodNum] == PKIX_RevStatus_Success &&
+                !(methodFlags & PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO)) {
+                overallStatus = PKIX_RevStatus_Success;
+                goto cleanup;
+            }
+        } /* inner loop */
+        if (!onlyUseRemoteMethods &&
+            revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST &&
+            chainVerificationState) {
+            onlyUseRemoteMethods = PKIX_TRUE;
+            continue;
+        }
+        break;
+    } /* outer loop */
+    
+    if (overallStatus == PKIX_RevStatus_NoInfo &&
+        chainVerificationState) {
+        /* The following check makes sence only for chain
+         * validation step, sinse we do not fetch info while
+         * in the process of finding trusted anchor. 
+         * For chain building step it is enough to know, that
+         * the cert was not directly revoked by any of the
+         * methods. */
+
+        /* Still have no info. But one of the method could
+         * have returned success status(possible if CONTINUE
+         * TESTING ON FRESH INFO flag was used).
+         * If any of the methods have returned Success status,
+         * the overallStatus should be success. */
+        int methodNum = 0;
+        for (;methodNum < PKIX_RevocationMethod_MAX;methodNum++) {
+            if (methodStatus[methodNum] == PKIX_RevStatus_Success) {
+                overallStatus = PKIX_RevStatus_Success;
+                goto cleanup;
+            }
+        }
+        if (revFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) {
+            overallStatus = PKIX_RevStatus_Revoked;
+        }
+    }
+
+cleanup:
+    *pRevStatus = overallStatus;
+    PKIX_DECREF(method);
+
+    PKIX_RETURN(REVOCATIONCHECKER);
+}
+
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)