summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix/checker
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix/checker')
-rw-r--r--security/nss/lib/libpkix/pkix/checker/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/checker/checker.gyp35
-rw-r--r--security/nss/lib/libpkix/pkix/checker/exports.gyp37
-rw-r--r--security/nss/lib/libpkix/pkix/checker/manifest.mn42
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c306
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h42
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c322
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h36
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c438
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h68
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c328
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h92
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c113
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h30
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c121
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h30
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c340
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h43
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c419
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h67
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c2783
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h73
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c475
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h151
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c66
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h81
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c443
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h44
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c516
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h47
30 files changed, 7634 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/checker/Makefile b/security/nss/lib/libpkix/pkix/checker/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
diff --git a/security/nss/lib/libpkix/pkix/checker/checker.gyp b/security/nss/lib/libpkix/pkix/checker/checker.gyp
new file mode 100644
index 0000000000..ac260fc24d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/checker.gyp
@@ -0,0 +1,35 @@
+# 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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixchecker',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_basicconstraintschecker.c',
+ 'pkix_certchainchecker.c',
+ 'pkix_crlchecker.c',
+ 'pkix_ekuchecker.c',
+ 'pkix_expirationchecker.c',
+ 'pkix_namechainingchecker.c',
+ 'pkix_nameconstraintschecker.c',
+ 'pkix_ocspchecker.c',
+ 'pkix_policychecker.c',
+ 'pkix_revocationchecker.c',
+ 'pkix_revocationmethod.c',
+ 'pkix_signaturechecker.c',
+ 'pkix_targetcertchecker.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/checker/exports.gyp b/security/nss/lib/libpkix/pkix/checker/exports.gyp
new file mode 100644
index 0000000000..4bd68b39c1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/exports.gyp
@@ -0,0 +1,37 @@
+# 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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_checker_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_basicconstraintschecker.h',
+ 'pkix_certchainchecker.h',
+ 'pkix_crlchecker.h',
+ 'pkix_ekuchecker.h',
+ 'pkix_expirationchecker.h',
+ 'pkix_namechainingchecker.h',
+ 'pkix_nameconstraintschecker.h',
+ 'pkix_ocspchecker.h',
+ 'pkix_policychecker.h',
+ 'pkix_revocationchecker.h',
+ 'pkix_revocationmethod.h',
+ 'pkix_signaturechecker.h',
+ 'pkix_targetcertchecker.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/manifest.mn b/security/nss/lib/libpkix/pkix/checker/manifest.mn
new file mode 100644
index 0000000000..84a372cea9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/manifest.mn
@@ -0,0 +1,42 @@
+#
+# 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/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_basicconstraintschecker.h \
+ pkix_certchainchecker.h \
+ pkix_crlchecker.h \
+ pkix_ekuchecker.h \
+ pkix_expirationchecker.h \
+ pkix_namechainingchecker.h \
+ pkix_nameconstraintschecker.h \
+ pkix_ocspchecker.h \
+ pkix_policychecker.h \
+ pkix_revocationmethod.h \
+ pkix_revocationchecker.h \
+ pkix_signaturechecker.h \
+ pkix_targetcertchecker.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_basicconstraintschecker.c \
+ pkix_certchainchecker.c \
+ pkix_crlchecker.c \
+ pkix_ekuchecker.c \
+ pkix_expirationchecker.c \
+ pkix_namechainingchecker.c \
+ pkix_nameconstraintschecker.c \
+ pkix_ocspchecker.c \
+ pkix_revocationmethod.c \
+ pkix_revocationchecker.c \
+ pkix_policychecker.c \
+ pkix_signaturechecker.c \
+ pkix_targetcertchecker.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixchecker
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c
new file mode 100644
index 0000000000..0e7a87997d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c
@@ -0,0 +1,306 @@
+/* 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_basicconstraintschecker.c
+ *
+ * Functions for basic constraints validation
+ *
+ */
+
+#include "pkix_basicconstraintschecker.h"
+
+/* --Private-BasicConstraintsCheckerState-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BasicConstraintsCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a basic constraints checker state */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE);
+
+ state = (pkix_BasicConstraintsCheckerState *)object;
+
+ PKIX_DECREF(state->basicConstraintsOID);
+
+cleanup:
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERT_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_BasicConstraintsCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_RegisterSelf");
+
+ entry.description = "BasicConstraintsCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState);
+ entry.destructor = pkix_BasicConstraintsCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_Create
+ * DESCRIPTION:
+ *
+ * Creates a new BasicConstraintsCheckerState using the number of certs in
+ * the chain represented by "certsRemaining" and stores it at "pState".
+ *
+ * PARAMETERS:
+ * "certsRemaining"
+ * Number of certificates 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 BasicConstraintsCheckerState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_BasicConstraintsCheckerState_Create(
+ PKIX_UInt32 certsRemaining,
+ pkix_BasicConstraintsCheckerState **pState,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_Create");
+
+ PKIX_NULLCHECK_ONE(pState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE,
+ sizeof (pkix_BasicConstraintsCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT);
+
+ /* initialize fields */
+ state->certsRemaining = certsRemaining;
+ state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_BASICCONSTRAINTS_OID,
+ &state->basicConstraintsOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/* --Private-BasicConstraintsChecker-Functions------------------------------ */
+
+/*
+ * FUNCTION: pkix_BasicConstraintsChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_BasicConstraintsChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ pkix_BasicConstraintsCheckerState *state = NULL;
+ PKIX_Boolean caFlag = PKIX_FALSE;
+ PKIX_Int32 pathLength = 0;
+ PKIX_Int32 maxPathLength_now;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_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->certsRemaining != 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraints, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ /* get CA Flag and path length */
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints,
+ &caFlag,
+ plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+
+ if (caFlag == PKIX_TRUE) {
+ PKIX_CHECK
+ (PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (basicConstraints,
+ &pathLength,
+ plContext),
+ PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
+ }
+
+ }else{
+ caFlag = PKIX_FALSE;
+ pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ }
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert,
+ &isSelfIssued,
+ plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ maxPathLength_now = state->maxPathLength;
+
+ if (isSelfIssued != PKIX_TRUE) {
+
+ /* Not last CA Cert, but maxPathLength is down to zero */
+ if (maxPathLength_now == 0) {
+ PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN);
+ }
+
+ if (caFlag == PKIX_FALSE) {
+ PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA);
+ }
+
+ if (maxPathLength_now > 0) { /* can be unlimited (-1) */
+ maxPathLength_now--;
+ }
+
+ }
+
+ if (caFlag == PKIX_TRUE) {
+ if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){
+ maxPathLength_now = pathLength;
+ } else {
+ /* If pathLength is not specified, don't set */
+ if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) {
+ maxPathLength_now =
+ (maxPathLength_now > pathLength)?
+ pathLength:maxPathLength_now;
+ }
+ }
+ }
+
+ state->maxPathLength = maxPathLength_now;
+ }
+
+ /* Remove Basic Constraints Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->basicConstraintsOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+
+cleanup:
+ PKIX_DECREF(state);
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsChecker_Initialize
+ * DESCRIPTION:
+ * Registers PKIX_CERT_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_BasicConstraintsChecker_Initialize(
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create
+ (certsRemaining, &state, plContext),
+ PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_BasicConstraintsChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCHECKFAILED);
+
+cleanup:
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h
new file mode 100644
index 0000000000..7a8b09c379
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h
@@ -0,0 +1,42 @@
+/* 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_basicconstraintschecker.h
+ *
+ * Header file for basic constraints checker.
+ *
+ */
+
+#ifndef _PKIX_BASICCONSTRAINTSCHECKER_H
+#define _PKIX_BASICCONSTRAINTSCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_BasicConstraintsCheckerStateStruct \
+ pkix_BasicConstraintsCheckerState;
+
+struct pkix_BasicConstraintsCheckerStateStruct{
+ PKIX_PL_OID *basicConstraintsOID;
+ PKIX_Int32 certsRemaining;
+ PKIX_Int32 maxPathLength;
+};
+
+PKIX_Error *
+pkix_BasicConstraintsChecker_Initialize(
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BASICCONSTRAINTSCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c
new file mode 100644
index 0000000000..a6ea50d02d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c
@@ -0,0 +1,322 @@
+/* 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_certchainchecker.c
+ *
+ * CertChainChecker Object Functions
+ *
+ */
+
+#include "pkix_certchainchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertChainChecker_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertChainChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a cert chain checker */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+ checker = (PKIX_CertChainChecker *)object;
+
+ PKIX_DECREF(checker->extensions);
+ PKIX_DECREF(checker->state);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CertChainChecker_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertChainChecker_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_CertChainChecker *checkerDuplicate = NULL;
+ PKIX_List *extensionsDuplicate = NULL;
+ PKIX_PL_Object *stateDuplicate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+ checker = (PKIX_CertChainChecker *)object;
+
+ if (checker->extensions){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->extensions,
+ (PKIX_PL_Object **)&extensionsDuplicate,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ if (checker->state){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->state,
+ (PKIX_PL_Object **)&stateDuplicate,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (checker->checkCallback,
+ checker->forwardChecking,
+ checker->isForwardDirectionExpected,
+ extensionsDuplicate,
+ stateDuplicate,
+ &checkerDuplicate,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)checkerDuplicate;
+
+cleanup:
+
+ PKIX_DECREF(extensionsDuplicate);
+ PKIX_DECREF(stateDuplicate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CertChainChecker_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTCHAINCHECKER_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_CertChainChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_RegisterSelf");
+
+ entry.description = "CertChainChecker";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertChainChecker);
+ entry.destructor = pkix_CertChainChecker_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CertChainChecker_Duplicate;
+
+ systemClasses[PKIX_CERTCHAINCHECKER_TYPE] = entry;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_Create (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_Create(
+ PKIX_CertChainChecker_CheckCallback callback,
+ PKIX_Boolean forwardCheckingSupported,
+ PKIX_Boolean isForwardDirectionExpected,
+ PKIX_List *list, /* list of PKIX_PL_OID */
+ PKIX_PL_Object *initialState,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_Create");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTCHAINCHECKER_TYPE,
+ sizeof (PKIX_CertChainChecker),
+ (PKIX_PL_Object **)&checker,
+ plContext),
+ PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+
+ /* initialize fields */
+ checker->checkCallback = callback;
+ checker->forwardChecking = forwardCheckingSupported;
+ checker->isForwardDirectionExpected = isForwardDirectionExpected;
+
+ PKIX_INCREF(list);
+ checker->extensions = list;
+
+ PKIX_INCREF(initialState);
+ checker->state = initialState;
+
+ *pChecker = checker;
+ checker = NULL;
+cleanup:
+
+ PKIX_DECREF(checker);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCheckCallback
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCheckCallback(
+ PKIX_CertChainChecker *checker,
+ PKIX_CertChainChecker_CheckCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_GetCheckCallback");
+ PKIX_NULLCHECK_TWO(checker, pCallback);
+
+ *pCallback = checker->checkCallback;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardCheckingSupported
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardCheckingSupported(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardCheckingSupported,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_IsForwardCheckingSupported");
+ PKIX_NULLCHECK_TWO(checker, pForwardCheckingSupported);
+
+ *pForwardCheckingSupported = checker->forwardChecking;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardDirectionExpected
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardDirectionExpected(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardDirectionExpected,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_IsForwardDirectionExpected");
+ PKIX_NULLCHECK_TWO(checker, pForwardDirectionExpected);
+
+ *pForwardDirectionExpected = checker->isForwardDirectionExpected;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCertChainCheckerState
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object **pCertChainCheckerState,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_GetCertChainCheckerState");
+
+ PKIX_NULLCHECK_TWO(checker, pCertChainCheckerState);
+
+ PKIX_INCREF(checker->state);
+
+ *pCertChainCheckerState = checker->state;
+
+cleanup:
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_SetCertChainCheckerState
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_SetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object *certChainCheckerState,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_SetCertChainCheckerState");
+
+ PKIX_NULLCHECK_ONE(checker);
+
+ /* DecRef old contents */
+ PKIX_DECREF(checker->state);
+
+ PKIX_INCREF(certChainCheckerState);
+ checker->state = certChainCheckerState;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)checker, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetSupportedExtensions
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetSupportedExtensions(
+ PKIX_CertChainChecker *checker,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_GetSupportedExtensions");
+
+ PKIX_NULLCHECK_TWO(checker, pExtensions);
+
+ PKIX_INCREF(checker->extensions);
+
+ *pExtensions = checker->extensions;
+
+cleanup:
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h
new file mode 100644
index 0000000000..ff6454761e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h
@@ -0,0 +1,36 @@
+/* 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_certchainchecker.h
+ *
+ * CertChainChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CERTCHAINCHECKER_H
+#define _PKIX_CERTCHAINCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertChainCheckerStruct {
+ PKIX_CertChainChecker_CheckCallback checkCallback;
+ PKIX_List *extensions;
+ PKIX_PL_Object *state;
+ PKIX_Boolean forwardChecking;
+ PKIX_Boolean isForwardDirectionExpected;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CertChainChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTCHAINCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c
new file mode 100644
index 0000000000..d6f5b6bcc8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c
@@ -0,0 +1,438 @@
+/* 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_defaultcrlchecker.c
+ *
+ * Functions for default CRL Checkers
+ *
+ */
+#include "pkix.h"
+#include "pkix_crlchecker.h"
+#include "pkix_tools.h"
+
+/* --Private-CRLChecker-Data-and-Types------------------------------- */
+
+typedef struct pkix_CrlCheckerStruct {
+ /* RevocationMethod is the super class of CrlChecker. */
+ pkix_RevocationMethod method;
+ PKIX_List *certStores; /* list of CertStore */
+ PKIX_PL_VerifyCallback crlVerifyFn;
+} pkix_CrlChecker;
+
+
+/* --Private-CRLChecker-Functions----------------------------------- */
+
+/*
+ * FUNCTION: pkix_CrlCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CrlChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_CrlChecker *state = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a default CRL checker state */
+ PKIX_CHECK(
+ pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCRLCHECKER);
+
+ state = (pkix_CrlChecker *)object;
+
+ PKIX_DECREF(state->certStores);
+
+cleanup:
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRLCHECKER_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * 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_CrlChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf");
+
+ entry->description = "CRLChecker";
+ entry->typeObjectSize = sizeof(pkix_CrlChecker);
+ entry->destructor = pkix_CrlChecker_Destroy;
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize CRLChecker state data.
+ *
+ * PARAMETERS
+ * "certStores"
+ * Address of CertStore List to be stored in state. Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date to be checked. May be NULL.
+ * "trustedPubKey"
+ * Trusted Anchor Public Key for verifying first Cert in the chain.
+ * Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "nistCRLPolicyEnabled"
+ * If enabled, enforce nist crl policy.
+ * "pChecker"
+ * Address of CRLChecker that is returned. 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 DefaultCrlChecker Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_List *certStores,
+ PKIX_PL_VerifyCallback crlVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext)
+{
+ pkix_CrlChecker *crlChecker = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create");
+ PKIX_NULLCHECK_TWO(certStores, pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLCHECKER_TYPE,
+ sizeof (pkix_CrlChecker),
+ (PKIX_PL_Object **)&crlChecker,
+ plContext),
+ PKIX_COULDNOTCREATECRLCHECKEROBJECT);
+
+ pkixErrorResult = pkix_RevocationMethod_Init(
+ (pkix_RevocationMethod*)crlChecker, methodType, flags, priority,
+ localRevChecker, externalRevChecker, plContext);
+ if (pkixErrorResult) {
+ goto cleanup;
+ }
+
+ /* Initialize fields */
+ PKIX_INCREF(certStores);
+ crlChecker->certStores = certStores;
+
+ crlChecker->crlVerifyFn = crlVerifyFn;
+ *pChecker = (pkix_RevocationMethod*)crlChecker;
+ crlChecker = NULL;
+
+cleanup:
+ PKIX_DECREF(crlChecker);
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/* --Private-CRLChecker-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_CrlChecker_CheckLocal
+ *
+ * DESCRIPTION:
+ * Check if the Cert has been revoked based the CRLs data. This function
+ * maintains the checker state to be current.
+ *
+ * PARAMETERS
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unreslvdCrtExts"
+ * A List OIDs. Not **yet** used in this checker function.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not 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
+ */
+PKIX_Error *
+pkix_CrlChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void *plContext)
+{
+ PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn;
+ PKIX_CertStore *certStore = NULL;
+ pkix_CrlChecker *state = NULL;
+ PKIX_UInt32 crlStoreIndex = 0;
+ PKIX_UInt32 numCrlStores = 0;
+ PKIX_Boolean storeIsLocal = PKIX_FALSE;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal");
+ PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject);
+
+ state = (pkix_CrlChecker*)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
+ plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+ if (storeIsLocal) {
+ PKIX_CHECK(
+ PKIX_CertStore_GetCrlCheckerFn(certStore,
+ &storeCheckRevocationFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ if (storeCheckRevocationFn) {
+ PKIX_CHECK(
+ (*storeCheckRevocationFn)(certStore, cert, issuer,
+ /* delay sig check if building
+ * a chain by not specifying the time*/
+ chainVerificationState ? date : NULL,
+ /* crl downloading is not done. */
+ PKIX_FALSE,
+ pReasonCode, &revStatus, plContext),
+ PKIX_CERTSTORECRLCHECKFAILED);
+ if (revStatus == PKIX_RevStatus_Revoked) {
+ break;
+ }
+ }
+ }
+ PKIX_DECREF(certStore);
+ } /* while */
+
+cleanup:
+ *pRevStatus = revStatus;
+ PKIX_DECREF(certStore);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_CheckRemote
+ *
+ * DESCRIPTION:
+ * Check if the Cert has been revoked based the CRLs data. This function
+ * maintains the checker state to be current.
+ *
+ * PARAMETERS
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unreslvdCrtExts"
+ * A List OIDs. Not **yet** used in this checker function.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not 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
+ */
+PKIX_Error *
+pkix_CrlChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL;
+ PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore *localStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ pkix_CrlChecker *state = NULL;
+ PKIX_UInt32 crlStoreIndex = 0;
+ PKIX_UInt32 numCrlStores = 0;
+ PKIX_Boolean storeIsLocal = PKIX_FALSE;
+ PKIX_List *crlList = NULL;
+ PKIX_List *dpList = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal");
+ PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL; /* prepare for Error exit */
+
+ state = (pkix_CrlChecker*)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Find a cert store that is capable of storing crls */
+ for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
+ plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+ if (storeIsLocal) {
+ PKIX_CHECK(
+ PKIX_CertStore_GetImportCrlCallback(certStore,
+ &storeImportCrlFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetCrlCheckerFn(certStore,
+ &storeCheckRevocationFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ if (storeImportCrlFn && storeCheckRevocationFn) {
+ localStore = certStore;
+ certStore = NULL;
+ break;
+ }
+ }
+ PKIX_DECREF(certStore);
+ } /* while */
+
+ /* Report unknown status if we can not check crl in one of the
+ * local stores. */
+ if (!localStore) {
+ PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND);
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext),
+ PKIX_CERTCHECKKEYUSAGEFAILED);
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext),
+ PKIX_CERTGETCRLDPFAILED);
+ if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
+ (!dpList || !dpList->length)) {
+ goto cleanup;
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+ PKIX_CHECK(
+ PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext),
+ PKIX_CRLCHECKERSETSELECTORFAILED);
+ /* Fetch crl and store in a local cert store */
+ for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CertStore_CRLCallback getCrlsFn;
+
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn,
+ plContext),
+ PKIX_CERTSTOREGETCRLCALLBACKFAILED);
+
+ PKIX_CHECK(
+ (*getCrlsFn)(certStore, crlSelector, &nbioContext,
+ &crlList, plContext),
+ PKIX_GETCRLSFAILED);
+
+ PKIX_CHECK(
+ (*storeImportCrlFn)(localStore, issuerName, crlList, plContext),
+ PKIX_CERTSTOREFAILTOIMPORTCRLLIST);
+
+ PKIX_CHECK(
+ (*storeCheckRevocationFn)(certStore, cert, issuer, date,
+ /* done with crl downloading */
+ PKIX_TRUE,
+ pReasonCode, &revStatus, plContext),
+ PKIX_CERTSTORECRLCHECKFAILED);
+ if (revStatus != PKIX_RevStatus_NoInfo) {
+ break;
+ }
+ PKIX_DECREF(crlList);
+ PKIX_DECREF(certStore);
+ } /* while */
+
+cleanup:
+ /* Update return flags */
+ if (revStatus == PKIX_RevStatus_NoInfo &&
+ ((dpList && dpList->length > 0) ||
+ (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) &&
+ methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+ revStatus = PKIX_RevStatus_Revoked;
+ }
+ *pRevStatus = revStatus;
+
+ PKIX_DECREF(dpList);
+ PKIX_DECREF(crlList);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(localStore);
+ PKIX_DECREF(crlSelector);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h
new file mode 100644
index 0000000000..35f1a47455
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h
@@ -0,0 +1,68 @@
+/* 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_defaultcrlchecker.h
+ *
+ * Header file for default CRL function
+ *
+ */
+
+#ifndef _PKIX_CRLCHECKER_H
+#define _PKIX_CRLCHECKER_H
+
+#include "pkixt.h"
+#include "pkix_revocationmethod.h"
+#include "pkix_crlsel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logic removed. Will be replaced later. */
+
+PKIX_Error *
+pkix_CrlChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_List *certStores,
+ PKIX_PL_VerifyCallback crlVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CRLCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c
new file mode 100644
index 0000000000..a2b8437397
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c
@@ -0,0 +1,328 @@
+/* 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_ekuchecker.c
+ *
+ * User Defined ExtenedKeyUsage Function Definitions
+ *
+ */
+
+#include "pkix_ekuchecker.h"
+
+SECOidTag ekuOidStrings[] = {
+ PKIX_KEY_USAGE_SERVER_AUTH_OID,
+ PKIX_KEY_USAGE_CLIENT_AUTH_OID,
+ PKIX_KEY_USAGE_CODE_SIGN_OID,
+ PKIX_KEY_USAGE_EMAIL_PROTECT_OID,
+ PKIX_KEY_USAGE_TIME_STAMP_OID,
+ PKIX_KEY_USAGE_OCSP_RESPONDER_OID,
+ PKIX_UNKNOWN_OID
+};
+
+typedef struct pkix_EkuCheckerStruct {
+ PKIX_List *requiredExtKeyUsageOids;
+ PKIX_PL_OID *ekuOID;
+} pkix_EkuChecker;
+
+
+/*
+ * FUNCTION: pkix_EkuChecker_Destroy
+ * (see comments for PKIX_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_EkuChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_EkuChecker *ekuCheckerState = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTANEKUCHECKERSTATE);
+
+ ekuCheckerState = (pkix_EkuChecker *)object;
+
+ PKIX_DECREF(ekuCheckerState->ekuOID);
+ PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids);
+
+cleanup:
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_HTTPCERTSTORECONTEXT_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_EkuChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE];
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf");
+
+ entry->description = "EkuChecker";
+ entry->typeObjectSize = sizeof(pkix_EkuChecker);
+ entry->destructor = pkix_EkuChecker_Destroy;
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Extend Key Usage CheckerState using "params" to retrieve
+ * application specified EKU for verification and stores it at "pState".
+ *
+ * PARAMETERS:
+ * "params"
+ * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification.
+ * "pState"
+ * Address where state 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 UserDefinedModules Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ pkix_EkuChecker **pState,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_ComCertSelParams *comCertSelParams = NULL;
+ PKIX_List *requiredOids = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create");
+ PKIX_NULLCHECK_TWO(params, pState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_EKUCHECKER_TYPE,
+ sizeof (pkix_EkuChecker),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT);
+
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (params, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ if (certSelector != NULL) {
+
+ /* Get initial EKU OIDs from ComCertSelParams, if set */
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (certSelector, &comCertSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ if (comCertSelParams != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (comCertSelParams, &requiredOids, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_EXTENDEDKEYUSAGE_OID,
+ &state->ekuOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ state->requiredExtKeyUsageOids = requiredOids;
+ requiredOids = NULL;
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(comCertSelParams);
+ PKIX_DECREF(requiredOids);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Check
+ * DESCRIPTION:
+ *
+ * This function determines the Extended Key Usage OIDs specified by the
+ * application is included in the Extended Key Usage OIDs of this "cert".
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unresolvedCriticalExtensions"
+ * A List OIDs. The OID for Extended Key Usage is removed.
+ * "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 UserDefinedModules Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_EkuChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_List *requiredExtKeyUsageList = NULL;
+ PKIX_List *certExtKeyUsageList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+ PKIX_Boolean checkResult = PKIX_TRUE;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* no non-blocking IO */
+
+ PKIX_CHECK(
+ PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ requiredExtKeyUsageList = state->requiredExtKeyUsageOids;
+ if (requiredExtKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(requiredExtKeyUsageList, &numItems,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (numItems == 0) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList,
+ plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ if (certExtKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(
+ PKIX_List_GetItem(requiredExtKeyUsageList, i,
+ (PKIX_PL_Object **)&ekuOid, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ pkix_List_Contains(certExtKeyUsageList,
+ (PKIX_PL_Object *)ekuOid,
+ &isContained,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(ekuOid);
+ if (isContained != PKIX_TRUE) {
+ checkResult = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (!pkixErrorResult && checkResult == PKIX_FALSE) {
+ pkixErrorReceived = PKIX_TRUE;
+ pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED;
+ }
+
+ PKIX_DECREF(ekuOid);
+ PKIX_DECREF(certExtKeyUsageList);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Initialize
+ * (see comments in pkix_sample_modules.h)
+ */
+PKIX_Error *
+PKIX_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker **pEkuChecker,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_List *critExtOIDsList = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize");
+ PKIX_NULLCHECK_ONE(params);
+
+ /*
+ * This function and functions in this file provide an example of how
+ * an application defined checker can be hooked into libpkix.
+ */
+
+ PKIX_CHECK(pkix_EkuChecker_Create
+ (params, &state, plContext),
+ PKIX_EKUCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (critExtOIDsList,
+ (PKIX_PL_Object *)state->ekuOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_EkuChecker_Check,
+ PKIX_TRUE, /* forwardCheckingSupported */
+ PKIX_FALSE, /* forwardDirectionExpected */
+ critExtOIDsList,
+ (PKIX_PL_Object *) state,
+ pEkuChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+cleanup:
+
+ PKIX_DECREF(critExtOIDsList);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h
new file mode 100644
index 0000000000..e542dda20b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h
@@ -0,0 +1,92 @@
+/* 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_ekuchecker.h
+ *
+ * User Defined Object Type Extended Key Usage Definition
+ *
+ */
+
+#ifndef _PKIX_EKUCHECKER_H
+#define _PKIX_EKUCHECKER_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * FUNCTION: PKIX_PL_EkuChecker_Create
+ *
+ * DESCRIPTION:
+ * Create a CertChainChecker with EkuCheckerState and add it into
+ * PKIX_ProcessingParams object.
+ *
+ * PARAMETERS
+ * "params"
+ * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification.
+ * "ekuChecker"
+ * Address of created ekuchecker.
+ * "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 UserDefinedModules Error if the function fails in a non-fatal
+ * way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+PKIX_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker **ekuChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_EkuChecker_GetRequiredEku
+ *
+ * DESCRIPTION:
+ * This function retrieves application specified ExtenedKeyUsage(s) from
+ * ComCertSetparams and converts its OID representations to SECCertUsageEnum.
+ * The result is stored and returned in bit mask at "pRequiredExtKeyUsage".
+ *
+ * PARAMETERS
+ * "certSelector"
+ * a PKIX_CertSelector links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification. Must be non-NULL.
+ * "pRequiredExtKeyUsage"
+ * Address where the result is returned. 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 UserDefinedModules Error if the function fails in a non-fatal
+ * way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_EkuChecker_GetRequiredEku(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 *pRequiredExtKeyUsage,
+ void *plContext);
+
+/* see source file for function documentation */
+PKIX_Error *pkix_EkuChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_EKUCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c
new file mode 100644
index 0000000000..4f101ee29b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c
@@ -0,0 +1,113 @@
+/* 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_expirationchecker.c
+ *
+ * Functions for expiration validation
+ *
+ */
+
+
+#include "pkix_expirationchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ExpirationChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_ExpirationChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_Date *testDate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_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 **)&testDate, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity(cert, testDate, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+
+cleanup:
+
+ PKIX_DECREF(testDate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_ExpirationChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * used by pkix_ExpirationChecker_Check to check that the certificate has not
+ * expired with respect to the Date pointed to by "testDate." If "testDate"
+ * is NULL, then the CertChainChecker will check that a certificate has not
+ * expired with respect to the current date and time.
+ *
+ * PARAMETERS:
+ * "testDate"
+ * Address of Date representing the point in time at which the cert is to
+ * be validated. If "testDate" is NULL, the current date and time is used.
+ * "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_ExpirationChecker_Initialize(
+ PKIX_PL_Date *testDate,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_PL_Date *myDate = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ /* if testDate is NULL, we use the current time */
+ if (!testDate){
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &nowDate, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+ myDate = nowDate;
+ } else {
+ myDate = testDate;
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_ExpirationChecker_Check,
+ PKIX_TRUE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)myDate,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(nowDate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h
new file mode 100644
index 0000000000..17b5c1bc10
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h
@@ -0,0 +1,30 @@
+/* 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_expirationchecker.h
+ *
+ * Header file for validate expiration function
+ *
+ */
+
+#ifndef _PKIX_EXPIRATIONCHECKER_H
+#define _PKIX_EXPIRATIONCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_ExpirationChecker_Initialize(
+ PKIX_PL_Date *testDate,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_EXPIRATIONCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c
new file mode 100644
index 0000000000..873d19cd05
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c
@@ -0,0 +1,121 @@
+/* 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_namechainingchecker.c
+ *
+ * Functions for name chaining validation
+ *
+ */
+
+
+#include "pkix_namechainingchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_NameChainingChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_NameChainingChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_X500Name *prevSubject = NULL;
+ PKIX_PL_X500Name *currIssuer = NULL;
+ PKIX_PL_X500Name *currSubject = NULL;
+ PKIX_Boolean result;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameChainingChecker_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 **)&prevSubject, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &currIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (prevSubject){
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (prevSubject, currIssuer, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+ if (!result){
+ PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
+ }
+ } else {
+ PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &currSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)currSubject, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(prevSubject);
+ PKIX_DECREF(currIssuer);
+ PKIX_DECREF(currSubject);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_NameChainingChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * be used by pkix_NameChainingChecker_Check to check that the issuer name
+ * of the certificate matches the subject name in the checker's state. The
+ * X500Name pointed to by "trustedCAName" is used to initialize the checker's
+ * state.
+ *
+ * PARAMETERS:
+ * "trustedCAName"
+ * Address of X500Name representing the trusted CA Name used to
+ * initialize the state of this checker. Must be non-NULL.
+ * "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_NameChainingChecker_Initialize(
+ PKIX_PL_X500Name *trustedCAName,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_NameChainingChecker_Initialize");
+ PKIX_NULLCHECK_TWO(pChecker, trustedCAName);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_NameChainingChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)trustedCAName,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h
new file mode 100644
index 0000000000..bc413f4561
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h
@@ -0,0 +1,30 @@
+/* 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_namechainingchecker.h
+ *
+ * Header file for name chaining checker.
+ *
+ */
+
+#ifndef _PKIX_NAMECHAININGCHECKER_H
+#define _PKIX_NAMECHAININGCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_NameChainingChecker_Initialize(
+ PKIX_PL_X500Name *trustedCAName,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_NAMECHAININGCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
new file mode 100644
index 0000000000..28f21a6c2d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
@@ -0,0 +1,340 @@
+/* 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_nameconstraintschecker.c
+ *
+ * Functions for Name Constraints Checkers
+ *
+ */
+
+#include "pkix_nameconstraintschecker.h"
+
+/* --Private-NameConstraintsCheckerState-Functions---------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that object type */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE);
+
+ state = (pkix_NameConstraintsCheckerState *)object;
+
+ PKIX_DECREF(state->nameConstraints);
+ PKIX_DECREF(state->nameConstraintsOID);
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_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_NameConstraintsCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_RegisterSelf");
+
+ entry.description = "NameConstraintsCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState);
+ entry.destructor = pkix_NameConstraintsCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize NameConstraintsChecker state data.
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of NameConstraints to be stored in state. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pCheckerState"
+ * Address of NameConstraintsCheckerState that is returned. 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 CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Create(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_UInt32 numCerts,
+ pkix_NameConstraintsCheckerState **pCheckerState,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Create");
+ PKIX_NULLCHECK_ONE(pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE,
+ sizeof (pkix_NameConstraintsCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT);
+
+ /* Initialize fields */
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_NAMECONSTRAINTS_OID,
+ &state->nameConstraintsOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_INCREF(nameConstraints);
+
+ state->nameConstraints = nameConstraints;
+ state->certsRemaining = numCerts;
+
+ *pCheckerState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/* --Private-NameConstraintsChecker-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL;
+ PKIX_Boolean selfIssued = PKIX_FALSE;
+ PKIX_Boolean lastCert = PKIX_FALSE;
+ PKIX_Boolean treatCommonNameAsDNSName = PKIX_FALSE;
+ PKIX_List *extKeyUsageList = NULL;
+ PKIX_PL_OID *serverAuthOID = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_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--;
+ lastCert = state->certsRemaining == 0;
+
+ /* Get status of self issued */
+ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (lastCert) {
+ /* For the last cert, treat the CN as a DNS name for name
+ * constraint check. But only if EKU has id-kp-serverAuth
+ * or EKU is absent. It does not make sense to treat CN
+ * as a DNS name for an OCSP signing certificate, for example.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &extKeyUsageList, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+ if (extKeyUsageList == NULL) {
+ treatCommonNameAsDNSName = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_KEY_USAGE_SERVER_AUTH_OID,
+ &serverAuthOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (extKeyUsageList,
+ (PKIX_PL_Object *) serverAuthOID,
+ &treatCommonNameAsDNSName,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+ }
+
+ /* Check on non self-issued and if so only for last cert */
+ if (selfIssued == PKIX_FALSE ||
+ (selfIssued == PKIX_TRUE && lastCert)) {
+ PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
+ (cert, state->nameConstraints, treatCommonNameAsDNSName,
+ plContext),
+ PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
+ }
+
+ if (!lastCert) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ /* Merge with previous name constraints kept in state */
+
+ if (nameConstraints != NULL) {
+
+ if (state->nameConstraints == NULL) {
+
+ state->nameConstraints = nameConstraints;
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints
+ (nameConstraints,
+ state->nameConstraints,
+ &mergedNameConstraints,
+ plContext),
+ PKIX_CERTMERGENAMECONSTRAINTSFAILED);
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(state->nameConstraints);
+
+ state->nameConstraints = mergedNameConstraints;
+ }
+
+ /* Remove Name Constraints Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *)state->nameConstraintsOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(serverAuthOID);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Initialize
+ *
+ * DESCRIPTION:
+ * Create a CertChainChecker with a NameConstraintsCheckerState. The
+ * NameConstraintsCheckerState is created with "trustedNC" and "numCerts"
+ * as its initial state. The CertChainChecker for the NameConstraints is
+ * returned at address of "pChecker".
+ *
+ * PARAMETERS
+ * "trustedNC"
+ * The NameConstraints from trusted anchor Cert is stored at "trustedNC"
+ * for initialization. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pChecker"
+ * Address of CertChainChecker to bo created and returned.
+ * 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
+ */
+PKIX_Error *
+pkix_NameConstraintsChecker_Initialize(
+ PKIX_PL_CertNameConstraints *trustedNC,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_NameConstraintsCheckerState_Create
+ (trustedNC, numCerts, &state, plContext),
+ PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_NameConstraintsChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h
new file mode 100644
index 0000000000..ac3de346db
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h
@@ -0,0 +1,43 @@
+/* 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_nameconstraintschecker.h
+ *
+ * Header file for validate Name Constraints Checker function
+ *
+ */
+
+#ifndef _PKIX_NAMECONSTRAINTSCHECKER_H
+#define _PKIX_NAMECONSTRAINTSCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_NameConstraintsCheckerState \
+ pkix_NameConstraintsCheckerState;
+
+struct pkix_NameConstraintsCheckerState {
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_PL_OID *nameConstraintsOID;
+ PKIX_UInt32 certsRemaining;
+};
+
+PKIX_Error *
+pkix_NameConstraintsChecker_Initialize(
+ PKIX_PL_CertNameConstraints *trustedNC,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_NAMECONSTRAINTSCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
new file mode 100644
index 0000000000..b6fca9a354
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
@@ -0,0 +1,419 @@
+/* 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_ocspchecker.c
+ *
+ * OcspChecker Object Functions
+ *
+ */
+
+#include "pkix_ocspchecker.h"
+#include "pkix_pl_ocspcertid.h"
+#include "pkix_error.h"
+
+
+/* --Private-Data-and-Types--------------------------------------- */
+
+typedef struct pkix_OcspCheckerStruct {
+ /* RevocationMethod is the super class of OcspChecker. */
+ pkix_RevocationMethod method;
+ PKIX_PL_VerifyCallback certVerifyFcn;
+} pkix_OcspChecker;
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_OcspChecker_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_OcspChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ return NULL;
+}
+
+/*
+ * FUNCTION: pkix_OcspChecker_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPCHECKER_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_OcspChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_OCSPCHECKER_TYPE];
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_RegisterSelf");
+
+ entry->description = "OcspChecker";
+ entry->typeObjectSize = sizeof(pkix_OcspChecker);
+ entry->destructor = pkix_OcspChecker_Destroy;
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
+/*
+ * FUNCTION: pkix_OcspChecker_Create
+ */
+PKIX_Error *
+pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_PL_VerifyCallback verifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext)
+{
+ pkix_OcspChecker *method = NULL;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Create");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPCHECKER_TYPE,
+ sizeof (pkix_OcspChecker),
+ (PKIX_PL_Object **)&method,
+ plContext),
+ PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+
+ pkixErrorResult = pkix_RevocationMethod_Init(
+ (pkix_RevocationMethod*)method, methodType, flags, priority,
+ localRevChecker, externalRevChecker, plContext);
+ if (pkixErrorResult) {
+ goto cleanup;
+ }
+ method->certVerifyFcn = (PKIX_PL_VerifyCallback)verifyFn;
+
+ *pChecker = (pkix_RevocationMethod*)method;
+ method = NULL;
+
+cleanup:
+ PKIX_DECREF(method);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_OcspChecker_MapResultCodeToRevStatus
+ */
+PKIX_RevocationStatus
+pkix_OcspChecker_MapResultCodeToRevStatus(SECErrorCodes resultCode)
+{
+ switch (resultCode) {
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ return PKIX_RevStatus_Revoked;
+ default:
+ return PKIX_RevStatus_NoInfo;
+ }
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_OcspChecker_Check (see comments in pkix_checker.h)
+ */
+
+/*
+ * The OCSPChecker is created in an idle state, and remains in this state until
+ * either (a) the default Responder has been set and enabled, and a Check
+ * request is received with no responder specified, or (b) a Check request is
+ * received with a specified responder. A request message is constructed and
+ * given to the HttpClient. If non-blocking I/O is used the client may return
+ * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
+ * condition to its caller in turn. On a subsequent call the I/O is resumed.
+ * When a response is received it is decoded and the results provided to the
+ * caller.
+ *
+ */
+PKIX_Error *
+pkix_OcspChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *cid = NULL;
+ PKIX_Boolean hasFreshStatus = PKIX_FALSE;
+ PKIX_Boolean statusIsGood = PKIX_FALSE;
+ SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckLocal");
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
+ plContext),
+ PKIX_OCSPCERTIDCREATEFAILED);
+ if (!cid) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_GetFreshCacheStatus(cid, date,
+ &hasFreshStatus,
+ &statusIsGood,
+ &resultCode,
+ plContext),
+ PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);
+ if (hasFreshStatus) {
+ if (statusIsGood) {
+ revStatus = PKIX_RevStatus_Success;
+ resultCode = 0;
+ } else {
+ revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
+ }
+ }
+
+cleanup:
+ *pRevStatus = revStatus;
+
+ /* ocsp carries only tree statuses: good, bad, and unknown.
+ * revStatus is used to pass them. reasonCode is always set
+ * to be unknown. */
+ *pReasonCode = crlEntryReasonUnspecified;
+ PKIX_DECREF(cid);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
+/*
+ * The OCSPChecker is created in an idle state, and remains in this state until
+ * either (a) the default Responder has been set and enabled, and a Check
+ * request is received with no responder specified, or (b) a Check request is
+ * received with a specified responder. A request message is constructed and
+ * given to the HttpClient. When a response is received it is decoded and the
+ * results provided to the caller.
+ *
+ * During the most recent enhancement of this function, it has been found that
+ * it doesn't correctly implement non-blocking I/O.
+ *
+ * The nbioContext is used in two places, for "response-obtaining" and
+ * for "response-verification".
+ *
+ * However, if this function gets called to resume, it always
+ * repeats the "request creation" and "response fetching" steps!
+ * As a result, the earlier operation is never resumed.
+ */
+PKIX_Error *
+pkix_OcspChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
+ PKIX_Boolean uriFound = PKIX_FALSE;
+ PKIX_Boolean passed = PKIX_TRUE;
+ pkix_OcspChecker *checker = NULL;
+ PKIX_PL_OcspCertID *cid = NULL;
+ PKIX_PL_OcspRequest *request = NULL;
+ PKIX_PL_OcspResponse *response = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ void *nbioContext = NULL;
+ enum { stageGET, stagePOST } currentStage;
+ PRBool retry = PR_FALSE;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckExternal");
+
+ PKIX_CHECK(
+ pkix_CheckType((PKIX_PL_Object*)checkerObject,
+ PKIX_OCSPCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPCHECKER);
+
+ checker = (pkix_OcspChecker *)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
+ plContext),
+ PKIX_OCSPCERTIDCREATEFAILED);
+
+ /* create request */
+ PKIX_CHECK(
+ pkix_pl_OcspRequest_Create(cert, cid, validity, NULL,
+ methodFlags, &uriFound, &request,
+ plContext),
+ PKIX_OCSPREQUESTCREATEFAILED);
+
+ if (uriFound == PKIX_FALSE) {
+ /* no caching for certs lacking URI */
+ resultCode = 0;
+ goto cleanup;
+ }
+
+ if (methodFlags & CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP) {
+ /* Do not try HTTP GET, only HTTP POST */
+ currentStage = stagePOST;
+ } else {
+ /* Try HTTP GET first, falling back to POST */
+ currentStage = stageGET;
+ }
+
+ do {
+ const char *method;
+ passed = PKIX_TRUE;
+
+ retry = PR_FALSE;
+ if (currentStage == stageGET) {
+ method = "GET";
+ } else {
+ PORT_Assert(currentStage == stagePOST);
+ method = "POST";
+ }
+
+ /* send request and create a response object */
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_Create(request, method, NULL,
+ checker->certVerifyFcn,
+ &nbioContext,
+ &response,
+ plContext),
+ PKIX_OCSPRESPONSECREATEFAILED);
+
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+
+ if (passed && nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_Decode(response, &passed,
+ &resultCode, plContext),
+ PKIX_OCSPRESPONSEDECODEFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_GetStatus(response, &passed,
+ &resultCode, plContext),
+ PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_VerifySignature(response, cert,
+ procParams, &passed,
+ &nbioContext, plContext),
+ PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ } else {
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ }
+ }
+
+ if (!passed && currentStage == stagePOST) {
+ /* We won't retry a POST failure, so it's final.
+ * Because the following block with its call to
+ * pkix_pl_OcspResponse_GetStatusForCert
+ * will take care of caching good or bad state,
+ * but we only execute that next block if there hasn't
+ * been a failure yet, we must cache the POST
+ * failure now.
+ */
+
+ if (cid && cid->certID) {
+ /* Caching MIGHT consume the cid. */
+ PKIX_Error *err;
+ err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ cid, plContext);
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
+ }
+ }
+ }
+
+ if (passed){
+ PKIX_Boolean allowCachingOfFailures =
+ (currentStage == stagePOST) ? PKIX_TRUE : PKIX_FALSE;
+
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_GetStatusForCert(cid, response,
+ allowCachingOfFailures,
+ date,
+ &passed, &resultCode,
+ plContext),
+ PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ } else if (passed == PKIX_FALSE) {
+ revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
+ } else {
+ revStatus = PKIX_RevStatus_Success;
+ }
+ }
+
+ if (currentStage == stageGET && revStatus != PKIX_RevStatus_Success &&
+ revStatus != PKIX_RevStatus_Revoked) {
+ /* we'll retry */
+ PKIX_DECREF(response);
+ retry = PR_TRUE;
+ currentStage = stagePOST;
+ revStatus = PKIX_RevStatus_NoInfo;
+ if (pkixErrorResult) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+ plContext);
+ pkixErrorResult = NULL;
+ }
+ }
+ } while (retry);
+
+cleanup:
+ if (revStatus == PKIX_RevStatus_NoInfo && (uriFound ||
+ methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
+ methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+ revStatus = PKIX_RevStatus_Revoked;
+ }
+ *pRevStatus = revStatus;
+
+ /* ocsp carries only three statuses: good, bad, and unknown.
+ * revStatus is used to pass them. reasonCode is always set
+ * to be unknown. */
+ *pReasonCode = crlEntryReasonUnspecified;
+
+ PKIX_DECREF(cid);
+ PKIX_DECREF(request);
+ PKIX_DECREF(response);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h
new file mode 100644
index 0000000000..fbec315f96
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h
@@ -0,0 +1,67 @@
+/* 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_ocspchecker.h
+ *
+ * OcspChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_OCSPCHECKER_H
+#define _PKIX_OCSPCHECKER_H
+
+#include "pkix_tools.h"
+#include "pkix_revocationmethod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logic removed. Will be replaced later. */
+
+PKIX_Error *
+pkix_OcspChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_OcspChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_PL_VerifyCallback certVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext);
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_OcspChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_OCSPCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c
new file mode 100644
index 0000000000..8e40596541
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c
@@ -0,0 +1,2783 @@
+/* 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_policychecker.c
+ *
+ * Functions for Policy Checker
+ *
+ */
+#include "pkix_policychecker.h"
+
+/* --Forward declarations----------------------------------------------- */
+
+static PKIX_Error *
+pkix_PolicyChecker_MakeSingleton(
+ PKIX_PL_Object *listItem,
+ PKIX_Boolean immutability,
+ PKIX_List **pList,
+ void *plContext);
+
+/* --Private-PolicyCheckerState-Functions---------------------------------- */
+
+/*
+ * FUNCTION:pkix_PolicyCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *checkerState = NULL;
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYCHECKERSTATE);
+
+ checkerState = (PKIX_PolicyCheckerState *)object;
+
+ PKIX_DECREF(checkerState->certPoliciesExtension);
+ PKIX_DECREF(checkerState->policyMappingsExtension);
+ PKIX_DECREF(checkerState->policyConstraintsExtension);
+ PKIX_DECREF(checkerState->inhibitAnyPolicyExtension);
+ PKIX_DECREF(checkerState->anyPolicyOID);
+ PKIX_DECREF(checkerState->validPolicyTree);
+ PKIX_DECREF(checkerState->userInitialPolicySet);
+ PKIX_DECREF(checkerState->mappedUserInitialPolicySet);
+
+ checkerState->policyQualifiersRejected = PKIX_FALSE;
+ checkerState->explicitPolicy = 0;
+ checkerState->inhibitAnyPolicy = 0;
+ checkerState->policyMapping = 0;
+ checkerState->numCerts = 0;
+ checkerState->certsProcessed = 0;
+ checkerState->certPoliciesCritical = PKIX_FALSE;
+
+ PKIX_DECREF(checkerState->anyPolicyNodeAtBottom);
+ PKIX_DECREF(checkerState->newAnyPolicyNode);
+ PKIX_DECREF(checkerState->mappedPolicyOIDs);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyCheckerState_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pCheckerStateString,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *state = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *policiesExtOIDString = NULL;
+ PKIX_PL_String *policyMapOIDString = NULL;
+ PKIX_PL_String *policyConstrOIDString = NULL;
+ PKIX_PL_String *inhAnyPolOIDString = NULL;
+ PKIX_PL_String *anyPolicyOIDString = NULL;
+ PKIX_PL_String *validPolicyTreeString = NULL;
+ PKIX_PL_String *userInitialPolicySetString = NULL;
+ PKIX_PL_String *mappedUserPolicySetString = NULL;
+ PKIX_PL_String *mappedPolicyOIDsString = NULL;
+ PKIX_PL_String *anyAtBottomString = NULL;
+ PKIX_PL_String *newAnyPolicyString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *trueString = NULL;
+ PKIX_PL_String *falseString = NULL;
+ PKIX_PL_String *nullString = NULL;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean certPoliciesCritical = PKIX_FALSE;
+ char *asciiFormat =
+ "{\n"
+ "\tcertPoliciesExtension: \t%s\n"
+ "\tpolicyMappingsExtension: \t%s\n"
+ "\tpolicyConstraintsExtension:\t%s\n"
+ "\tinhibitAnyPolicyExtension:\t%s\n"
+ "\tanyPolicyOID: \t%s\n"
+ "\tinitialIsAnyPolicy: \t%s\n"
+ "\tvalidPolicyTree: \t%s\n"
+ "\tuserInitialPolicySet: \t%s\n"
+ "\tmappedUserPolicySet: \t%s\n"
+ "\tpolicyQualifiersRejected: \t%s\n"
+ "\tinitialPolMappingInhibit: \t%s\n"
+ "\tinitialExplicitPolicy: \t%s\n"
+ "\tinitialAnyPolicyInhibit: \t%s\n"
+ "\texplicitPolicy: \t%d\n"
+ "\tinhibitAnyPolicy: \t%d\n"
+ "\tpolicyMapping: \t%d\n"
+ "\tnumCerts: \t%d\n"
+ "\tcertsProcessed: \t%d\n"
+ "\tanyPolicyNodeAtBottom: \t%s\n"
+ "\tnewAnyPolicyNode: \t%s\n"
+ "\tcertPoliciesCritical: \t%s\n"
+ "\tmappedPolicyOIDs: \t%s\n"
+ "}";
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pCheckerStateString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYCHECKERSTATE);
+
+ state = (PKIX_PolicyCheckerState *)object;
+ PKIX_NULLCHECK_THREE
+ (state->certPoliciesExtension,
+ state->policyMappingsExtension,
+ state->policyConstraintsExtension);
+ PKIX_NULLCHECK_THREE
+ (state->inhibitAnyPolicyExtension,
+ state->anyPolicyOID,
+ state->userInitialPolicySet);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ /*
+ * Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a
+ * PKIX_PL_String is complicated enough, it's worth checking, for
+ * each, to make sure the string is needed.
+ */
+ initialPolicyMappingInhibit = state->initialPolicyMappingInhibit;
+ initialExplicitPolicy = state->initialExplicitPolicy;
+ initialAnyPolicyInhibit = state->initialAnyPolicyInhibit;
+ initialIsAnyPolicy = state->initialIsAnyPolicy;
+ policyQualifiersRejected = state->policyQualifiersRejected;
+ certPoliciesCritical = state->certPoliciesCritical;
+
+ if (initialPolicyMappingInhibit || initialExplicitPolicy ||
+ initialAnyPolicyInhibit || initialIsAnyPolicy ||
+ policyQualifiersRejected || certPoliciesCritical) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "TRUE", 0, &trueString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+ if (!initialPolicyMappingInhibit || !initialExplicitPolicy ||
+ !initialAnyPolicyInhibit || !initialIsAnyPolicy ||
+ !policyQualifiersRejected || !certPoliciesCritical) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "FALSE", 0, &falseString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+ if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(null)", 0, &nullString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ PKIX_TOSTRING
+ (state->certPoliciesExtension, &policiesExtOIDString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->policyMappingsExtension,
+ &policyMapOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->policyConstraintsExtension,
+ &policyConstrOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->inhibitAnyPolicyExtension,
+ &inhAnyPolOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->userInitialPolicySet,
+ &userInitialPolicySetString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->mappedUserInitialPolicySet,
+ &mappedUserPolicySetString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ if (state->anyPolicyNodeAtBottom) {
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (state->anyPolicyNodeAtBottom,
+ &anyAtBottomString,
+ plContext),
+ PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
+ } else {
+ PKIX_INCREF(nullString);
+ anyAtBottomString = nullString;
+ }
+
+ if (state->newAnyPolicyNode) {
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (state->newAnyPolicyNode,
+ &newAnyPolicyString,
+ plContext),
+ PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
+ } else {
+ PKIX_INCREF(nullString);
+ newAnyPolicyString = nullString;
+ }
+
+ PKIX_TOSTRING
+ (state->mappedPolicyOIDs,
+ &mappedPolicyOIDsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ formatString,
+ policiesExtOIDString,
+ policyMapOIDString,
+ policyConstrOIDString,
+ inhAnyPolOIDString,
+ anyPolicyOIDString,
+ initialIsAnyPolicy?trueString:falseString,
+ validPolicyTreeString,
+ userInitialPolicySetString,
+ mappedUserPolicySetString,
+ policyQualifiersRejected?trueString:falseString,
+ initialPolicyMappingInhibit?trueString:falseString,
+ initialExplicitPolicy?trueString:falseString,
+ initialAnyPolicyInhibit?trueString:falseString,
+ state->explicitPolicy,
+ state->inhibitAnyPolicy,
+ state->policyMapping,
+ state->numCerts,
+ state->certsProcessed,
+ anyAtBottomString,
+ newAnyPolicyString,
+ certPoliciesCritical?trueString:falseString,
+ mappedPolicyOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pCheckerStateString = resultString;
+
+cleanup:
+ PKIX_DECREF(policiesExtOIDString);
+ PKIX_DECREF(policyMapOIDString);
+ PKIX_DECREF(policyConstrOIDString);
+ PKIX_DECREF(inhAnyPolOIDString);
+ PKIX_DECREF(anyPolicyOIDString);
+ PKIX_DECREF(validPolicyTreeString);
+ PKIX_DECREF(userInitialPolicySetString);
+ PKIX_DECREF(mappedUserPolicySetString);
+ PKIX_DECREF(anyAtBottomString);
+ PKIX_DECREF(newAnyPolicyString);
+ PKIX_DECREF(mappedPolicyOIDsString);
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(trueString);
+ PKIX_DECREF(falseString);
+ PKIX_DECREF(nullString);
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyCheckerState_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * 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_PolicyCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER
+ (CERTPOLICYCHECKERSTATE,
+ "pkix_PolicyCheckerState_RegisterSelf");
+
+ entry.description = "PolicyCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState);
+ entry.destructor = pkix_PolicyCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = pkix_PolicyCheckerState_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION:pkix_PolicyCheckerState_Create
+ * DESCRIPTION:
+ *
+ * Creates a PolicyCheckerState Object, using the List pointed to
+ * by "initialPolicies" for the user-initial-policy-set, the Boolean value
+ * of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
+ * the Boolean value of "initialPolicyMappingInhibit" for the
+ * inhibitPolicyMappings parameter, the Boolean value of
+ * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
+ * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
+ * parameter, and the UInt32 value of "numCerts" as the number of
+ * certificates in the chain; and stores the Object at "pCheckerState".
+ *
+ * PARAMETERS:
+ * "initialPolicies"
+ * Address of List of OIDs comprising the user-initial-policy-set; the List
+ * may be empty, but must be non-NULL
+ * "policyQualifiersRejected"
+ * Boolean value of the policyQualifiersRejected parameter
+ * "initialPolicyMappingInhibit"
+ * Boolean value of the inhibitPolicyMappings parameter
+ * "initialExplicitPolicy"
+ * Boolean value of the initialExplicitPolicy parameter
+ * "initialAnyPolicyInhibit"
+ * Boolean value of the inhibitAnyPolicy parameter
+ * "numCerts"
+ * Number of certificates in the chain to be validated
+ * "pCheckerState"
+ * Address where PolicyCheckerState 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 CertPolicyCheckerState Error if the functions fails in a
+ * non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_Create(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_PolicyCheckerState **pCheckerState,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *checkerState = NULL;
+ PKIX_PolicyNode *policyNode = NULL;
+ PKIX_List *anyPolicyList = NULL;
+ PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create");
+ PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYCHECKERSTATE_TYPE,
+ sizeof (PKIX_PolicyCheckerState),
+ (PKIX_PL_Object **)&checkerState,
+ plContext),
+ PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT);
+
+ /* Create constant PKIX_PL_OIDs: */
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTIFICATEPOLICIES_OID,
+ &(checkerState->certPoliciesExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_POLICYMAPPINGS_OID,
+ &(checkerState->policyMappingsExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_POLICYCONSTRAINTS_OID,
+ &(checkerState->policyConstraintsExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_INHIBITANYPOLICY_OID,
+ &(checkerState->inhibitAnyPolicyExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID,
+ &(checkerState->anyPolicyOID),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* Create an initial policy set from argument supplied */
+ PKIX_INCREF(initialPolicies);
+ checkerState->userInitialPolicySet = initialPolicies;
+ PKIX_INCREF(initialPolicies);
+ checkerState->mappedUserInitialPolicySet = initialPolicies;
+
+ PKIX_CHECK(PKIX_List_IsEmpty
+ (initialPolicies,
+ &initialPoliciesIsEmpty,
+ plContext),
+ PKIX_LISTISEMPTYFAILED);
+ if (initialPoliciesIsEmpty) {
+ checkerState->initialIsAnyPolicy = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(pkix_List_Contains
+ (initialPolicies,
+ (PKIX_PL_Object *)(checkerState->anyPolicyOID),
+ &(checkerState->initialIsAnyPolicy),
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+
+ checkerState->policyQualifiersRejected =
+ policyQualifiersRejected;
+ checkerState->initialExplicitPolicy = initialExplicitPolicy;
+ checkerState->explicitPolicy =
+ (initialExplicitPolicy? 0: numCerts + 1);
+ checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit;
+ checkerState->inhibitAnyPolicy =
+ (initialAnyPolicyInhibit? 0: numCerts + 1);
+ checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit;
+ checkerState->policyMapping =
+ (initialPolicyMappingInhibit? 0: numCerts + 1);
+ ;
+ checkerState->numCerts = numCerts;
+ checkerState->certsProcessed = 0;
+ checkerState->certPoliciesCritical = PKIX_FALSE;
+
+ /* Create a valid_policy_tree as in RFC3280 6.1.2(a) */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)(checkerState->anyPolicyOID),
+ PKIX_TRUE,
+ &anyPolicyList,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (checkerState->anyPolicyOID, /* validPolicy */
+ NULL, /* qualifier set */
+ PKIX_FALSE, /* criticality */
+ anyPolicyList, /* expectedPolicySet */
+ &policyNode,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+ checkerState->validPolicyTree = policyNode;
+
+ /*
+ * Since the initial validPolicyTree specifies
+ * ANY_POLICY, begin with a pointer to the root node.
+ */
+ PKIX_INCREF(policyNode);
+ checkerState->anyPolicyNodeAtBottom = policyNode;
+
+ checkerState->newAnyPolicyNode = NULL;
+
+ checkerState->mappedPolicyOIDs = NULL;
+
+ *pCheckerState = checkerState;
+ checkerState = NULL;
+
+cleanup:
+
+ PKIX_DECREF(checkerState);
+
+ PKIX_DECREF(anyPolicyList);
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/* --Private-PolicyChecker-Functions--------------------------------------- */
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapContains
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to
+ * determine whether the OID pointed to by "policy" is among the
+ * issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and
+ * stores the result in "pFound".
+ *
+ * This function is intended to allow an efficient check that the proscription
+ * against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is
+ * not violated.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty, but
+ * must be non-NULL
+ * "policy"
+ * Address of OID to be checked for. Must be non-NULL
+ * "pFound"
+ * Address where the result of the search 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_PolicyChecker_MapContains(
+ PKIX_List *certPolicyMaps,
+ PKIX_PL_OID *policy,
+ PKIX_Boolean *pFound,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+ PKIX_PL_OID *subjectDomainPolicy = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains");
+ PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound);
+
+ PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; (!match) && (index < numEntries); index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, issuerDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!match) {
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ (map, &subjectDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, subjectDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ }
+
+ *pFound = match;
+
+cleanup:
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create
+ * a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the
+ * policy pointed to by "policy", and stores the result in
+ * "pSubjectDomainPolicies".
+ *
+ * If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the
+ * resulting List will be NULL. If there are CertPolicyMaps, but none that
+ * include "policy" as an IssuerDomainPolicy, the returned List pointer will
+ * be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies
+ * of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a
+ * List is returned it will be immutable.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty or NULL.
+ * "policy"
+ * Address of OID to be checked for. Must be non-NULL
+ * "pSubjectDomainPolicies"
+ * Address where the result of the search 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_PolicyChecker_MapGetSubjectDomainPolicies(
+ PKIX_List *certPolicyMaps,
+ PKIX_PL_OID *policy,
+ PKIX_List **pSubjectDomainPolicies,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_List *subjectList = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+ PKIX_PL_OID *subjectDomainPolicy = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_MapGetSubjectDomainPolicies");
+ PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies);
+
+ if (certPolicyMaps) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyMaps,
+ &numEntries,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, issuerDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (match) {
+ if (!subjectList) {
+ PKIX_CHECK(PKIX_List_Create(&subjectList, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ (map, &subjectDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (subjectList,
+ (PKIX_PL_Object *)subjectDomainPolicy,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ }
+
+ if (subjectList) {
+ PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ *pSubjectDomainPolicies = subjectList;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(subjectList);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a
+ * List of all IssuerDomainPolicies, and stores the result in
+ * "pMappedPolicies".
+ *
+ * The caller may not rely on the IssuerDomainPolicies to be in any particular
+ * order. IssuerDomainPolicies that appear in more than one CertPolicyMap will
+ * only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the
+ * result will be an empty List. The created List is mutable.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty, but
+ * must be non-NULL.
+ * "pMappedPolicies"
+ * Address where the result 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 functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_MapGetMappedPolicies(
+ PKIX_List *certPolicyMaps,
+ PKIX_List **pMappedPolicies,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_List *mappedList = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies");
+ PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies);
+
+ PKIX_CHECK(PKIX_List_Create(&mappedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (mappedList,
+ (PKIX_PL_Object *)issuerDomainPolicy,
+ &isContained,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isContained == PKIX_FALSE) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (mappedList,
+ (PKIX_PL_Object *)issuerDomainPolicy,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ }
+
+ *pMappedPolicies = mappedList;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(mappedList);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MakeMutableCopy
+ * DESCRIPTION:
+ *
+ * Creates a mutable copy of the List pointed to by "list", which may or may
+ * not be immutable, and stores the address at "pMutableCopy".
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to be copied. Must be non-NULL.
+ * "pMutableCopy"
+ * Address where mutable copy 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 functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_MakeMutableCopy(
+ PKIX_List *list,
+ PKIX_List **pMutableCopy,
+ void *plContext)
+{
+ PKIX_List *newList = NULL;
+ PKIX_UInt32 listLen = 0;
+ PKIX_UInt32 listIx = 0;
+ PKIX_PL_Object *object = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy");
+ PKIX_NULLCHECK_TWO(list, pMutableCopy);
+
+ PKIX_CHECK(PKIX_List_Create(&newList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (listIx = 0; listIx < listLen; listIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(object);
+ }
+
+ *pMutableCopy = newList;
+ newList = NULL;
+
+cleanup:
+ PKIX_DECREF(newList);
+ PKIX_DECREF(object);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MakeSingleton
+ * DESCRIPTION:
+ *
+ * Creates a new List containing the Object pointed to by "listItem", using
+ * the Boolean value of "immutability" to determine whether to set the List
+ * immutable, and stores the address at "pList".
+ *
+ * PARAMETERS:
+ * "listItem"
+ * Address of Object to be inserted into the new List. Must be non-NULL.
+ * "immutability"
+ * Boolean value indicating whether new List is to be immutable
+ * "pList"
+ * Address where List 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 functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_MakeSingleton(
+ PKIX_PL_Object *listItem,
+ PKIX_Boolean immutability,
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *newList = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton");
+ PKIX_NULLCHECK_TWO(listItem, pList);
+
+ PKIX_CHECK(PKIX_List_Create(&newList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (newList, (PKIX_PL_Object *)listItem, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (immutability) {
+ PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ *pList = newList;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(newList);
+ }
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Spawn
+ * DESCRIPTION:
+ *
+ * Creates a new childNode for the parent pointed to by "parent", using
+ * the OID pointed to by "policyOID", the List of CertPolicyQualifiers
+ * pointed to by "qualifiers", the List of OIDs pointed to by
+ * "subjectDomainPolicies", and the PolicyCheckerState pointed to by
+ * "state". The new node will be added to "parent".
+ *
+ * The validPolicy of the new node is set from the OID pointed to by
+ * "policyOID". The policy qualifiers for the new node is set from the
+ * List of qualifiers pointed to by "qualifiers", and may be NULL or
+ * empty if the argument provided was NULL or empty. The criticality is
+ * set according to the criticality obtained from the PolicyCheckerState.
+ * If "subjectDomainPolicies" is NULL, the expectedPolicySet of the
+ * child is set to contain the same policy as the validPolicy. If
+ * "subjectDomainPolicies" is not NULL, it is used as the value for
+ * the expectedPolicySet.
+ *
+ * The PolicyCheckerState also contains a constant, anyPolicy, which is
+ * compared to "policyOID". If they match, the address of the childNode
+ * is saved in the state's newAnyPolicyNode.
+ *
+ * PARAMETERS:
+ * "parent"
+ * Address of PolicyNode to which the child will be linked. Must be
+ * non-NULL.
+ * "policyOID"
+ * Address of OID of the new child's validPolicy and also, if
+ * subjectDomainPolicies is NULL, of the new child's expectedPolicySet.
+ * Must be non-NULL.
+ * "qualifiers"
+ * Address of List of CertPolicyQualifiers. May be NULL or empty.
+ * "subjectDomainPolicies"
+ * Address of List of OIDs indicating the policies to which "policy" is
+ * mapped. May be empty or NULL.
+ * "state"
+ * Address of the current PKIX_PolicyCheckerState. Must be non-NULL..
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_Spawn(
+ PKIX_PolicyNode *parent,
+ PKIX_PL_OID *policyOID,
+ PKIX_List *qualifiers, /* CertPolicyQualifiers */
+ PKIX_List *subjectDomainPolicies,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_List *expectedSet = NULL; /* OIDs */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn");
+ PKIX_NULLCHECK_THREE(policyOID, parent, state);
+
+ if (subjectDomainPolicies) {
+
+ PKIX_INCREF(subjectDomainPolicies);
+ expectedSet = subjectDomainPolicies;
+
+ } else {
+ /* Create the child's ExpectedPolicy Set */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)policyOID,
+ PKIX_TRUE, /* make expectedPolicySet immutable */
+ &expectedSet,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+ }
+
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (policyOID,
+ qualifiers,
+ state->certPoliciesCritical,
+ expectedSet,
+ &childNode,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+
+ /*
+ * If we had a non-empty mapping, we know the new node could not
+ * have been created with a validPolicy of anyPolicy. Otherwise,
+ * check whether we just created a new node with anyPolicy, because
+ * in that case we want to save the child pointer in newAnyPolicyNode.
+ */
+ if (!subjectDomainPolicies) {
+ PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (match) {
+ PKIX_DECREF(state->newAnyPolicyNode);
+ PKIX_INCREF(childNode);
+ state->newAnyPolicyNode = childNode;
+ }
+ }
+
+ PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext),
+ PKIX_POLICYNODEADDTOPARENTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedSet);
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive
+ * DESCRIPTION:
+ *
+ * Performs policy processing for the policy whose OID is pointed to by
+ * "policyOID" and whose List of CertPolicyQualifiers is pointed to by
+ * "policyQualifiers", using the List of policy OIDs pointed to by
+ * "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode",
+ * in accordance with the current PolicyCheckerState pointed to by "state",
+ * and setting "pChildNodeCreated" to TRUE if a new childNode is created.
+ * Note: "pChildNodeCreated" is not set to FALSE if no childNode is created.
+ * The intent of the design is that the caller can set a variable to FALSE
+ * initially, prior to a recursive set of calls. At the end, the variable
+ * can be tested to see whether *any* of the calls created a child node.
+ *
+ * If the currentNode is not at the bottom of the tree, this function
+ * calls itself recursively for each child of currentNode. At the bottom of
+ * the tree, it creates new child nodes as appropriate. This function will
+ * never be called with policy = anyPolicy.
+ *
+ * This function implements the processing described in RFC3280
+ * Section 6.1.3(d)(1)(i).
+ *
+ * PARAMETERS:
+ * "policyOID"
+ * Address of OID of the policy to be checked for. Must be non-NULL.
+ * "policyQualifiers"
+ * Address of List of CertPolicyQualifiers of the policy to be checked for.
+ * May be empty or NULL.
+ * "subjectDomainPolicies"
+ * Address of List of OIDs indicating the policies to which "policy" is
+ * mapped. May be empty or NULL.
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be checked, if not at the
+ * bottom of the tree; or whose expectedPolicySet will be compared to
+ * "policy", if at the bottom. Must be non-NULL.
+ * "state"
+ * Address of PolicyCheckerState of the current PolicyChecker. Must be
+ * non-NULL.
+ * "pChildNodeCreated"
+ * Address of the Boolean that will be set TRUE if this function
+ * creates a child node. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckPolicyRecursive(
+ PKIX_PL_OID *policyOID,
+ PKIX_List *policyQualifiers,
+ PKIX_List *subjectDomainPolicies,
+ PKIX_PolicyNode *currentNode,
+ PKIX_PolicyCheckerState *state,
+ PKIX_Boolean *pChildNodeCreated,
+ void *plContext)
+{
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIx = 0;
+ PKIX_Boolean isIncluded = PKIX_FALSE;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_List *expectedPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_CheckPolicyRecursive");
+ PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated);
+
+ /* if not at the bottom of the tree */
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ if (depth < (state->certsProcessed)) {
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIx = 0; childIx < numChildren; childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
+ (policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ childNode,
+ state,
+ pChildNodeCreated,
+ plContext),
+ PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
+
+ PKIX_DECREF(childNode);
+ }
+ } else { /* if at the bottom of the tree */
+
+ /* Check whether policy is in this node's expectedPolicySet */
+ PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
+ (currentNode, &expectedPolicies, plContext),
+ PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
+
+ PKIX_NULLCHECK_ONE(expectedPolicies);
+
+ PKIX_CHECK(pkix_List_Contains
+ (expectedPolicies,
+ (PKIX_PL_Object *)policyOID,
+ &isIncluded,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isIncluded) {
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (currentNode,
+ policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ *pChildNodeCreated = PKIX_TRUE;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(children);
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckPolicy
+ * DESCRIPTION:
+ *
+ * Performs the non-recursive portion of the policy processing for the policy
+ * whose OID is pointed to by "policyOID" and whose List of
+ * CertPolicyQualifiers is pointed to by "policyQualifiers", for the
+ * Certificate pointed to by "cert" with the List of CertPolicyMaps pointed
+ * to by "maps", in accordance with the current PolicyCheckerState pointed
+ * to by "state".
+ *
+ * This function implements the processing described in RFC3280
+ * Section 6.1.3(d)(1)(i).
+ *
+ * PARAMETERS:
+ * "policyOID"
+ * Address of OID of the policy to be checked for. Must be non-NULL.
+ * "policyQualifiers"
+ * Address of List of CertPolicyQualifiers of the policy to be checked for.
+ * May be empty or NULL.
+ * "cert"
+ * Address of the current certificate. Must be non-NULL.
+ * "maps"
+ * Address of List of CertPolicyMaps for the current certificate
+ * "state"
+ * Address of PolicyCheckerState of the current PolicyChecker. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckPolicy(
+ PKIX_PL_OID *policyOID,
+ PKIX_List *policyQualifiers,
+ PKIX_PL_Cert *cert,
+ PKIX_List *maps,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_Boolean childNodeCreated = PKIX_FALSE;
+ PKIX_Boolean okToSpawn = PKIX_FALSE;
+ PKIX_Boolean found = PKIX_FALSE;
+ PKIX_List *subjectDomainPolicies = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy");
+ PKIX_NULLCHECK_THREE(policyOID, cert, state);
+
+ /*
+ * If this is not the last certificate, get the set of
+ * subjectDomainPolicies that "policy" maps to, according to the
+ * current cert's policy mapping extension. That set will be NULL
+ * if the current cert does not have a policy mapping extension,
+ * or if the current policy is not mapped.
+ */
+ if (state->certsProcessed != (state->numCerts - 1)) {
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (maps, policyOID, &subjectDomainPolicies, plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+ }
+
+ /*
+ * Section 6.1.4(b)(2) tells us that if policyMapping is zero, we
+ * will have to delete any nodes created with validPolicies equal to
+ * policies that appear as issuerDomainPolicies in a policy mapping
+ * extension. Let's avoid creating any such nodes.
+ */
+ if ((state->policyMapping) == 0) {
+ if (subjectDomainPolicies) {
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
+ (policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state->validPolicyTree,
+ state,
+ &childNodeCreated,
+ plContext),
+ PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
+
+ if (!childNodeCreated) {
+ /*
+ * Section 6.1.3(d)(1)(ii)
+ * There was no match. If there was a node at
+ * depth i-1 with valid policy anyPolicy,
+ * generate a node subordinate to that.
+ *
+ * But that means this created node would be in
+ * the valid-policy-node-set, and will be
+ * pruned in 6.1.5(g)(iii)(2) unless it is in
+ * the user-initial-policy-set or the user-
+ * initial-policy-set is {anyPolicy}. So check,
+ * and don't create it if it will be pruned.
+ */
+ if (state->anyPolicyNodeAtBottom) {
+ if (state->initialIsAnyPolicy) {
+ okToSpawn = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(pkix_List_Contains
+ (state->mappedUserInitialPolicySet,
+ (PKIX_PL_Object *)policyOID,
+ &okToSpawn,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+ if (okToSpawn) {
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (state->anyPolicyNodeAtBottom,
+ policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+ childNodeCreated = PKIX_TRUE;
+ }
+ }
+ }
+
+ if (childNodeCreated) {
+ /*
+ * If this policy had qualifiers, and the certificate policies
+ * extension was marked critical, and the user cannot deal with
+ * policy qualifiers, throw an error.
+ */
+ if (policyQualifiers &&
+ state->certPoliciesCritical &&
+ state->policyQualifiersRejected) {
+ PKIX_ERROR
+ (PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION);
+ }
+ /*
+ * If the policy we just propagated was in the list of mapped
+ * policies, remove it from the list. That list is used, at the
+ * end, to determine policies that have not been propagated.
+ */
+ if (state->mappedPolicyOIDs) {
+ PKIX_CHECK(pkix_List_Contains
+ (state->mappedPolicyOIDs,
+ (PKIX_PL_Object *)policyOID,
+ &found,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ if (found) {
+ PKIX_CHECK(pkix_List_Remove
+ (state->mappedPolicyOIDs,
+ (PKIX_PL_Object *)policyOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckAny
+ * DESCRIPTION:
+ * Performs the creation of PolicyNodes, for the PolicyNode pointed to by
+ * "currentNode" and PolicyNodes subordinate to it, using the List of
+ * qualifiers pointed to by "qualsOfAny", in accordance with the current
+ * certificate's PolicyMaps pointed to by "policyMaps" and the current
+ * PolicyCheckerState pointed to by "state".
+ *
+ * If the currentNode is not just above the bottom of the validPolicyTree, this
+ * function calls itself recursively for each child of currentNode. At the
+ * level just above the bottom, for each policy in the currentNode's
+ * expectedPolicySet not already present in a child node, it creates a new
+ * child node. The validPolicy of the child created, and its expectedPolicySet,
+ * will be the policy from the currentNode's expectedPolicySet. The policy
+ * qualifiers will be the qualifiers from the current certificate's anyPolicy,
+ * the "qualsOfAny" parameter. If the currentNode's expectedSet includes
+ * anyPolicy, a childNode will be created with a policy of anyPolicy. This is
+ * the only way such a node can be created.
+ *
+ * This function is called only when anyPolicy is one of the current
+ * certificate's policies. This function implements the processing described
+ * in RFC3280 Section 6.1.3(d)(2).
+ *
+ * PARAMETERS:
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be checked, if not at the
+ * bottom of the tree; or whose expectedPolicySet will be compared to those
+ * in "alreadyPresent", if at the bottom. Must be non-NULL.
+ * "qualsOfAny"
+ * Address of List of qualifiers of the anyPolicy in the current
+ * certificate. May be empty or NULL.
+ * "policyMaps"
+ * Address of the List of PolicyMaps of the current certificate. May be
+ * empty or NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckAny(
+ PKIX_PolicyNode *currentNode,
+ PKIX_List *qualsOfAny, /* CertPolicyQualifiers */
+ PKIX_List *policyMaps, /* CertPolicyMaps */
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIx = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polx = 0;
+ PKIX_Boolean isIncluded = PKIX_FALSE;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_List *expectedPolicies = NULL; /* OIDs */
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_PL_OID *childPolicy = NULL;
+ PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny");
+ PKIX_NULLCHECK_TWO(currentNode, state);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (depth < (state->certsProcessed)) {
+ for (childIx = 0; childIx < numChildren; childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(childNode);
+ PKIX_CHECK(pkix_PolicyChecker_CheckAny
+ (childNode,
+ qualsOfAny,
+ policyMaps,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERCHECKANYFAILED);
+
+ PKIX_DECREF(childNode);
+ }
+ } else { /* if at the bottom of the tree */
+
+ PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
+ (currentNode, &expectedPolicies, plContext),
+ PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
+
+ /* Expected Policy Set is not allowed to be NULL */
+ PKIX_NULLCHECK_ONE(expectedPolicies);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (expectedPolicies, &numPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polx = 0; polx < numPolicies; polx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (expectedPolicies,
+ polx,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(policyOID);
+
+ isIncluded = PKIX_FALSE;
+
+ for (childIx = 0;
+ (!isIncluded && (childIx < numChildren));
+ childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(childNode);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (childNode, &childPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_ONE(childPolicy);
+
+ PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childPolicy);
+ }
+
+ if (!isIncluded) {
+ if (policyMaps) {
+ PKIX_CHECK
+ (pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+ }
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (currentNode,
+ policyOID,
+ qualsOfAny,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+ PKIX_DECREF(subjectDomainPolicies);
+ }
+
+ PKIX_DECREF(policyOID);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(children);
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedPolicies);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(childPolicy);
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CalculateIntersection
+ * DESCRIPTION:
+ *
+ * Processes the PolicyNode pointed to by "currentNode", and its descendants,
+ * using the PolicyCheckerState pointed to by "state", using the List at
+ * the address pointed to by "nominees" the OIDs of policies that are in the
+ * user-initial-policy-set but are not represented among the nodes at the
+ * bottom of the tree, and storing at "pShouldBePruned" the value TRUE if
+ * currentNode is childless at the end of this processing, FALSE if it has
+ * children or is at the bottom of the tree.
+ *
+ * When this function is called at the top level, "nominees" should be the List
+ * of all policies in the user-initial-policy-set. Policies that are
+ * represented in the valid-policy-node-set are removed from this List. As a
+ * result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will
+ * be created for each policy remaining in this List.
+ *
+ * This function implements the calculation of the intersection of the
+ * validPolicyTree with the user-initial-policy-set, as described in
+ * RFC 3280 6.1.5(g)(iii).
+ *
+ * PARAMETERS:
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be processed as described.
+ * Must be non-NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker. Must be non-NULL
+ * "nominees"
+ * Address of List of the OIDs for which nodes should be created to replace
+ * anyPolicy nodes. Must be non-NULL but may be empty.
+ * "pShouldBePruned"
+ * Address where Boolean return value, set to TRUE if this PolicyNode
+ * should be deleted, is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CalculateIntersection(
+ PKIX_PolicyNode *currentNode,
+ PKIX_PolicyCheckerState *state,
+ PKIX_List *nominees, /* OIDs */
+ PKIX_Boolean *pShouldBePruned,
+ void *plContext)
+{
+ PKIX_Boolean currentPolicyIsAny = PKIX_FALSE;
+ PKIX_Boolean parentPolicyIsAny = PKIX_FALSE;
+ PKIX_Boolean currentPolicyIsValid = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_Boolean priorCriticality = PKIX_FALSE;
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_UInt32 numNominees = 0;
+ PKIX_UInt32 polIx = 0;
+ PKIX_PL_OID *currentPolicy = NULL;
+ PKIX_PL_OID *parentPolicy = NULL;
+ PKIX_PL_OID *substPolicy = NULL;
+ PKIX_PolicyNode *parent = NULL;
+ PKIX_PolicyNode *child = NULL;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_List *policyQualifiers = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_CalculateIntersection");
+
+ /*
+ * We call this function if the valid_policy_tree is not NULL and
+ * the user-initial-policy-set is not any-policy.
+ */
+ if (!state->validPolicyTree || state->initialIsAnyPolicy) {
+ PKIX_ERROR(PKIX_PRECONDITIONFAILED);
+ }
+
+ PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (currentNode, &currentPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ currentPolicy,
+ &currentPolicyIsAny,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext),
+ PKIX_POLICYNODEGETPARENTFAILED);
+
+ if (currentPolicyIsAny == PKIX_FALSE) {
+
+ /*
+ * If we are at the top of the tree, or if our
+ * parent's validPolicy is anyPolicy, we are in
+ * the valid policy node set.
+ */
+ if (parent) {
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (parent, &parentPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_ONE(parentPolicy);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ parentPolicy,
+ &parentPolicyIsAny,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ /*
+ * Section 6.1.5(g)(iii)(2)
+ * If this node's policy is not in the user-initial-policy-set,
+ * it is not in the intersection. Prune it.
+ */
+ if (!parent || parentPolicyIsAny) {
+ PKIX_CHECK(pkix_List_Contains
+ (state->userInitialPolicySet,
+ (PKIX_PL_Object *)currentPolicy,
+ &currentPolicyIsValid,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ if (!currentPolicyIsValid) {
+ *pShouldBePruned = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If this node's policy is in the user-initial-policy-
+ * set, it will propagate that policy into the next
+ * level of the tree. Remove the policy from the list
+ * of policies that an anyPolicy will spawn.
+ */
+ PKIX_CHECK(pkix_List_Remove
+ (nominees,
+ (PKIX_PL_Object *)currentPolicy,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+
+
+ /* Are we at the bottom of the tree? */
+
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ if (depth == (state->numCerts)) {
+ /*
+ * Section 6.1.5(g)(iii)(3)
+ * Replace anyPolicy nodes...
+ */
+ if (currentPolicyIsAny == PKIX_TRUE) {
+
+ /* replace this node */
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (nominees, &numNominees, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numNominees) {
+
+ PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers
+ (currentNode,
+ &policyQualifiers,
+ plContext),
+ PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED);
+
+ PKIX_CHECK(PKIX_PolicyNode_IsCritical
+ (currentNode, &priorCriticality, plContext),
+ PKIX_POLICYNODEISCRITICALFAILED);
+ }
+
+ PKIX_NULLCHECK_ONE(parent);
+
+ for (polIx = 0; polIx < numNominees; polIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (nominees,
+ polIx,
+ (PKIX_PL_Object **)&substPolicy,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (parent,
+ substPolicy,
+ policyQualifiers,
+ NULL,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ PKIX_DECREF(substPolicy);
+
+ }
+ /* remove currentNode from parent */
+ *pShouldBePruned = PKIX_TRUE;
+ /*
+ * We can get away with augmenting the parent's List
+ * of children because we started at the end and went
+ * toward the beginning. New nodes are added at the end.
+ */
+ }
+ } else {
+ /*
+ * Section 6.1.5(g)(iii)(4)
+ * Prune any childless nodes above the bottom level
+ */
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ /* CurrentNode should have been pruned if childless. */
+ PKIX_NULLCHECK_ONE(children);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (childIndex = numChildren; childIndex > 0; childIndex--) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex - 1,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
+ (child, state, nominees, &shouldBePruned, plContext),
+ PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
+
+ if (PKIX_TRUE == shouldBePruned) {
+
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (children, childIndex - 1, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_DECREF(child);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numChildren == 0) {
+ *pShouldBePruned = PKIX_TRUE;
+ }
+ }
+cleanup:
+ PKIX_DECREF(currentPolicy);
+ PKIX_DECREF(parentPolicy);
+ PKIX_DECREF(substPolicy);
+ PKIX_DECREF(parent);
+ PKIX_DECREF(child);
+ PKIX_DECREF(children);
+ PKIX_DECREF(policyQualifiers);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_PolicyMapProcessing
+ * DESCRIPTION:
+ *
+ * Performs the processing of Policies in the List of CertPolicyMaps pointed
+ * to by "policyMaps", using and updating the PolicyCheckerState pointed to by
+ * "state".
+ *
+ * This function implements the policyMap processing described in RFC3280
+ * Section 6.1.4(b)(1), after certificate i has been processed, in preparation
+ * for certificate i+1. Section references are to that document.
+ *
+ * PARAMETERS:
+ * "policyMaps"
+ * Address of the List of CertPolicyMaps presented by certificate i.
+ * Must be non-NULL.
+ * "certPoliciesIncludeAny"
+ * Boolean value which is PKIX_TRUE if the current certificate asserts
+ * anyPolicy, PKIX_FALSE otherwise.
+ * "qualsOfAny"
+ * Address of List of qualifiers of the anyPolicy in the current
+ * certificate. May be empty or NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_PolicyMapProcessing(
+ PKIX_List *policyMaps, /* CertPolicyMaps */
+ PKIX_Boolean certPoliciesIncludeAny,
+ PKIX_List *qualsOfAny,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polX = 0;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *newMappedPolicies = NULL; /* OIDs */
+ PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_PolicyMapProcessing");
+ PKIX_NULLCHECK_THREE
+ (policyMaps,
+ state,
+ state->mappedUserInitialPolicySet);
+
+ /*
+ * For each policy in mappedUserInitialPolicySet, if it is not mapped,
+ * append it to new policySet; if it is mapped, append its
+ * subjectDomainPolicies to new policySet. When done, this new
+ * policySet will replace mappedUserInitialPolicySet.
+ */
+ PKIX_CHECK(PKIX_List_Create
+ (&newMappedPolicies, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->mappedUserInitialPolicySet,
+ &numPolicies,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->mappedUserInitialPolicySet,
+ polX,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+
+ if (subjectDomainPolicies) {
+
+ PKIX_CHECK(pkix_List_AppendUnique
+ (newMappedPolicies,
+ subjectDomainPolicies,
+ plContext),
+ PKIX_LISTAPPENDUNIQUEFAILED);
+
+ PKIX_DECREF(subjectDomainPolicies);
+
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (newMappedPolicies,
+ (PKIX_PL_Object *)policyOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(policyOID);
+ }
+
+ /*
+ * For each policy ID-P remaining in mappedPolicyOIDs, it has not been
+ * propagated to the bottom of the tree (depth i). If policyMapping
+ * is greater than zero and this cert contains anyPolicy and the tree
+ * contains an anyPolicy node at depth i-1, then we must create a node
+ * with validPolicy ID-P, the policy qualifiers of anyPolicy in
+ * this certificate, and expectedPolicySet the subjectDomainPolicies
+ * that ID-P maps to. We also then add those subjectDomainPolicies to
+ * the list of policies that will be accepted in the next certificate,
+ * the mappedUserInitialPolicySet.
+ */
+
+ if ((state->policyMapping > 0) && (certPoliciesIncludeAny) &&
+ (state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->mappedPolicyOIDs,
+ &numPolicies,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->mappedPolicyOIDs,
+ polX,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (state->anyPolicyNodeAtBottom,
+ policyOID,
+ qualsOfAny,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ PKIX_CHECK(pkix_List_AppendUnique
+ (newMappedPolicies,
+ subjectDomainPolicies,
+ plContext),
+ PKIX_LISTAPPENDUNIQUEFAILED);
+
+ PKIX_DECREF(subjectDomainPolicies);
+ PKIX_DECREF(policyOID);
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_DECREF(state->mappedUserInitialPolicySet);
+ PKIX_INCREF(newMappedPolicies);
+
+ state->mappedUserInitialPolicySet = newMappedPolicies;
+
+cleanup:
+
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(newMappedPolicies);
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_WrapUpProcessing
+ * DESCRIPTION:
+ *
+ * Performs the wrap-up processing for the Cert pointed to by "cert",
+ * using and updating the PolicyCheckerState pointed to by "state".
+ *
+ * This function implements the wrap-up processing described in RFC3280
+ * Section 6.1.5, after the final certificate has been processed. Section
+ * references in the comments are to that document.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the current (presumably the end entity) certificate.
+ * Must be non-NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_WrapUpProcessing(
+ PKIX_PL_Cert *cert,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_List *nominees = NULL; /* OIDs */
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_UInt32 length;
+#endif
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_WrapUpProcessing");
+ PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG("%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+ /* Section 6.1.5(a) ... */
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (!isSelfIssued) {
+ if (state->explicitPolicy > 0) {
+
+ state->explicitPolicy--;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+ }
+
+ /* Section 6.1.5(b) ... */
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &explicitPolicySkipCerts, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ if (explicitPolicySkipCerts == 0) {
+ state->explicitPolicy = 0;
+ }
+
+ /* Section 6.1.5(g)(i) ... */
+
+ if (!(state->validPolicyTree)) {
+ goto cleanup;
+ }
+
+ /* Section 6.1.5(g)(ii) ... */
+
+ if (state->initialIsAnyPolicy) {
+ goto cleanup;
+ }
+
+ /*
+ * Section 6.1.5(g)(iii) ...
+ * Create a list of policies which could be substituted for anyPolicy.
+ * Start with a (mutable) copy of user-initial-policy-set.
+ */
+ PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy
+ (state->userInitialPolicySet, &nominees, plContext),
+ PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
+ (state->validPolicyTree, /* node at top of tree */
+ state,
+ nominees,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
+
+ if (PKIX_TRUE == shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ }
+
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state->validPolicyTree, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG
+ ("After CalculateIntersection:\n%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+ } else {
+ PKIX_DEBUG("validPolicyTree is NULL\n");
+ }
+#endif
+
+ /* Section 6.1.5(g)(iii)(4) ... */
+
+ if (state->validPolicyTree) {
+
+ PKIX_CHECK(pkix_PolicyNode_Prune
+ (state->validPolicyTree,
+ state->numCerts,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYNODEPRUNEFAILED);
+
+ if (shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ }
+ }
+
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state->validPolicyTree, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+cleanup:
+
+ PKIX_DECREF(nominees);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Check
+ * (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback)
+ *
+ * Labels referring to sections, such as "Section 6.1.3(d)", refer to
+ * sections of RFC3280, Section 6.1.3 Basic Certificate Processing.
+ *
+ * If a non-fatal error occurs, it is unlikely that policy processing can
+ * continue. But it is still possible that chain validation could succeed if
+ * policy processing is non-critical. So if this function receives a non-fatal
+ * error from a lower level routine, it aborts policy processing by setting
+ * the validPolicyTree to NULL and tries to continue.
+ *
+ */
+static PKIX_Error *
+pkix_PolicyChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticals, /* OIDs */
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polX = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitAnyPolicySkipCerts = 0;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE;
+ PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE;
+
+ PKIX_PolicyCheckerState *state = NULL;
+ PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */
+ PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */
+ PKIX_List *policyMaps = NULL; /* CertPolicyMaps */
+ PKIX_List *mappedPolicies = NULL; /* OIDs */
+ PKIX_Error *subroutineErr = NULL;
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_PL_String *certString = NULL;
+ char *certAscii = NULL;
+ PKIX_UInt32 length;
+#endif
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check");
+ PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("On entry %s\n", stateAscii);
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+ /*
+ * Section 6.1.4(a)
+ * If this is not the last certificate, and if
+ * policyMapping extension is present, check that no
+ * issuerDomainPolicy or subjectDomainPolicy is equal to the
+ * special policy anyPolicy.
+ */
+ if (state->certsProcessed != (state->numCerts - 1)) {
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
+ (cert, &policyMaps, plContext),
+ PKIX_CERTGETPOLICYMAPPINGSFAILED);
+ }
+
+ if (policyMaps) {
+
+ PKIX_CHECK(pkix_PolicyChecker_MapContains
+ (policyMaps, state->anyPolicyOID, &result, plContext),
+ PKIX_POLICYCHECKERMAPCONTAINSFAILED);
+
+ if (result) {
+ PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY);
+ }
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies
+ (policyMaps, &mappedPolicies, plContext),
+ PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED);
+
+ PKIX_DECREF(state->mappedPolicyOIDs);
+ PKIX_INCREF(mappedPolicies);
+ state->mappedPolicyOIDs = mappedPolicies;
+ }
+
+ /* Section 6.1.3(d) */
+ if (state->validPolicyTree) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicyInfos, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ if (certPolicyInfos) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyInfos, &numPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numPolicies > 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical
+ (cert, &(state->certPoliciesCritical), plContext),
+ PKIX_CERTARECERTPOLICIESCRITICALFAILED);
+
+ /* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyInfos,
+ polX,
+ (PKIX_PL_Object **)&policy,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (policy, &policyOID, plContext),
+ PKIX_CERTPOLICYINFOGETPOLICYIDFAILED);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ (policy, &policyQualifiers, plContext),
+ PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ policyOID,
+ &result,
+ plContext,
+ PKIX_OIDEQUALFAILED);
+
+ if (result == PKIX_FALSE) {
+
+ /* Section 6.1.3(d)(1)(i) */
+ subroutineErr = pkix_PolicyChecker_CheckPolicy
+ (policyOID,
+ policyQualifiers,
+ cert,
+ policyMaps,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+
+ } else {
+ /*
+ * No descent (yet) for anyPolicy, but we will need
+ * the policyQualifiers for anyPolicy in 6.1.3(d)(2)
+ */
+ PKIX_DECREF(qualsOfAny);
+ PKIX_INCREF(policyQualifiers);
+ qualsOfAny = policyQualifiers;
+ certPoliciesIncludeAny = PKIX_TRUE;
+ }
+ PKIX_DECREF(policy);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(policyQualifiers);
+ }
+
+ /* Section 6.1.3(d)(2) */
+ if (certPoliciesIncludeAny == PKIX_TRUE) {
+ if (state->inhibitAnyPolicy > 0) {
+ doAnyPolicyProcessing = PKIX_TRUE;
+ } else {
+ /* We haven't yet counted the current cert */
+ if (((state->certsProcessed) + 1) <
+ (state->numCerts)) {
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert,
+ &doAnyPolicyProcessing,
+ plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+ }
+ }
+ if (doAnyPolicyProcessing) {
+ subroutineErr = pkix_PolicyChecker_CheckAny
+ (state->validPolicyTree,
+ qualsOfAny,
+ policyMaps,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ }
+ }
+
+ /* Section 6.1.3(d)(3) */
+ if (state->validPolicyTree) {
+ subroutineErr = pkix_PolicyNode_Prune
+ (state->validPolicyTree,
+ state->certsProcessed + 1,
+ &shouldBePruned,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ if (shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ } else {
+ /* Section 6.1.3(e) */
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+ }
+
+ /* Section 6.1.3(f) */
+ if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
+ PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+
+ /*
+ * Remove Policy OIDs from list of unresolved critical
+ * extensions, if present.
+ */
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->certPoliciesExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->policyMappingsExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->policyConstraintsExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->inhibitAnyPolicyExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ state->certsProcessed++;
+
+ /* If this was not the last certificate, do next-cert preparation */
+ if (state->certsProcessed != state->numCerts) {
+
+ if (policyMaps) {
+ subroutineErr = pkix_PolicyChecker_PolicyMapProcessing
+ (policyMaps,
+ certPoliciesIncludeAny,
+ qualsOfAny,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ }
+
+ /* update anyPolicyNodeAtBottom pointer */
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ state->anyPolicyNodeAtBottom = state->newAnyPolicyNode;
+ state->newAnyPolicyNode = NULL;
+
+ /* Section 6.1.4(h) */
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (!isSelfIssued) {
+ if (state->explicitPolicy > 0) {
+ state->explicitPolicy--;
+ }
+ if (state->policyMapping > 0) {
+ state->policyMapping--;
+ }
+ if (state->inhibitAnyPolicy > 0) {
+ state->inhibitAnyPolicy--;
+ }
+ }
+
+ /* Section 6.1.4(i) */
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &explicitPolicySkipCerts, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ if (explicitPolicySkipCerts != -1) {
+ if (((PKIX_UInt32)explicitPolicySkipCerts) <
+ (state->explicitPolicy)) {
+ state->explicitPolicy =
+ ((PKIX_UInt32) explicitPolicySkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
+ (cert, &inhibitMappingSkipCerts, plContext),
+ PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
+
+ if (inhibitMappingSkipCerts != -1) {
+ if (((PKIX_UInt32)inhibitMappingSkipCerts) <
+ (state->policyMapping)) {
+ state->policyMapping =
+ ((PKIX_UInt32)inhibitMappingSkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
+ (cert, &inhibitAnyPolicySkipCerts, plContext),
+ PKIX_CERTGETINHIBITANYPOLICYFAILED);
+
+ if (inhibitAnyPolicySkipCerts != -1) {
+ if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) <
+ (state->inhibitAnyPolicy)) {
+ state->inhibitAnyPolicy =
+ ((PKIX_UInt32)inhibitAnyPolicySkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ } else { /* If this was the last certificate, do wrap-up processing */
+
+ /* Section 6.1.5 */
+ subroutineErr = pkix_PolicyChecker_WrapUpProcessing
+ (cert, state, plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+
+ if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
+ PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+ }
+
+
+ if (subroutineErr) {
+
+subrErrorCleanup:
+ /* We had an error. Was it a fatal error? */
+ pkixErrorClass = subroutineErr->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = subroutineErr;
+ subroutineErr = NULL;
+ goto cleanup;
+ }
+ /*
+ * Abort policy processing, and then determine whether
+ * we can continue without policy processing.
+ */
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+ if (state->explicitPolicy == 0) {
+ PKIX_ERROR
+ (PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+ }
+
+ /* Checking is complete. Save state for the next certificate. */
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ if (cert) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)cert, &certString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (certString,
+ PKIX_ESCASCII,
+ (void **)&certAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("Cert was %s\n", certAscii);
+ PKIX_FREE(certAscii);
+ PKIX_DECREF(certString);
+ }
+ if (state) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("On exit %s\n", stateAscii);
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+ }
+#endif
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(certPolicyInfos);
+ PKIX_DECREF(policy);
+ PKIX_DECREF(qualsOfAny);
+ PKIX_DECREF(policyQualifiers);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(subroutineErr);
+ PKIX_DECREF(policyMaps);
+ PKIX_DECREF(mappedPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates and initializes a PolicyChecker, using the List pointed to
+ * by "initialPolicies" for the user-initial-policy-set, the Boolean value
+ * of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
+ * the Boolean value of "initialPolicyMappingInhibit" for the
+ * inhibitPolicyMappings parameter, the Boolean value of
+ * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
+ * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
+ * parameter, and the UInt32 value of "numCerts" as the number of
+ * certificates in the chain; and stores the Checker at "pChecker".
+ *
+ * PARAMETERS:
+ * "initialPolicies"
+ * Address of List of OIDs comprising the user-initial-policy-set; the List
+ * may be empty or NULL
+ * "policyQualifiersRejected"
+ * Boolean value of the policyQualifiersRejected parameter
+ * "initialPolicyMappingInhibit"
+ * Boolean value of the inhibitPolicyMappings parameter
+ * "initialExplicitPolicy"
+ * Boolean value of the initialExplicitPolicy parameter
+ * "initialAnyPolicyInhibit"
+ * Boolean value of the inhibitAnyPolicy parameter
+ * "numCerts"
+ * Number of certificates in the chain to be validated
+ * "pChecker"
+ * Address to store the created PolicyChecker. 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 functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_Initialize(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *polCheckerState = NULL;
+ PKIX_List *policyExtensions = NULL; /* OIDs */
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_PolicyCheckerState_Create
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numCerts,
+ &polCheckerState,
+ plContext),
+ PKIX_POLICYCHECKERSTATECREATEFAILED);
+
+ /* Create the list of extensions that we handle */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension),
+ PKIX_TRUE,
+ &policyExtensions,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_PolicyChecker_Check,
+ PKIX_FALSE, /* forwardCheckingSupported */
+ PKIX_FALSE,
+ policyExtensions,
+ (PKIX_PL_Object *)polCheckerState,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+ PKIX_DECREF(polCheckerState);
+ PKIX_DECREF(policyExtensions);
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h
new file mode 100644
index 0000000000..8b87ac1224
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h
@@ -0,0 +1,73 @@
+/* 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_policychecker.h
+ *
+ * Header file for policy checker.
+ *
+ */
+
+#ifndef _PKIX_POLICYCHECKER_H
+#define _PKIX_POLICYCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PKIX_PolicyCheckerStateStruct PKIX_PolicyCheckerState;
+
+struct PKIX_PolicyCheckerStateStruct{
+ PKIX_PL_OID *certPoliciesExtension; /* const */
+ PKIX_PL_OID *policyMappingsExtension; /* const */
+ PKIX_PL_OID *policyConstraintsExtension; /* const */
+ PKIX_PL_OID *inhibitAnyPolicyExtension; /* const */
+ PKIX_PL_OID *anyPolicyOID; /* const */
+ PKIX_Boolean initialIsAnyPolicy; /* const */
+ PKIX_PolicyNode *validPolicyTree;
+ PKIX_List *userInitialPolicySet; /* immutable */
+ PKIX_List *mappedUserInitialPolicySet;
+ PKIX_Boolean policyQualifiersRejected;
+ PKIX_Boolean initialPolicyMappingInhibit;
+ PKIX_Boolean initialExplicitPolicy;
+ PKIX_Boolean initialAnyPolicyInhibit;
+ PKIX_UInt32 explicitPolicy;
+ PKIX_UInt32 inhibitAnyPolicy;
+ PKIX_UInt32 policyMapping;
+ PKIX_UInt32 numCerts;
+ PKIX_UInt32 certsProcessed;
+ PKIX_PolicyNode *anyPolicyNodeAtBottom;
+ PKIX_PolicyNode *newAnyPolicyNode;
+ /*
+ * The following variables do not survive from one
+ * certificate to the next. They are needed at each
+ * level of recursive routines, any by placing them
+ * in the state object we can pass fewer arguments.
+ */
+ PKIX_Boolean certPoliciesCritical;
+ PKIX_List *mappedPolicyOIDs;
+};
+
+PKIX_Error *
+pkix_PolicyChecker_Initialize(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+/* --Private-Functions-------------------------------------------- */
+
+PKIX_Error *
+pkix_PolicyCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_POLICYCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
new file mode 100644
index 0000000000..7bed9b8860
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
@@ -0,0 +1,475 @@
+/* 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 their priorities (lower priority = higher preference) */
+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;
+
+ if (method1->priority < method2->priority) {
+ *pResult = -1;
+ } else if (method1->priority > method2->priority) {
+ *pResult = 1;
+ } else {
+ *pResult = 0;
+ }
+
+ 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++) {
+ unsigned 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,
+ (CERTCRLEntryReasonCode *)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,
+ (CERTCRLEntryReasonCode *)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);
+}
+
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h
new file mode 100644
index 0000000000..20dfe37787
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h
@@ -0,0 +1,151 @@
+/* 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.h
+ *
+ * RevocationChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_REVOCATIONCHECKER_H
+#define _PKIX_REVOCATIONCHECKER_H
+
+#include "pkixt.h"
+#include "certt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logistic removed. Will be replaced later. */
+
+/*
+ * All Flags are prefixed by CERT_REV_M_, where _M_ indicates
+ * this is a method dependent flag.
+ */
+
+/*
+ * Whether or not to use a method for revocation testing.
+ * If set to "do not test", then all other flags are ignored.
+ */
+#define PKIX_REV_M_DO_NOT_TEST_USING_THIS_METHOD 0x00L
+#define PKIX_REV_M_TEST_USING_THIS_METHOD 0x01L
+
+/*
+ * Whether or not NSS is allowed to attempt to fetch fresh information
+ * from the network.
+ * (Although fetching will never happen if fresh information for the
+ * method is already locally available.)
+ */
+#define PKIX_REV_M_ALLOW_NETWORK_FETCHING 0x00L
+#define PKIX_REV_M_FORBID_NETWORK_FETCHING 0x02L
+
+/*
+ * Example for an implicit default source:
+ * The globally configured default OCSP responder.
+ * IGNORE means:
+ * ignore the implicit default source, whether it's configured or not.
+ * ALLOW means:
+ * if an implicit default source is configured,
+ * then it overrides any available or missing source in the cert.
+ * if no implicit default source is configured,
+ * then we continue to use what's available (or not available)
+ * in the certs.
+ */
+#define PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE 0x00L
+#define PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE 0x04L /* OCSP only */
+
+/*
+ * Defines the behavior if no fresh information is available,
+ * fetching from the network is allowed, but the source of revocation
+ * information is unknown (even after considering implicit sources,
+ * if allowed by other flags).
+ * SKIPT_TEST means:
+ * We ignore that no fresh information is available and
+ * skip this test.
+ * REQUIRE_INFO means:
+ * We still require that fresh information is available.
+ * Other flags define what happens on missing fresh info.
+ */
+
+#define PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE 0x00L
+#define PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE 0x08L
+
+/*
+ * Defines the behavior if we are unable to obtain fresh information.
+ * INGORE means:
+ * Return "cert status unknown"
+ * FAIL means:
+ * Return "cert revoked".
+ */
+
+#define PKIX_REV_M_IGNORE_MISSING_FRESH_INFO 0x00L
+#define PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO 0x10L
+
+/*
+ * What should happen if we were able to find fresh information using
+ * this method, and the data indicated the cert is good?
+ * STOP_TESTING means:
+ * Our success is sufficient, do not continue testing
+ * other methods.
+ * CONTINUE_TESTING means:
+ * We will continue and test the next allowed
+ * specified method.
+ */
+
+#define PKIX_REV_M_STOP_TESTING_ON_FRESH_INFO 0x00L
+#define PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO 0x20L
+
+/*
+ * All Flags are prefixed by PKIX_REV_MI_, where _MI_ indicates
+ * this is a method independent flag.
+ */
+
+/*
+ * This defines the order to checking.
+ * EACH_METHOD_SEPARATELY means:
+ * Do all tests related to a particular allowed method
+ * (both local information and network fetching) in a single step.
+ * Only after testing for a particular method is done,
+ * then switching to the next method will happen.
+ * ALL_LOCAL_INFORMATION_FIRST means:
+ * Start by testing the information for all allowed methods
+ * which are already locally available. Only after that is done
+ * consider to fetch from the network (as allowed by other flags).
+ */
+#define PKIX_REV_MI_TEST_EACH_METHOD_SEPARATELY 0x00L
+#define PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST 0x01L
+
+/*
+ * Use this flag to specify that it's necessary that fresh information
+ * is available for at least one of the allowed methods, but it's
+ * irrelevant which of the mechanisms succeeded.
+ * NO_OVERALL_INFO_REQUIREMENT means:
+ * We strictly follow the requirements for each individual method.
+ * REQUIRE_SOME_FRESH_INFO_AVAILABLE means:
+ * After the individual tests have been executed, we must have
+ * been able to find fresh information using at least one method.
+ * If we were unable to find fresh info, it's a failure.
+ */
+#define PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT 0x00L
+#define PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE 0x02L
+
+/* Defines check time for the cert, revocation methods lists and
+ * flags for leaf and chain certs revocation tests. */
+struct PKIX_RevocationCheckerStruct {
+ PKIX_List *leafMethodList;
+ PKIX_List *chainMethodList;
+ PKIX_UInt32 leafMethodListFlags;
+ PKIX_UInt32 chainMethodListFlags;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_RevocationChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_REVOCATIONCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c
new file mode 100644
index 0000000000..ee18ddef95
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c
@@ -0,0 +1,66 @@
+/* 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_revocationmethod.c
+ *
+ * RevocationMethod Object Functions
+ *
+ */
+
+#include "pkix_revocationmethod.h"
+#include "pkix_tools.h"
+
+/* Constructor of revocation method object. Does not create an object,
+ * but just initializez PKIX_RevocationMethodStruct fields. Object
+ * suppose to be already created. */
+PKIX_Error *
+pkix_RevocationMethod_Init(
+ pkix_RevocationMethod *method,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ void *plContext)
+{
+ PKIX_ENTER(REVOCATIONMETHOD, "PKIX_RevocationMethod_Init");
+
+ method->methodType = methodType;
+ method->flags = flags;
+ method->priority = priority;
+ method->localRevChecker = localRevChecker;
+ method->externalRevChecker = externalRevChecker;
+
+ PKIX_RETURN(REVOCATIONMETHOD);
+}
+
+/* Data duplication data. Not create an object. Only initializes fields
+ * in the new object by data from "object". */
+PKIX_Error *
+pkix_RevocationMethod_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object *newObject,
+ void *plContext)
+{
+ pkix_RevocationMethod *method = NULL;
+
+ PKIX_ENTER(REVOCATIONMETHOD, "pkix_RevocationMethod_Duplicate");
+ PKIX_NULLCHECK_TWO(object, newObject);
+
+ method = (pkix_RevocationMethod *)object;
+
+ PKIX_CHECK(
+ pkix_RevocationMethod_Init((pkix_RevocationMethod*)newObject,
+ method->methodType,
+ method->flags,
+ method->priority,
+ method->localRevChecker,
+ method->externalRevChecker,
+ plContext),
+ PKIX_COULDNOTCREATEREVOCATIONMETHODOBJECT);
+
+cleanup:
+
+ PKIX_RETURN(REVOCATIONMETHOD);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h
new file mode 100644
index 0000000000..a97c7620ae
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h
@@ -0,0 +1,81 @@
+/* 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_revocationmethod.h
+ *
+ * RevocationMethod Object
+ *
+ */
+
+#ifndef _PKIX_REVOCATIONMETHOD_H
+#define _PKIX_REVOCATIONMETHOD_H
+
+#include "pkixt.h"
+#include "pkix_revocationchecker.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_RevocationMethodStruct pkix_RevocationMethod;
+
+/* Local revocation check function prototype definition.
+ * Revocation methods capable of checking revocation though local
+ * means(cache) should implement this prototype. */
+typedef PKIX_Error *
+pkix_LocalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+/* External revocation check function prototype definition.
+ * Revocation methods that required external communications(crldp
+ * ocsp) shoult implement this prototype. */
+typedef PKIX_Error *
+pkix_ExternalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext, void *plContext);
+
+/* Revocation method structure assosiates revocation types with
+ * a set of flags on the method, a priority of the method (0
+ * corresponds to the highest priority), and method local/external
+ * checker functions. */
+struct pkix_RevocationMethodStruct {
+ PKIX_RevocationMethodType methodType;
+ PKIX_UInt32 flags;
+ PKIX_UInt32 priority;
+ pkix_LocalRevocationCheckFn (*localRevChecker);
+ pkix_ExternalRevocationCheckFn (*externalRevChecker);
+};
+
+PKIX_Error *
+pkix_RevocationMethod_Duplicate(PKIX_PL_Object *object,
+ PKIX_PL_Object *newObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_RevocationMethod_Init(pkix_RevocationMethod *method,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ void *plContext);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_REVOCATIONMETHOD_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c
new file mode 100644
index 0000000000..0ed9ffaecc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c
@@ -0,0 +1,443 @@
+/* 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_signaturechecker.c
+ *
+ * Functions for signature validation
+ *
+ */
+
+#include "pkix_signaturechecker.h"
+
+/*
+ * FUNCTION: pkix_SignatureCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_SignatureCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE,
+ "pkix_SignatureCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a signature checker state */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_SIGNATURECHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTSIGNATURECHECKERSTATE);
+
+ state = (pkix_SignatureCheckerState *) object;
+
+ state->prevCertCertSign = PKIX_FALSE;
+
+ PKIX_DECREF(state->prevPublicKey);
+ PKIX_DECREF(state->prevPublicKeyList);
+ PKIX_DECREF(state->keyUsageOID);
+
+cleanup:
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_SignatureCheckerState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_SIGNATURECHECKERSTATE_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * 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_SignatureCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE,
+ "pkix_SignatureCheckerState_RegisterSelf");
+
+ entry.description = "SignatureCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_SignatureCheckerState);
+ entry.destructor = pkix_SignatureCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_SIGNATURECHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_SignatureCheckerState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize SignatureChecker state data.
+ *
+ * PARAMETERS
+ * "trustedPubKey"
+ * Address of trusted Anchor Public Key for verifying first Cert in the
+ * chain. Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "pCheckerState"
+ * Address where SignatureCheckerState will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a SignatureCheckerState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_SignatureCheckerState_Create(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ pkix_SignatureCheckerState **pCheckerState,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+ PKIX_PL_OID *keyUsageOID = NULL;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE, "pkix_SignatureCheckerState_Create");
+ PKIX_NULLCHECK_TWO(trustedPubKey, pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SIGNATURECHECKERSTATE_TYPE,
+ sizeof (pkix_SignatureCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATESIGNATURECHECKERSTATEOBJECT);
+
+ /* Initialize fields */
+
+ state->prevCertCertSign = PKIX_TRUE;
+ state->prevPublicKeyList = NULL;
+ state->certsRemaining = certsRemaining;
+
+ PKIX_INCREF(trustedPubKey);
+ state->prevPublicKey = trustedPubKey;
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTKEYUSAGE_OID,
+ &keyUsageOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ state->keyUsageOID = keyUsageOID;
+ keyUsageOID = NULL;
+
+ *pCheckerState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(keyUsageOID);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_SignatureChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_SignatureChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+ PKIX_PL_PublicKey *prevPubKey = NULL;
+ PKIX_PL_PublicKey *currPubKey = NULL;
+ PKIX_PL_PublicKey *newPubKey = NULL;
+ PKIX_PL_PublicKey *pKey = NULL;
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_Error *checkKeyUsageFail = NULL;
+ PKIX_Error *verifyFail = NULL;
+ PKIX_Boolean certVerified = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_SignatureChecker_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)--;
+
+ PKIX_INCREF(state->prevPublicKey);
+ prevPubKey = state->prevPublicKey;
+
+ /*
+ * Previous Cert doesn't have CertSign bit on for signature
+ * verification and it is not a self-issued Cert so there is no
+ * old key saved. This is considered error.
+ */
+ if (state->prevCertCertSign == PKIX_FALSE &&
+ state->prevPublicKeyList == NULL) {
+ PKIX_ERROR(PKIX_KEYUSAGEKEYCERTSIGNBITNOTON);
+ }
+
+ /* Previous Cert is valid for signature verification, try it first */
+ if (state->prevCertCertSign == PKIX_TRUE) {
+ verifyFail = PKIX_PL_Cert_VerifySignature
+ (cert, prevPubKey, plContext);
+ if (verifyFail == NULL) {
+ certVerified = PKIX_TRUE;
+ } else {
+ certVerified = PKIX_FALSE;
+ }
+ }
+
+#ifdef NIST_TEST_4_5_4_AND_4_5_6
+
+ /*
+ * Following codes under this compiler flag is implemented for
+ * special cases of NIST tests 4.5.4 and 4.5.6. We are not sure
+ * we should handle these two tests as what is implemented so the
+ * codes are commented out, and the tests fails (for now).
+ * For Cert chain validation, our assumption is all the Certs on
+ * the chain are using its previous Cert's public key to decode
+ * its current key. But for thses two tests, keys are used not
+ * in this precedent order, we can either
+ * 1) Use what is implemented here: take in what Cert order NIST
+ * specified and for continuous self-issued Certs, stacking up
+ * their keys and tries all of them in FILO order.
+ * But this method breaks the idea of chain key presdency.
+ * 2) Use Build Chain facility: we will specify the valid Certs
+ * order (means key precedency is kept) and count on Build Chain
+ * to get the Certs that can fill for the needed keys. This may have
+ * performance impact.
+ * 3) Fetch Certs from CertStore: we will specifiy the valid Certs
+ * order and use CertSelector on SubjectName to get a list of
+ * candidates Certs to fill in for the needed keys.
+ * Anyhow, the codes are kept around just in case we want to use
+ * solution one...
+ */
+
+ /* If failed and previous key is self-issued, try its old key(s) */
+ if (certVerified == PKIX_FALSE && state->prevPublicKeyList != NULL) {
+
+ /* Verify from keys on the list */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->prevPublicKeyList, &numKeys, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = numKeys - 1; i >= 0; i--) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->prevPublicKeyList,
+ i,
+ (PKIX_PL_Object **) &pKey,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_DECREF(verifyFail);
+ verifyFail = PKIX_PL_Cert_VerifySignature
+ (cert, pKey, plContext);
+
+ if (verifyFail == NULL) {
+ certVerified = PKIX_TRUE;
+ break;
+ } else {
+ certVerified = PKIX_FALSE;
+ }
+
+ PKIX_DECREF(pKey);
+ }
+ }
+#endif
+
+ if (certVerified == PKIX_FALSE) {
+ pkixErrorResult = verifyFail;
+ verifyFail = NULL;
+ PKIX_ERROR(PKIX_VALIDATIONFAILEDCERTSIGNATURECHECKING);
+ }
+
+#ifdef NIST_TEST_4_5_4_AND_4_5_6
+ /*
+ * Check if Cert is self-issued. If so, the old key(s) is saved, in
+ * conjunction to the new key, for verifying CERT validity later.
+ */
+ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
+ PKIX_ISCERTSELFISSUEFAILED);
+
+ /*
+ * Check if Cert is self-issued. If so, the public key of the Cert
+ * that issues this Cert (old key) can be used together with this
+ * current key (new key) for key verification. If there are multiple
+ * self-issued certs, keys of those Certs (old keys) can also be used
+ * for key verification. Old key(s) is saved in a list (PrevPublickKey-
+ * List) and cleared when a Cert is no longer self-issued. PrevPublic-
+ * Key keep key of the previous Cert.
+ */
+ if (selfIssued == PKIX_TRUE) {
+
+ /* Make sure previous Cert is valid for signature verification */
+ if (state->prevCertCertSign == PKIX_TRUE) {
+
+ if (state->prevPublicKeyList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&state->prevPublicKeyList, plContext),
+ PKIX_LISTCREATEFALIED);
+
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->prevPublicKeyList,
+ (PKIX_PL_Object *) state->prevPublicKey,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ } else {
+ /* Not self-issued Cert any more, clear old key(s) saved */
+ PKIX_DECREF(state->prevPublicKeyList);
+ }
+#endif
+
+ /* Save current key as prevPublicKey */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &currPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
+ (currPubKey, prevPubKey, &newPubKey, plContext),
+ PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED);
+
+ if (newPubKey == NULL){
+ PKIX_INCREF(currPubKey);
+ newPubKey = currPubKey;
+ }
+
+ PKIX_INCREF(newPubKey);
+ PKIX_DECREF(state->prevPublicKey);
+
+ state->prevPublicKey = newPubKey;
+
+ /* Save this Cert key usage CertSign bit */
+ if (state->certsRemaining != 0) {
+ checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage
+ (cert, PKIX_KEY_CERT_SIGN, plContext);
+
+ state->prevCertCertSign = (checkKeyUsageFail == NULL)?
+ PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_DECREF(checkKeyUsageFail);
+ }
+
+ /* Remove Key Usage Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->keyUsageOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(pKey);
+ PKIX_DECREF(prevPubKey);
+ PKIX_DECREF(currPubKey);
+ PKIX_DECREF(newPubKey);
+ PKIX_DECREF(basicConstraints);
+ PKIX_DECREF(verifyFail);
+ PKIX_DECREF(checkKeyUsageFail);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_SignatureChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * be used by pkix_SignatureChecker_Check to check that the public key in
+ * the checker's state is able to successfully validate the certificate's
+ * signature. The PublicKey pointed to by "trustedPubKey" is used to
+ * initialize the checker's state.
+ *
+ * PARAMETERS:
+ * "trustedPubKey"
+ * Address of PublicKey representing the trusted public key used to
+ * initialize the state of this checker. Must be non-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_SignatureChecker_Initialize(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_SignatureCheckerState* state = NULL;
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_SignatureChecker_Initialize");
+ PKIX_NULLCHECK_TWO(pChecker, trustedPubKey);
+
+ PKIX_CHECK(pkix_SignatureCheckerState_Create
+ (trustedPubKey, certsRemaining, &state, plContext),
+ PKIX_SIGNATURECHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_SignatureChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h
new file mode 100644
index 0000000000..ccfb578579
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h
@@ -0,0 +1,44 @@
+/* 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_signaturechecker.h
+ *
+ * Header file for validate signature function
+ *
+ */
+
+#ifndef _PKIX_SIGNATURECHECKER_H
+#define _PKIX_SIGNATURECHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_SignatureCheckerState pkix_SignatureCheckerState;
+
+struct pkix_SignatureCheckerState {
+ PKIX_Boolean prevCertCertSign;
+ PKIX_UInt32 certsRemaining;
+ PKIX_PL_PublicKey *prevPublicKey; /* Subject PubKey of last cert */
+ PKIX_List *prevPublicKeyList; /* of PKIX_PL_PublicKey */
+ PKIX_PL_OID *keyUsageOID;
+};
+
+PKIX_Error *
+pkix_SignatureChecker_Initialize(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_SignatureCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_SIGNATURECHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c
new file mode 100644
index 0000000000..46fe07112b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c
@@ -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);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h
new file mode 100644
index 0000000000..4592d10a94
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h
@@ -0,0 +1,47 @@
+/* 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.h
+ *
+ * Header file for validate target cert function
+ *
+ */
+
+#ifndef _PKIX_TARGETCERTCHECKER_H
+#define _PKIX_TARGETCERTCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_TargetCertCheckerState pkix_TargetCertCheckerState;
+
+struct pkix_TargetCertCheckerState {
+ PKIX_CertSelector *certSelector;
+ PKIX_List *pathToNameList;
+ PKIX_List *extKeyUsageList; /* List of PKIX_PL_OID */
+ PKIX_List *subjAltNameList;
+ PKIX_Boolean subjAltNameMatchAll;
+ PKIX_UInt32 certsRemaining;
+ PKIX_PL_OID *extKeyUsageOID;
+ PKIX_PL_OID *subjAltNameOID;
+};
+
+PKIX_Error *
+pkix_TargetCertChecker_Initialize(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_TargetCertCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TARGETCERTCHECKER_H */