summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix')
-rw-r--r--security/nss/lib/libpkix/pkix/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/certsel.gyp24
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/exports.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/manifest.mn20
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c1637
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h41
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c1188
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h57
-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
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp24
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/exports.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/manifest.mn20
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c826
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h38
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c870
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h40
-rw-r--r--security/nss/lib/libpkix/pkix/manifest.mn11
-rw-r--r--security/nss/lib/libpkix/pkix/params/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/params/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/params/manifest.mn24
-rw-r--r--security/nss/lib/libpkix/pkix/params/params.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_procparams.c1417
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_procparams.h50
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c433
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h36
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c525
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h35
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_valparams.c335
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_valparams.h33
-rw-r--r--security/nss/lib/libpkix/pkix/results/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/results/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/results/manifest.mn24
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_buildresult.c362
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_buildresult.h40
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_policynode.c1377
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_policynode.h74
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_valresult.c442
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_valresult.h43
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_verifynode.c1182
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_verifynode.h75
-rw-r--r--security/nss/lib/libpkix/pkix/results/results.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/store/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/store/exports.gyp25
-rw-r--r--security/nss/lib/libpkix/pkix/store/manifest.mn18
-rw-r--r--security/nss/lib/libpkix/pkix/store/pkix_store.c415
-rw-r--r--security/nss/lib/libpkix/pkix/store/pkix_store.h41
-rw-r--r--security/nss/lib/libpkix/pkix/store/store.gyp23
-rw-r--r--security/nss/lib/libpkix/pkix/top/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/top/exports.gyp27
-rw-r--r--security/nss/lib/libpkix/pkix/top/manifest.mn22
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_build.c3763
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_build.h120
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c210
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h23
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_validate.c1451
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_validate.h42
-rw-r--r--security/nss/lib/libpkix/pkix/top/top.gyp25
-rw-r--r--security/nss/lib/libpkix/pkix/util/Makefile44
-rw-r--r--security/nss/lib/libpkix/pkix/util/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/util/manifest.mn25
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.c565
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.h36
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_errpaths.c103
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.c1701
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.h95
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.c1088
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.h57
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.c1525
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.h1588
-rw-r--r--security/nss/lib/libpkix/pkix/util/util.gyp27
101 files changed, 32506 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/Makefile b/security/nss/lib/libpkix/pkix/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/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/certsel/Makefile b/security/nss/lib/libpkix/pkix/certsel/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/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/certsel/certsel.gyp b/security/nss/lib/libpkix/pkix/certsel/certsel.gyp
new file mode 100644
index 0000000000..a7ff65ce76
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/certsel.gyp
@@ -0,0 +1,24 @@
+# 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': 'pkixcertsel',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_certselector.c',
+ 'pkix_comcertselparams.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/certsel/exports.gyp b/security/nss/lib/libpkix/pkix/certsel/exports.gyp
new file mode 100644
index 0000000000..9cbd847e7c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/exports.gyp
@@ -0,0 +1,26 @@
+# 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_certsel_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_certselector.h',
+ 'pkix_comcertselparams.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/manifest.mn b/security/nss/lib/libpkix/pkix/certsel/manifest.mn
new file mode 100644
index 0000000000..eb434bd531
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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_certselector.h \
+ pkix_comcertselparams.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_certselector.c \
+ pkix_comcertselparams.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixcertsel
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c
new file mode 100644
index 0000000000..89bddd98bc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c
@@ -0,0 +1,1637 @@
+/* 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_certselector.c
+ *
+ * CertSelector Object Functions
+ *
+ */
+
+#include "pkix_certselector.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertSelector_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertSelector_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a cert selector */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSELECTOR);
+
+ selector = (PKIX_CertSelector *)object;
+ PKIX_DECREF(selector->params);
+ PKIX_DECREF(selector->context);
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertSelector_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_CertSelector *certSelectorDuplicate = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSELECTOR);
+
+ certSelector = (PKIX_CertSelector *)object;
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (certSelector->matchCallback,
+ certSelector->context,
+ &certSelectorDuplicate,
+ plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)certSelector->params,
+ (PKIX_PL_Object **)&certSelectorDuplicate->params,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)certSelectorDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(certSelectorDuplicate);
+ }
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_BasicConstraint
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the basic
+ * constraints criterion using the basic constraints field of the
+ * ComCertSelParams pointed to by "params". If the basic constraints field is
+ * -1, no basic constraints check is done and the Cert is considered to match
+ * the basic constraints criterion. If the Cert does not match the basic
+ * constraints criterion, an Error pointer is returned.
+ *
+ * In order to match against this criterion, there are several possibilities.
+ *
+ * 1) If the criterion's minimum path length is greater than or equal to zero,
+ * a certificate must include a BasicConstraints extension with a pathLen of
+ * at least this value.
+ *
+ * 2) If the criterion's minimum path length is -2, a certificate must be an
+ * end-entity certificate.
+ *
+ * 3) If the criterion's minimum path length is -1, no basic constraints check
+ * is done and all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose basic constraints field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * OUTPUT PARAMETERS ON FAILURE:
+ * If the function returns a failure,
+ * the output parameters of this function are undefined.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_BasicConstraint(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_Boolean caFlag = PKIX_FALSE; /* EE Cert by default */
+ PKIX_Int32 pathLength = 0;
+ PKIX_Int32 minPathLength = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_BasicConstraint");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+ *pResult = PKIX_TRUE;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
+ (params, &minPathLength, plContext),
+ PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);
+
+ /* If the minPathLength is unlimited (-1), no checking */
+ if (minPathLength == PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraints, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints, &caFlag, plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (basicConstraints, &pathLength, plContext),
+ PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
+ }
+
+ /*
+ * if minPathLength >= 0, the cert must have a BasicConstraints ext and
+ * the pathLength in this cert
+ * BasicConstraints needs to be >= minPathLength.
+ */
+ if (minPathLength >= 0){
+ if ((!basicConstraints) || (caFlag == PKIX_FALSE)){
+ PKIX_ERROR(PKIX_CERTNOTALLOWEDTOSIGNCERTIFICATES);
+ } else if ((pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) &&
+ (pathLength < minPathLength)){
+ PKIX_CERTSELECTOR_DEBUG
+ ("Basic Constraints path length match failed\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID);
+ }
+ }
+
+ /* if the minPathLength is -2, this cert must be an end-entity cert. */
+ if (minPathLength == PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH) {
+ if (caFlag == PKIX_TRUE) {
+ PKIX_CERTSELECTOR_DEBUG
+ ("Basic Constraints end-entity match failed\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_Policies
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the policy
+ * constraints specified in the ComCertsSelParams given by "params".
+ * If "params" specifies a policy constraint of NULL, all certificates
+ * match. If "params" specifies an empty list, "cert" must have at least
+ * some policy. Otherwise "cert" must include at least one of the
+ * policies in the list. See the description of PKIX_CertSelector in
+ * pkix_certsel.h for more.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose policy criterion (if any) is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_Policies(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 numConstraintPolicies = 0;
+ PKIX_UInt32 numCertPolicies = 0;
+ PKIX_UInt32 certPolicyIndex = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_List *constraintPolicies = NULL; /* List of PKIX_PL_OID */
+ PKIX_List *certPolicyInfos = NULL; /* List of PKIX_PL_CertPolicyInfo */
+ PKIX_PL_CertPolicyInfo *policyInfo = NULL;
+ PKIX_PL_OID *polOID = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_Policies");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetPolicy
+ (params, &constraintPolicies, plContext),
+ PKIX_COMCERTSELPARAMSGETPOLICYFAILED);
+
+ /* If constraintPolicies is NULL, all certificates "match" */
+ if (constraintPolicies) {
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicyInfos, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ /* No hope of a match if cert has no policies */
+ if (!certPolicyInfos) {
+ PKIX_CERTSELECTOR_DEBUG("Certificate has no policies\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (constraintPolicies, &numConstraintPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numConstraintPolicies > 0) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyInfos, &numCertPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (certPolicyIndex = 0;
+ ((!result) && (certPolicyIndex < numCertPolicies));
+ certPolicyIndex++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyInfos,
+ certPolicyIndex,
+ (PKIX_PL_Object **)&policyInfo,
+ plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (policyInfo, &polOID, plContext),
+ PKIX_CERTPOLICYINFOGETPOLICYIDFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (constraintPolicies,
+ (PKIX_PL_Object *)polOID,
+ &result,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(polOID);
+ }
+ if (!result) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(constraintPolicies);
+ PKIX_DECREF(certPolicyInfos);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(polOID);
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_CertificateValid
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the certificate
+ * validity criterion using the CertificateValid field of the
+ * ComCertSelParams pointed to by "params". If the CertificateValid field is
+ * NULL, no validity check is done and the Cert is considered to match
+ * the CertificateValid criterion. If the CertificateValid field specifies a
+ * Date prior to the notBefore field in the Cert, or greater than the notAfter
+ * field in the Cert, an Error is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose certValid field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_CertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_Date *validityTime = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_CertificateValid");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
+ (params, &validityTime, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
+
+ /* If the validityTime is not set, all certificates are acceptable */
+ if (validityTime) {
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity
+ (cert, validityTime, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+ PKIX_DECREF(validityTime);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_NameConstraints
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the name
+ * constraints criterion specified in the ComCertSelParams pointed to by
+ * "params". If the name constraints field is NULL, no name constraints check
+ * is done and the Cert is considered to match the name constraints criterion.
+ * If the Cert does not match the name constraints criterion, an Error pointer
+ * is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose name constraints field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_NameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_NameConstraints");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetNameConstraints
+ (params, &nameConstraints, plContext),
+ PKIX_COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED);
+
+ if (nameConstraints != NULL) {
+ /* As only the end-entity certificate should have
+ * the common name constrained as if it was a dNSName,
+ * do not constrain the common name when building a
+ * forward path.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
+ (cert, nameConstraints, PKIX_FALSE, plContext),
+ PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_PathToNames
+ * DESCRIPTION:
+ *
+ * Determines whether the names at pathToNames in "params" complies with the
+ * NameConstraints pointed to by "cert". If the pathToNames field is NULL
+ * or there is no name constraints for this "cert", no checking is done
+ * and the Cert is considered to match the name constraints criterion.
+ * If the Cert does not match the name constraints criterion, an Error
+ * pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose PathToNames field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_PathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *pathToNamesList = NULL;
+ PKIX_Boolean passed = PKIX_FALSE;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_PathToNames");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
+ (params, &pathToNamesList, plContext),
+ PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
+
+ if (pathToNamesList != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ if (nameConstraints != NULL) {
+
+ PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ (pathToNamesList, nameConstraints, &passed, plContext),
+ PKIX_CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED);
+
+ if (passed != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPATHTONAMESFAILED);
+ }
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(pathToNamesList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjAltNames
+ * DESCRIPTION:
+ *
+ * Determines whether the names at subjAltNames in "params" match with the
+ * SubjAltNames pointed to by "cert". If the subjAltNames field is NULL,
+ * no name checking is done and the Cert is considered to match the
+ * criterion. If the Cert does not match the criterion, an Error pointer
+ * is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose SubjAltNames field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_SubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *subjAltNamesList = NULL;
+ PKIX_List *certSubjAltNames = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_Boolean checkPassed = PKIX_FALSE;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ PKIX_UInt32 i, numItems;
+ PKIX_UInt32 matchCount = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjAltNames");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ (params, &matchAll, plContext),
+ PKIX_COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
+ (params, &subjAltNamesList, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+
+ if (subjAltNamesList != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+ (cert, &certSubjAltNames, plContext),
+ PKIX_CERTGETSUBJALTNAMESFAILED);
+
+ if (certSubjAltNames == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (subjAltNamesList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (subjAltNamesList,
+ 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 (matchAll == PKIX_FALSE) {
+ /* one match is good enough */
+ matchCount = numItems;
+ break;
+ } else {
+ /* else continue checking next */
+ matchCount++;
+ }
+
+ }
+
+ }
+
+ if (matchCount != numItems) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(name);
+ PKIX_DECREF(certSubjAltNames);
+ PKIX_DECREF(subjAltNamesList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_ExtendedKeyUsage
+ * DESCRIPTION:
+ *
+ * Determines whether the names at ExtKeyUsage in "params" matches with the
+ * ExtKeyUsage pointed to by "cert". If the ExtKeyUsage criterion or
+ * ExtKeyUsage in "cert" is NULL, no checking is done and the Cert is
+ * considered a match. If the Cert does not match, an Error pointer is
+ * returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose ExtKeyUsage field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_ExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *extKeyUsageList = NULL;
+ PKIX_List *certExtKeyUsageList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_ExtendedKeyUsage");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (params, &extKeyUsageList, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ if (extKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &certExtKeyUsageList, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ if (certExtKeyUsageList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (extKeyUsageList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (extKeyUsageList, 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) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(ekuOid);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(certExtKeyUsageList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_KeyUsage
+ * DESCRIPTION:
+ *
+ * Determines whether the bits at KeyUsage in "params" matches with the
+ * KeyUsage pointed to by "cert". If the KeyUsage in params is 0
+ * no checking is done and the Cert is considered a match. If the Cert does
+ * not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose ExtKeyUsage field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_KeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 keyUsage = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_KeyUsage");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
+ (params, &keyUsage, plContext),
+ PKIX_COMCERTSELPARAMSGETKEYUSAGEFAILED);
+
+ if (keyUsage != 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_VerifyKeyUsage
+ (cert, keyUsage, plContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjKeyId
+ * DESCRIPTION:
+ *
+ * Determines whether the bytes at subjKeyId in "params" matches with the
+ * Subject Key Identifier pointed to by "cert". If the subjKeyId in params is
+ * set to NULL or the Cert doesn't have a Subject Key Identifier, no checking
+ * is done and the Cert is considered a match. If the Cert does not match, an
+ * Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subjKeyId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_SubjKeyId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *selSubjKeyId = NULL;
+ PKIX_PL_ByteArray *certSubjKeyId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjKeyId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ (params, &selSubjKeyId, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED);
+
+ if (selSubjKeyId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
+ (cert, &certSubjKeyId, plContext),
+ PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
+
+ if (certSubjKeyId == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selSubjKeyId,
+ (PKIX_PL_Object *)certSubjKeyId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals == PKIX_FALSE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selSubjKeyId);
+ PKIX_DECREF(certSubjKeyId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_AuthKeyId
+ * DESCRIPTION:
+ *
+ * Determines whether the bytes at authKeyId in "params" matches with the
+ * Authority Key Identifier pointed to by "cert". If the authKeyId in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose authKeyId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_AuthKeyId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *selAuthKeyId = NULL;
+ PKIX_PL_ByteArray *certAuthKeyId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_AuthKeyId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ (params, &selAuthKeyId, plContext),
+ PKIX_COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ if (selAuthKeyId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (cert, &certAuthKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ if (certAuthKeyId == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selAuthKeyId,
+ (PKIX_PL_Object *)certAuthKeyId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selAuthKeyId);
+ PKIX_DECREF(certAuthKeyId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjPKAlgId
+ * DESCRIPTION:
+ *
+ * Determines whether the OID at subjPKAlgId in "params" matches with the
+ * Subject Public Key Alg Id pointed to by "cert". If the subjPKAlgId in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subjPKAlgId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_SubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_OID *selPKAlgId = NULL;
+ PKIX_PL_OID *certPKAlgId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPKAlgId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPKAlgId
+ (params, &selPKAlgId, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJPKALGIDFAILED);
+
+ if (selPKAlgId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKeyAlgId
+ (cert, &certPKAlgId, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYALGIDFAILED);
+
+ if (certPKAlgId != NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selPKAlgId,
+ (PKIX_PL_Object *)certPKAlgId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selPKAlgId);
+ PKIX_DECREF(certPKAlgId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjPubKey
+ * DESCRIPTION:
+ *
+ * Determines whether the key at subjPubKey in "params" matches with the
+ * Subject Public Key pointed to by "cert". If the subjPubKey in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subPubKey field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_Match_SubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *selPK = NULL;
+ PKIX_PL_PublicKey *certPK = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPubKey");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPubKey
+ (params, &selPK, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJPUBKEYFAILED);
+
+ if (selPK != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &certPK, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ if (certPK == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selPK,
+ (PKIX_PL_Object *)certPK,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selPK);
+ PKIX_DECREF(certPK);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_DefaultMatch
+ * DESCRIPTION:
+ *
+ * This default match function determines whether the specified Cert pointed
+ * to by "cert" matches the criteria of the CertSelector pointed to by
+ * "selector". If the Cert does not match the CertSelector's
+ * criteria, an error will be thrown.
+ *
+ * This default match function understands how to process the most common
+ * parameters. Any common parameter that is not set is assumed to be disabled,
+ * which means this function will select all certificates without regard to
+ * that particular disabled parameter. For example, if the SerialNumber
+ * parameter is not set, this function will not filter out any certificate
+ * based on its serial number. As such, if no parameters are set, all are
+ * disabled and any certificate will match. If a parameter is disabled, its
+ * associated PKIX_ComCertSelParams_Get* function returns a default value.
+ * That value is -1 for PKIX_ComCertSelParams_GetBasicConstraints and
+ * PKIX_ComCertSelParams_GetVersion, 0 for PKIX_ComCertSelParams_GetKeyUsage,
+ * and NULL for all other Get functions.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose MatchCallback logic and parameters are
+ * to be used. Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched using "selector".
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector 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_CertSelector_DefaultMatch(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_X500Name *certSubject = NULL;
+ PKIX_PL_X500Name *selSubject = NULL;
+ PKIX_PL_X500Name *certIssuer = NULL;
+ PKIX_PL_X500Name *selIssuer = NULL;
+ PKIX_PL_BigInt *certSerialNumber = NULL;
+ PKIX_PL_BigInt *selSerialNumber = NULL;
+ PKIX_PL_Cert *selCert = NULL;
+ PKIX_PL_Date *selDate = NULL;
+ PKIX_UInt32 selVersion = 0xFFFFFFFF;
+ PKIX_UInt32 certVersion = 0;
+ PKIX_Boolean result = PKIX_TRUE;
+ PKIX_Boolean isLeafCert = PKIX_TRUE;
+
+#ifdef PKIX_BUILDDEBUG
+ PKIX_PL_String *certString = NULL;
+ void *certAscii = NULL;
+ PKIX_UInt32 certAsciiLen;
+#endif
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_DefaultMatch");
+ PKIX_NULLCHECK_TWO(selector, cert);
+
+ PKIX_INCREF(selector->params);
+ params = selector->params;
+
+ /* Are we looking for CAs? */
+ PKIX_CHECK(PKIX_ComCertSelParams_GetLeafCertFlag
+ (params, &isLeafCert, plContext),
+ PKIX_COMCERTSELPARAMSGETLEAFCERTFLAGFAILED);
+
+ if (params == NULL){
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetVersion
+ (params, &selVersion, plContext),
+ PKIX_COMCERTSELPARAMSGETVERSIONFAILED);
+
+ if (selVersion != 0xFFFFFFFF){
+ PKIX_CHECK(PKIX_PL_Cert_GetVersion
+ (cert, &certVersion, plContext),
+ PKIX_CERTGETVERSIONFAILED);
+
+ if (selVersion != certVersion) {
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTVERSIONFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (params, &selSubject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ if (selSubject){
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (cert, &certSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ if (certSubject){
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (selSubject, certSubject, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED);
+ }
+ } else { /* cert has no subject */
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetIssuer
+ (params, &selIssuer, plContext),
+ PKIX_COMCERTSELPARAMSGETISSUERFAILED);
+
+ if (selIssuer){
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (cert, &certIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (selIssuer, certIssuer, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTISSUERFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSerialNumber
+ (params, &selSerialNumber, plContext),
+ PKIX_COMCERTSELPARAMSGETSERIALNUMBERFAILED);
+
+ if (selSerialNumber){
+ PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber
+ (cert, &certSerialNumber, plContext),
+ PKIX_CERTGETSERIALNUMBERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selSerialNumber,
+ (PKIX_PL_Object *)certSerialNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSERIALNUMFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
+ (params, &selCert, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
+
+ if (selCert){
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *) selCert,
+ (PKIX_PL_Object *) cert,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTOBJECTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
+ (params, &selDate, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
+
+ if (selDate){
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity
+ (cert, selDate, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+ }
+
+ PKIX_CHECK(pkix_CertSelector_Match_BasicConstraint
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHBASICCONSTRAINTFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_Policies
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_CertificateValid
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_NameConstraints
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_PathToNames
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHPATHTONAMESFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjAltNames
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+
+ /* Check key usage and cert type based on certificate usage. */
+ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, !isLeafCert,
+ plContext),
+ PKIX_CERTVERIFYCERTTYPEFAILED);
+
+ /* Next two check are for user supplied additional KU and EKU. */
+ PKIX_CHECK(pkix_CertSelector_Match_ExtendedKeyUsage
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_KeyUsage
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHKEYUSAGEFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjKeyId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_AuthKeyId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjPKAlgId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjPubKey
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+
+ /* if we reach here, the cert has successfully matched criteria */
+
+
+#ifdef PKIX_BUILDDEBUG
+
+ PKIX_CHECK(pkix_pl_Cert_ToString_Helper
+ (cert, PKIX_TRUE, &certString, plContext),
+ PKIX_CERTTOSTRINGHELPERFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (certString,
+ PKIX_ESCASCII,
+ &certAscii,
+ &certAsciiLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CERTSELECTOR_DEBUG_ARG("Cert Selected:\n%s\n", certAscii);
+
+#endif
+
+cleanup:
+
+#ifdef PKIX_BUILDDEBUG
+ PKIX_DECREF(certString);
+ PKIX_FREE(certAscii);
+#endif
+
+ PKIX_DECREF(certSubject);
+ PKIX_DECREF(selSubject);
+ PKIX_DECREF(certIssuer);
+ PKIX_DECREF(selIssuer);
+ PKIX_DECREF(certSerialNumber);
+ PKIX_DECREF(selSerialNumber);
+ PKIX_DECREF(selCert);
+ PKIX_DECREF(selDate);
+ PKIX_DECREF(params);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTSELECTOR_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_CertSelector_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_RegisterSelf");
+
+ entry.description = "CertSelector";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertSelector);
+ entry.destructor = pkix_CertSelector_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CertSelector_Duplicate;
+
+ systemClasses[PKIX_CERTSELECTOR_TYPE] = entry;
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_CertSelector_Create (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_Create(
+ PKIX_CertSelector_MatchCallback callback,
+ PKIX_PL_Object *certSelectorContext,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Create");
+ PKIX_NULLCHECK_ONE(pSelector);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTSELECTOR_TYPE,
+ sizeof (PKIX_CertSelector),
+ (PKIX_PL_Object **)&selector,
+ plContext),
+ PKIX_COULDNOTCREATECERTSELECTOROBJECT);
+
+ /*
+ * if user specified a particular match callback, we use that one.
+ * otherwise, we use the default match implementation which
+ * understands how to process PKIX_ComCertSelParams
+ */
+
+ if (callback){
+ selector->matchCallback = callback;
+ } else {
+ selector->matchCallback = pkix_CertSelector_DefaultMatch;
+ }
+
+ /* initialize other fields */
+ selector->params = NULL;
+
+ PKIX_INCREF(certSelectorContext);
+ selector->context = certSelectorContext;
+
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetMatchCallback
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_CertSelector_MatchCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetMatchCallback");
+ PKIX_NULLCHECK_TWO(selector, pCallback);
+
+ *pCallback = selector->matchCallback;
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCertSelectorContext
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCertSelectorContext(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Object **pCertSelectorContext,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetCertSelectorContext");
+ PKIX_NULLCHECK_TWO(selector, pCertSelectorContext);
+
+ PKIX_INCREF(selector->context);
+
+ *pCertSelectorContext = selector->context;
+
+cleanup:
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR,
+ "PKIX_CertSelector_GetCommonCertSelectorParams");
+
+ PKIX_NULLCHECK_TWO(selector, pParams);
+
+ PKIX_INCREF(selector->params);
+ *pParams = selector->params;
+
+cleanup:
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_SetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams *params,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR,
+ "PKIX_CertSelector_SetCommonCertSelectorParams");
+
+ PKIX_NULLCHECK_ONE(selector);
+
+ PKIX_DECREF(selector->params);
+ PKIX_INCREF(params);
+ selector->params = params;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)selector, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Select
+ * DESCRIPTION:
+ *
+ * This function applies the selector pointed to by "selector" to each Cert,
+ * in turn, in the List pointed to by "before", and creates a List containing
+ * all the Certs that matched, or passed the selection process, storing that
+ * List at "pAfter". If no Certs match, an empty List is stored at "pAfter".
+ *
+ * The List returned in "pAfter" is immutable.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelelector to be applied to the List. Must be non-NULL.
+ * "before"
+ * Address of List that is to be filtered. Must be non-NULL.
+ * "pAfter"
+ * Address at which resulting List, possibly empty, is 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 CertSelector 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_CertSelector_Select(
+ PKIX_CertSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext)
+{
+ PKIX_UInt32 numBefore = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *filtered = NULL;
+ PKIX_PL_Cert *candidate = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Select");
+ PKIX_NULLCHECK_THREE(selector, before, pAfter);
+
+ PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numBefore; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (before, i, (PKIX_PL_Object **)&candidate, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(selector->matchCallback
+ (selector, candidate, plContext),
+ PKIX_CERTSELECTORMATCHCALLBACKFAILED);
+
+ if (!(PKIX_ERROR_RECEIVED)) {
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (filtered,
+ (PKIX_PL_Object *)candidate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(candidate);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* Don't throw away the list if one Cert was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pAfter = filtered;
+ filtered = NULL;
+
+cleanup:
+
+ PKIX_DECREF(filtered);
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h
new file mode 100644
index 0000000000..33b648354c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h
@@ -0,0 +1,41 @@
+/* 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_certselector.h
+ *
+ * CertSelector Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CERTSELECTOR_H
+#define _PKIX_CERTSELECTOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertSelectorStruct {
+ PKIX_CertSelector_MatchCallback matchCallback;
+ PKIX_ComCertSelParams *params;
+ PKIX_PL_Object *context;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_CertSelector_Select(
+ PKIX_CertSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext);
+
+PKIX_Error *pkix_CertSelector_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTSELECTOR_H */
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c
new file mode 100644
index 0000000000..a62f78d231
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c
@@ -0,0 +1,1188 @@
+/* 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_comcertselparams.c
+ *
+ * ComCertSelParams Object Functions
+ *
+ */
+
+#include "pkix_comcertselparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCertSelParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a comCertSelParams object */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCERTSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCERTSELPARAMS);
+
+ params = (PKIX_ComCertSelParams *)object;
+
+ PKIX_DECREF(params->subject);
+ PKIX_DECREF(params->policies);
+ PKIX_DECREF(params->cert);
+ PKIX_DECREF(params->nameConstraints);
+ PKIX_DECREF(params->pathToNames);
+ PKIX_DECREF(params->subjAltNames);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->extKeyUsage);
+ PKIX_DECREF(params->certValid);
+ PKIX_DECREF(params->issuer);
+ PKIX_DECREF(params->serialNumber);
+ PKIX_DECREF(params->authKeyId);
+ PKIX_DECREF(params->subjKeyId);
+ PKIX_DECREF(params->subjPubKey);
+ PKIX_DECREF(params->subjPKAlgId);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCertSelParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_ComCertSelParams *paramsDuplicate = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCERTSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCERTSELPARAMS);
+
+ params = (PKIX_ComCertSelParams *)object;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create(&paramsDuplicate, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ paramsDuplicate->minPathLength = params->minPathLength;
+ paramsDuplicate->matchAllSubjAltNames = params->matchAllSubjAltNames;
+
+ PKIX_DUPLICATE(params->subject, &paramsDuplicate->subject, plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->policies, &paramsDuplicate->policies, plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (params->cert){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)params->cert,
+ (PKIX_PL_Object **)&paramsDuplicate->cert,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ PKIX_DUPLICATE
+ (params->nameConstraints,
+ &paramsDuplicate->nameConstraints,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->pathToNames,
+ &paramsDuplicate->pathToNames,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->subjAltNames,
+ &paramsDuplicate->subjAltNames,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (params->date){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)params->date,
+ (PKIX_PL_Object **)&paramsDuplicate->date,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ paramsDuplicate->keyUsage = params->keyUsage;
+
+ PKIX_DUPLICATE(params->certValid,
+ &paramsDuplicate->certValid,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->issuer,
+ &paramsDuplicate->issuer,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->serialNumber,
+ &paramsDuplicate->serialNumber,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->authKeyId,
+ &paramsDuplicate->authKeyId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjKeyId,
+ &paramsDuplicate->subjKeyId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjPubKey,
+ &paramsDuplicate->subjPubKey,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjPKAlgId,
+ &paramsDuplicate->subjPKAlgId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->leafCertFlag = params->leafCertFlag;
+
+ *pNewObject = (PKIX_PL_Object *)paramsDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(paramsDuplicate);
+ }
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_COMCERTSELPARAMS_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_ComCertSelParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_COMCERTSELPARAMS_TYPE];
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_RegisterSelf");
+
+ entry->description = "ComCertSelParams";
+ entry->typeObjectSize = sizeof(PKIX_ComCertSelParams);
+ entry->destructor = pkix_ComCertSelParams_Destroy;
+ entry->duplicateFunction = pkix_ComCertSelParams_Duplicate;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_Create (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_Create(
+ PKIX_ComCertSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCERTSELPARAMS_TYPE,
+ sizeof (PKIX_ComCertSelParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATECOMMONCERTSELPARAMSOBJECT);
+
+ /* initialize fields */
+ params->version = 0xFFFFFFFF;
+ params->minPathLength = -1;
+ params->matchAllSubjAltNames = PKIX_TRUE;
+ params->subject = NULL;
+ params->policies = NULL;
+ params->cert = NULL;
+ params->nameConstraints = NULL;
+ params->pathToNames = NULL;
+ params->subjAltNames = NULL;
+ params->extKeyUsage = NULL;
+ params->keyUsage = 0;
+ params->extKeyUsage = NULL;
+ params->keyUsage = 0;
+ params->date = NULL;
+ params->certValid = NULL;
+ params->issuer = NULL;
+ params->serialNumber = NULL;
+ params->authKeyId = NULL;
+ params->subjKeyId = NULL;
+ params->subjPubKey = NULL;
+ params->subjPKAlgId = NULL;
+ params->leafCertFlag = PKIX_FALSE;
+
+ *pParams = params;
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubject (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pSubject,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubject");
+ PKIX_NULLCHECK_TWO(params, pSubject);
+
+ PKIX_INCREF(params->subject);
+
+ *pSubject = params->subject;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubject (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *subject,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubject");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subject);
+
+ PKIX_INCREF(subject);
+
+ params->subject = subject;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetBasicConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 *pMinPathLength,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetBasicConstraints");
+ PKIX_NULLCHECK_TWO(params, pMinPathLength);
+
+ *pMinPathLength = params->minPathLength;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetBasicConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 minPathLength,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetBasicConstraints");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->minPathLength = minPathLength;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPolicy (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pPolicy, /* List of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPolicy");
+ PKIX_NULLCHECK_TWO(params, pPolicy);
+
+ PKIX_INCREF(params->policies);
+ *pPolicy = params->policies;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPolicy (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *policy, /* List of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPolicy");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->policies);
+ PKIX_INCREF(policy);
+ params->policies = policy;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificate
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetCertificate");
+ PKIX_NULLCHECK_TWO(params, pCert);
+
+ PKIX_INCREF(params->cert);
+ *pCert = params->cert;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificate
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetCertificate");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->cert);
+ PKIX_INCREF(cert);
+ params->cert = cert;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificateValid
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetCertificateValid");
+
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificateValid
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetCertificateValid");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->date);
+ PKIX_INCREF(date);
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetNameConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetNameConstraints");
+ PKIX_NULLCHECK_TWO(params, pNameConstraints);
+
+ PKIX_INCREF(params->nameConstraints);
+
+ *pNameConstraints = params->nameConstraints;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetNameConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetNameConstraints");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->nameConstraints);
+ PKIX_INCREF(nameConstraints);
+ params->nameConstraints = nameConstraints;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPathToNames
+ * (see comments in pkix_certsel.h)
+ */PKIX_Error *
+PKIX_ComCertSelParams_GetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_NULLCHECK_TWO(params, pNames);
+
+ PKIX_INCREF(params->pathToNames);
+
+ *pNames = params->pathToNames;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPathToNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->pathToNames);
+ PKIX_INCREF(names);
+
+ params->pathToNames = names;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddPathToName
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddPathToName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *name,
+ void *plContext)
+{
+ PKIX_List *pathToNamesList = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddPathToName");
+ PKIX_NULLCHECK_ONE(params);
+
+ if (name == NULL) {
+ goto cleanup;
+ }
+
+ if (params->pathToNames == NULL) {
+ /* Create a list for name item */
+ PKIX_CHECK(PKIX_List_Create(&pathToNamesList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ params->pathToNames = pathToNamesList;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->pathToNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, pNames);
+
+ PKIX_INCREF(params->subjAltNames);
+
+ *pNames = params->subjAltNames;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, names);
+
+ PKIX_DECREF(params->subjAltNames);
+ PKIX_INCREF(names);
+
+ params->subjAltNames = names;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddSubjAltName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *name,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_NULLCHECK_TWO(params, name);
+
+ if (params->subjAltNames == NULL) {
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+ params->subjAltNames = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->subjAltNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS)
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetMatchAllSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, pMatch);
+
+ *pMatch = params->matchAllSubjAltNames;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean match,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->matchAllSubjAltNames = match;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetExtendedKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pExtKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetExtendedKeyUsage");
+ PKIX_NULLCHECK_TWO(params, pExtKeyUsage);
+
+ PKIX_INCREF(params->extKeyUsage);
+ *pExtKeyUsage = params->extKeyUsage;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetExtendedKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *extKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->extKeyUsage);
+ PKIX_INCREF(extKeyUsage);
+
+ params->extKeyUsage = extKeyUsage;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pKeyUsage,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetKeyUsage");
+ PKIX_NULLCHECK_TWO(params, pKeyUsage);
+
+ *pKeyUsage = params->keyUsage;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 keyUsage,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->keyUsage = keyUsage;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetIssuer
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pIssuer,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetIssuer");
+ PKIX_NULLCHECK_TWO(params, pIssuer);
+
+ PKIX_INCREF(params->issuer);
+ *pIssuer = params->issuer;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetIssuer
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *issuer,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetIssuer");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->issuer);
+ PKIX_INCREF(issuer);
+ params->issuer = issuer;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSerialNumber
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt **pSerialNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSerialNumber");
+ PKIX_NULLCHECK_TWO(params, pSerialNumber);
+
+ PKIX_INCREF(params->serialNumber);
+ *pSerialNumber = params->serialNumber;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSerialNumber
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt *serialNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->serialNumber);
+ PKIX_INCREF(serialNumber);
+ params->serialNumber = serialNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetVersion
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetVersion");
+ PKIX_NULLCHECK_TWO(params, pVersion);
+
+ *pVersion = params->version;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetVersion
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 version,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetVersion");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->version = version;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetSubjKeyIdentifier");
+ PKIX_NULLCHECK_TWO(params, pSubjKeyId);
+
+ PKIX_INCREF(params->subjKeyId);
+
+ *pSubjKeyId = params->subjKeyId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *subjKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetSubjKeyIdentifier");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjKeyId);
+ PKIX_INCREF(subjKeyId);
+
+ params->subjKeyId = subjKeyId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetAuthorityKeyIdentifier");
+ PKIX_NULLCHECK_TWO(params, pAuthKeyId);
+
+ PKIX_INCREF(params->authKeyId);
+
+ *pAuthKeyId = params->authKeyId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetAuthorityKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *authKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetAuthKeyIdentifier");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->authKeyId);
+ PKIX_INCREF(authKeyId);
+
+ params->authKeyId = authKeyId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPubKey
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey **pSubjPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPubKey");
+ PKIX_NULLCHECK_TWO(params, pSubjPubKey);
+
+ PKIX_INCREF(params->subjPubKey);
+
+ *pSubjPubKey = params->subjPubKey;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPubKey
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey *subjPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjPubKey);
+ PKIX_INCREF(subjPubKey);
+
+ params->subjPubKey = subjPubKey;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPKAlgId
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID **pAlgId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPKAlgId");
+ PKIX_NULLCHECK_TWO(params, pAlgId);
+
+ PKIX_INCREF(params->subjPKAlgId);
+
+ *pAlgId = params->subjPKAlgId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPKAlgId
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID *algId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjPKAlgId);
+ PKIX_INCREF(algId);
+
+ params->subjPKAlgId = algId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetLeafCertFlag
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error*
+PKIX_ComCertSelParams_GetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pLeafFlag,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetLeafCertFlag");
+ PKIX_NULLCHECK_TWO(params, pLeafFlag);
+
+ *pLeafFlag = params->leafCertFlag;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetLeafCertFlag
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean leafFlag,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetLeafCertFlag");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->leafCertFlag = leafFlag;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h
new file mode 100644
index 0000000000..935c639f0a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h
@@ -0,0 +1,57 @@
+/* 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_comcertselparams.h
+ *
+ * ComCertSelParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_COMCERTSELPARAMS_H
+#define _PKIX_COMCERTSELPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * pathToNamesConstraint is Name Constraints generated based on the
+ * pathToNames. We save a cached copy to save regeneration for each
+ * check. SubjAltNames also has its cache, since SubjAltNames are
+ * verified by checker, its cache copy is stored in checkerstate.
+ */
+struct PKIX_ComCertSelParamsStruct {
+ PKIX_Int32 version;
+ PKIX_Int32 minPathLength;
+ PKIX_Boolean matchAllSubjAltNames;
+ PKIX_PL_X500Name *subject;
+ PKIX_List *policies; /* List of PKIX_PL_OID */
+ PKIX_PL_Cert *cert;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_List *pathToNames; /* List of PKIX_PL_GeneralNames */
+ PKIX_List *subjAltNames; /* List of PKIX_PL_GeneralNames */
+ PKIX_List *extKeyUsage; /* List of PKIX_PL_OID */
+ PKIX_UInt32 keyUsage;
+ PKIX_PL_Date *date;
+ PKIX_PL_Date *certValid;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_PL_ByteArray *authKeyId;
+ PKIX_PL_ByteArray *subjKeyId;
+ PKIX_PL_PublicKey *subjPubKey;
+ PKIX_PL_OID *subjPKAlgId;
+ PKIX_Boolean leafCertFlag;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ComCertSelParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_COMCERTSELPARAMS_H */
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 */
diff --git a/security/nss/lib/libpkix/pkix/crlsel/Makefile b/security/nss/lib/libpkix/pkix/crlsel/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/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/crlsel/crlsel.gyp b/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp
new file mode 100644
index 0000000000..894569ef6c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp
@@ -0,0 +1,24 @@
+# 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': 'pkixcrlsel',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_comcrlselparams.c',
+ 'pkix_crlselector.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/crlsel/exports.gyp b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp
new file mode 100644
index 0000000000..a7001ffed7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp
@@ -0,0 +1,26 @@
+# 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_crlsel_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_comcrlselparams.h',
+ 'pkix_crlselector.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/manifest.mn b/security/nss/lib/libpkix/pkix/crlsel/manifest.mn
new file mode 100644
index 0000000000..fe84a2d62f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/manifest.mn
@@ -0,0 +1,20 @@
+#
+# 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_comcrlselparams.h \
+ pkix_crlselector.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_crlselector.c \
+ pkix_comcrlselparams.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixcrlsel
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c
new file mode 100644
index 0000000000..90380c5b2b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c
@@ -0,0 +1,826 @@
+/* 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_comcrlselparams.c
+ *
+ * ComCRLSelParams Function Definitions
+ *
+ */
+
+#include "pkix_comcrlselparams.h"
+
+/* --ComCRLSelParams-Private-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_ComCrlSelParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ params = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_DECREF(params->issuerNames);
+ PKIX_DECREF(params->cert);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->maxCRLNumber);
+ PKIX_DECREF(params->minCRLNumber);
+ PKIX_DECREF(params->crldpList);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of ComCRLSelParams
+ * pointed to by "crlParams" and stores the result at "pString".
+ *
+ * PARAMETERS
+ * "crlParams"
+ * Address of ComCRLSelParams whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry 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_ComCRLSelParams_ToString_Helper(
+ PKIX_ComCRLSelParams *crlParams,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlIssuerNamesString = NULL;
+ PKIX_PL_String *crlDateString = NULL;
+ PKIX_PL_String *crlMaxCRLNumberString = NULL;
+ PKIX_PL_String *crlMinCRLNumberString = NULL;
+ PKIX_PL_String *crlCertString = NULL;
+ PKIX_PL_String *crlParamsString = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString_Helper");
+ PKIX_NULLCHECK_TWO(crlParams, pString);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tIssuerNames: %s\n"
+ "\tDate: %s\n"
+ "\tmaxCRLNumber: %s\n"
+ "\tminCRLNumber: %s\n"
+ "\tCertificate: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->issuerNames, &crlIssuerNamesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(crlParams->date, &crlDateString, plContext,
+ PKIX_DATETOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->maxCRLNumber, &crlMaxCRLNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->minCRLNumber, &crlMinCRLNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(crlParams->cert, &crlCertString, plContext,
+ PKIX_CERTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlParamsString,
+ plContext,
+ formatString,
+ crlIssuerNamesString,
+ crlDateString,
+ crlMaxCRLNumberString,
+ crlMinCRLNumberString,
+ crlCertString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlParamsString;
+
+cleanup:
+
+ PKIX_DECREF(crlIssuerNamesString);
+ PKIX_DECREF(crlDateString);
+ PKIX_DECREF(crlMaxCRLNumberString);
+ PKIX_DECREF(crlMinCRLNumberString);
+ PKIX_DECREF(crlCertString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlParamsString = NULL;
+ PKIX_ComCRLSelParams *crlParams = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ crlParams = (PKIX_ComCRLSelParams *) object;
+
+ PKIX_CHECK(pkix_ComCRLSelParams_ToString_Helper
+ (crlParams, &crlParamsString, plContext),
+ PKIX_COMCRLSELPARAMSTOSTRINGHELPERFAILED);
+
+ *pString = crlParamsString;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *crlParams = NULL;
+ PKIX_UInt32 namesHash = 0;
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 maxCRLNumberHash = 0;
+ PKIX_UInt32 minCRLNumberHash = 0;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ crlParams = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_HASHCODE(crlParams->issuerNames, &namesHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->cert, &certHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->date, &dateHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->maxCRLNumber, &maxCRLNumberHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->minCRLNumber, &minCRLNumberHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+
+ hash = (((namesHash << 3) + certHash) << 3) + dateHash;
+ hash = (hash << 3) + maxCRLNumberHash + minCRLNumberHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *firstCrlParams = NULL;
+ PKIX_ComCRLSelParams *secondCrlParams = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a ComCRLSelParams */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCOMCRLSELPARAMS);
+
+ firstCrlParams = (PKIX_ComCRLSelParams *)firstObject;
+ secondCrlParams = (PKIX_ComCRLSelParams *)secondObject;
+
+ /*
+ * Since we know firstObject is a ComCRLSelParams, if both references
+ * are identical, they must be equal
+ */
+ if (firstCrlParams == secondCrlParams){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondComCRLSelParams isn't a ComCRLSelParams, we don't
+ * throw an error. We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlParams, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_COMCRLSELPARAMS_TYPE) {
+ goto cleanup;
+ }
+
+ /* Compare Issuer Names */
+ PKIX_EQUALS
+ (firstCrlParams->issuerNames,
+ secondCrlParams->issuerNames,
+ &cmpResult,
+ plContext,
+ PKIX_LISTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Date */
+ PKIX_EQUALS
+ (firstCrlParams->date,
+ secondCrlParams->date,
+ &cmpResult,
+ plContext,
+ PKIX_DATEEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Max CRL Number */
+ PKIX_EQUALS
+ (firstCrlParams->maxCRLNumber,
+ secondCrlParams->maxCRLNumber,
+ &cmpResult,
+ plContext,
+ PKIX_BIGINTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Min CRL Number */
+ PKIX_EQUALS
+ (firstCrlParams->minCRLNumber,
+ secondCrlParams->minCRLNumber,
+ &cmpResult,
+ plContext,
+ PKIX_BIGINTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Cert */
+ PKIX_EQUALS
+ (firstCrlParams->cert,
+ secondCrlParams->cert,
+ &cmpResult,
+ plContext,
+ PKIX_CERTEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *old;
+ PKIX_ComCRLSelParams *new = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ old = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCRLSELPARAMS_TYPE,
+ (PKIX_UInt32)(sizeof (PKIX_ComCRLSelParams)),
+ (PKIX_PL_Object **)&new,
+ plContext),
+ PKIX_OBJECTALLOCFAILED);
+
+ PKIX_DUPLICATE(old->cert, &new->cert, plContext,
+ PKIX_OBJECTDUPLICATECERTFAILED);
+
+ PKIX_DUPLICATE(old->crldpList, &new->crldpList, plContext,
+ PKIX_OBJECTDUPLICATECERTFAILED);
+
+ PKIX_DUPLICATE(old->issuerNames, &new->issuerNames, plContext,
+ PKIX_OBJECTDUPLICATEISSUERNAMESFAILED);
+
+ PKIX_DUPLICATE(old->date, &new->date, plContext,
+ PKIX_OBJECTDUPLICATEDATEFAILED);
+
+ PKIX_DUPLICATE(old->maxCRLNumber, &new->maxCRLNumber, plContext,
+ PKIX_OBJECTDUPLICATEMAXCRLNUMBERFAILED);
+
+ PKIX_DUPLICATE(old->minCRLNumber, &new->minCRLNumber, plContext,
+ PKIX_OBJECTDUPLICATEMINCRLNUMBERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)new;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(new);
+ }
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCrlSelParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_COMCRLSELPARAMS_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_ComCRLSelParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_RegisterSelf");
+
+ entry.description = "ComCRLSelParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ComCRLSelParams);
+ entry.destructor = pkix_ComCRLSelParams_Destroy;
+ entry.equalsFunction = pkix_ComCRLSelParams_Equals;
+ entry.hashcodeFunction = pkix_ComCRLSelParams_Hashcode;
+ entry.toStringFunction = pkix_ComCRLSelParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_ComCRLSelParams_Duplicate;
+
+ systemClasses[PKIX_COMCRLSELPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/* --ComCRLSelParams-Public-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_Create (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_Create(
+ PKIX_ComCRLSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCRLSELPARAMS_TYPE,
+ sizeof (PKIX_ComCRLSelParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATECOMMONCRLSELECTORPARAMSOBJECT);
+
+ /* initialize fields */
+ params->issuerNames = NULL;
+ params->cert = NULL;
+ params->crldpList = NULL;
+ params->date = NULL;
+ params->nistPolicyEnabled = PKIX_TRUE;
+ params->maxCRLNumber = NULL;
+ params->minCRLNumber = NULL;
+
+ *pParams = params;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetIssuerNames (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List **pIssuerNames,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_GetIssuerNames");
+ PKIX_NULLCHECK_TWO(params, pIssuerNames);
+
+ PKIX_INCREF(params->issuerNames);
+
+ *pIssuerNames = params->issuerNames;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetIssuerNames (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *names,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetIssuerNames");
+ PKIX_NULLCHECK_ONE(params); /* allows null for names from spec */
+
+ PKIX_DECREF(params->issuerNames);
+
+ PKIX_INCREF(names); /* if NULL, allows to reset for no action */
+
+ params->issuerNames = names;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_AddIssuerName (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_AddIssuerName(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_X500Name *name,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_AddIssuerName");
+ PKIX_NULLCHECK_ONE(params);
+
+ if (name != NULL) {
+
+ if (params->issuerNames == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+ params->issuerNames = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->issuerNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ }
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetCertificateChecking
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetCertificateChecking");
+ PKIX_NULLCHECK_TWO(params, pCert);
+
+ PKIX_INCREF(params->cert);
+
+ *pCert = params->cert;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetCertificateChecking
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetCertificateChecking");
+ PKIX_NULLCHECK_ONE(params); /* allows cert to be NULL from spec */
+
+ PKIX_DECREF(params->cert);
+
+ PKIX_INCREF(cert);
+
+ params->cert = cert;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetDateAndTime");
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetDateAndTime");
+ PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */
+
+ PKIX_DECREF (params->date);
+
+ PKIX_INCREF(date);
+
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean *pEnabled,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetNISTPolicyEnabled");
+ PKIX_NULLCHECK_TWO(params, pEnabled);
+
+ *pEnabled = params->nistPolicyEnabled;
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean enabled,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetNISTPolicyEnabled");
+ PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */
+
+ params->nistPolicyEnabled = enabled;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMaxCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pMaxCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetMaxCRLNumber");
+ PKIX_NULLCHECK_TWO(params, pMaxCRLNumber);
+
+ PKIX_INCREF(params->maxCRLNumber);
+
+ *pMaxCRLNumber = params->maxCRLNumber;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMaxCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *maxCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetMaxCRLNumber");
+ PKIX_NULLCHECK_ONE(params); /* maxCRLNumber can be NULL - from spec */
+
+ PKIX_DECREF(params->maxCRLNumber);
+
+ PKIX_INCREF(maxCRLNumber);
+
+ params->maxCRLNumber = maxCRLNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMinCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pMinCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetMinCRLNumber");
+ PKIX_NULLCHECK_TWO(params, pMinCRLNumber);
+
+ PKIX_INCREF(params->minCRLNumber);
+
+ *pMinCRLNumber = params->minCRLNumber;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMinCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *minCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetMinCRLNumber");
+ PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */
+
+ PKIX_DECREF(params->minCRLNumber);
+
+ PKIX_INCREF(minCRLNumber);
+
+ params->minCRLNumber = minCRLNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+PKIX_Error*
+PKIX_ComCRLSelParams_SetCrlDp(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *crldpList,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetCrlDp");
+ PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */
+
+ PKIX_INCREF(crldpList);
+ params->crldpList = crldpList;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h
new file mode 100644
index 0000000000..08351375d9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h
@@ -0,0 +1,38 @@
+/* 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_comcrlselparams.h
+ *
+ * ComCrlSelParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_COMCRLSELPARAMS_H
+#define _PKIX_COMCRLSELPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ComCRLSelParamsStruct {
+ PKIX_List *issuerNames; /* list of PKIX_PL_X500Name */
+ PKIX_PL_Cert *cert; /* certificate being checked */
+ PKIX_List *crldpList;
+ PKIX_PL_Date *date;
+ PKIX_Boolean nistPolicyEnabled;
+ PKIX_PL_BigInt *maxCRLNumber;
+ PKIX_PL_BigInt *minCRLNumber;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ComCRLSelParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_COMCRLSELPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c
new file mode 100644
index 0000000000..e9a9c03dfd
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c
@@ -0,0 +1,870 @@
+/* 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_crlselector.c
+ *
+ * CRLSelector Function Definitions
+ *
+ */
+
+#include "pkix_crlselector.h"
+
+/* --CRLSelector Private-Functions-------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CRLSelector_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ selector = (PKIX_CRLSelector *)object;
+
+ selector->matchCallback = NULL;
+
+ PKIX_DECREF(selector->params);
+ PKIX_DECREF(selector->context);
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_ToString_Helper
+ *
+ * DESCRIPTION:
+ * Helper function that creates a string representation of CRLSelector
+ * pointed to by "crlParams" and stores its address in the object pointed to
+ * by "pString".
+ *
+ * PARAMETERS
+ * "list"
+ * Address of CRLSelector whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector 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_CRLSelector_ToString_Helper(
+ PKIX_CRLSelector *crlSelector,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlSelectorString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlParamsString = NULL;
+ PKIX_PL_String *crlContextString = NULL;
+ char *asciiFormat = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString_Helper");
+ PKIX_NULLCHECK_TWO(crlSelector, pString);
+ PKIX_NULLCHECK_ONE(crlSelector->params);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tMatchCallback: 0x%x\n"
+ "\tParams: %s\n"
+ "\tContext: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Params */
+ PKIX_TOSTRING
+ ((PKIX_PL_Object *)crlSelector->params,
+ &crlParamsString,
+ plContext,
+ PKIX_COMCRLSELPARAMSTOSTRINGFAILED);
+
+ /* Context */
+ PKIX_TOSTRING(crlSelector->context, &crlContextString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlSelectorString,
+ plContext,
+ formatString,
+ crlSelector->matchCallback,
+ crlParamsString,
+ crlContextString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlSelectorString;
+
+cleanup:
+
+ PKIX_DECREF(crlParamsString);
+ PKIX_DECREF(crlContextString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlSelectorString = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ crlSelector = (PKIX_CRLSelector *) object;
+
+ PKIX_CHECK(pkix_CRLSelector_ToString_Helper
+ (crlSelector, &crlSelectorString, plContext),
+ PKIX_CRLSELECTORTOSTRINGHELPERFAILED);
+
+ *pString = crlSelectorString;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 paramsHash = 0;
+ PKIX_UInt32 contextHash = 0;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ crlSelector = (PKIX_CRLSelector *)object;
+
+ PKIX_HASHCODE(crlSelector->params, &paramsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlSelector->context, &contextHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * ((PKIX_UInt32)((char *)crlSelector->matchCallback - (char *)NULL) +
+ (contextHash << 3)) + paramsHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_CRLSelector *firstCrlSelector = NULL;
+ PKIX_CRLSelector *secondCrlSelector = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRLSelector */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRLSELECTOR);
+
+ firstCrlSelector = (PKIX_CRLSelector *)firstObject;
+ secondCrlSelector = (PKIX_CRLSelector *)secondObject;
+
+ /*
+ * Since we know firstObject is a CRLSelector, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrlSelector == secondCrlSelector){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCRLSelector isn't a CRLSelector, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlSelector,
+ &secondType,
+ plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CRLSELECTOR_TYPE) {
+ goto cleanup;
+ }
+
+ /* Compare MatchCallback address */
+ cmpResult = (firstCrlSelector->matchCallback ==
+ secondCrlSelector->matchCallback);
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* Compare Common CRL Selector Params */
+ PKIX_EQUALS
+ (firstCrlSelector->params,
+ secondCrlSelector->params,
+ &cmpResult,
+ plContext,
+ PKIX_COMCRLSELPARAMSEQUALSFAILED);
+
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* Compare Context */
+ PKIX_EQUALS
+ (firstCrlSelector->context,
+ secondCrlSelector->context,
+ &cmpResult,
+ plContext,
+ PKIX_COMCRLSELPARAMSEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CRLSelector *old;
+ PKIX_CRLSelector *new = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ old = (PKIX_CRLSelector *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLSELECTOR_TYPE,
+ (PKIX_UInt32)(sizeof (PKIX_CRLSelector)),
+ (PKIX_PL_Object **)&new,
+ plContext),
+ PKIX_CREATECRLSELECTORDUPLICATEOBJECTFAILED);
+
+ new->matchCallback = old->matchCallback;
+
+ PKIX_DUPLICATE(old->params, &new->params, plContext,
+ PKIX_OBJECTDUPLICATEPARAMSFAILED);
+
+ PKIX_DUPLICATE(old->context, &new->context, plContext,
+ PKIX_OBJECTDUPLICATECONTEXTFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)new;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(new);
+ }
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_DefaultMatch
+ *
+ * DESCRIPTION:
+ * This function compares the parameter values (Issuer, date, and CRL number)
+ * set in the ComCRLSelParams of the CRLSelector pointed to by "selector" with
+ * the corresponding values in the CRL pointed to by "crl". When all the
+ * criteria set in the parameter values match the values in "crl", PKIX_TRUE is
+ * stored at "pMatch". If the CRL does not match the CRLSelector's criteria,
+ * PKIX_FALSE is stored at "pMatch".
+ *
+ * PARAMETERS
+ * "selector"
+ * Address of CRLSelector which is verified for a match
+ * Must be non-NULL.
+ * "crl"
+ * Address of the CRL object to be verified. Must be non-NULL.
+ * "pMatch"
+ * Address at which Boolean result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector 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_CRLSelector_DefaultMatch(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+ PKIX_PL_X500Name *crlIssuerName = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_List *selIssuerNames = NULL;
+ PKIX_PL_Date *selDate = NULL;
+ PKIX_Boolean result = PKIX_TRUE;
+ PKIX_UInt32 numIssuers = 0;
+ PKIX_UInt32 i;
+ PKIX_PL_BigInt *minCRLNumber = NULL;
+ PKIX_PL_BigInt *maxCRLNumber = NULL;
+ PKIX_PL_BigInt *crlNumber = NULL;
+ PKIX_Boolean nistPolicyEnabled = PKIX_FALSE;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_DefaultMatch");
+ PKIX_NULLCHECK_TWO(selector, crl);
+
+ *pMatch = PKIX_TRUE;
+ params = selector->params;
+
+ /* No matching parameter provided, just a match */
+ if (params == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
+ (params, &selIssuerNames, plContext),
+ PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);
+
+ /* Check for Issuers */
+ if (selIssuerNames != NULL){
+
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_CRL_GetIssuer
+ (crl, &crlIssuerName, plContext),
+ PKIX_CRLGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (selIssuerNames, &numIssuers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numIssuers; i++){
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (selIssuerNames,
+ i,
+ (PKIX_PL_Object **)&issuerName,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (crlIssuerName,
+ issuerName,
+ &result,
+ plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ PKIX_DECREF(issuerName);
+
+ if (result == PKIX_TRUE) {
+ break;
+ }
+ }
+
+ if (result == PKIX_FALSE) {
+ PKIX_CRLSELECTOR_DEBUG("Issuer Match Failed\N");
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetDateAndTime
+ (params, &selDate, plContext),
+ PKIX_COMCRLSELPARAMSGETDATEANDTIMEFAILED);
+
+ /* Check for Date */
+ if (selDate != NULL){
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetNISTPolicyEnabled
+ (params, &nistPolicyEnabled, plContext),
+ PKIX_COMCRLSELPARAMSGETNISTPOLICYENABLEDFAILED);
+
+ /* check crl dates only for if NIST policies enforced */
+ if (nistPolicyEnabled) {
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_CRL_VerifyUpdateTime
+ (crl, selDate, &result, plContext),
+ PKIX_CRLVERIFYUPDATETIMEFAILED);
+
+ if (result == PKIX_FALSE) {
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ }
+
+ /* Check for CRL number in range */
+ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber(crl, &crlNumber, plContext),
+ PKIX_CRLGETCRLNUMBERFAILED);
+
+ if (crlNumber != NULL) {
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetMinCRLNumber
+ (params, &minCRLNumber, plContext),
+ PKIX_COMCRLSELPARAMSGETMINCRLNUMBERFAILED);
+
+ if (minCRLNumber != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)minCRLNumber,
+ (PKIX_PL_Object *)crlNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (result == 1) {
+ PKIX_CRLSELECTOR_DEBUG
+ ("CRL MinNumber Range Match Failed\n");
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetMaxCRLNumber
+ (params, &maxCRLNumber, plContext),
+ PKIX_COMCRLSELPARAMSGETMAXCRLNUMBERFAILED);
+
+ if (maxCRLNumber != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)crlNumber,
+ (PKIX_PL_Object *)maxCRLNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (result == 1) {
+ PKIX_CRLSELECTOR_DEBUG
+ (PKIX_CRLMAXNUMBERRANGEMATCHFAILED);
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selIssuerNames);
+ PKIX_DECREF(selDate);
+ PKIX_DECREF(crlIssuerName);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(crlNumber);
+ PKIX_DECREF(minCRLNumber);
+ PKIX_DECREF(maxCRLNumber);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CRLSELECTOR_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_CRLSelector_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_RegisterSelf");
+
+ entry.description = "CRLSelector";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CRLSelector);
+ entry.destructor = pkix_CRLSelector_Destroy;
+ entry.equalsFunction = pkix_CRLSelector_Equals;
+ entry.hashcodeFunction = pkix_CRLSelector_Hashcode;
+ entry.toStringFunction = pkix_CRLSelector_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CRLSelector_Duplicate;
+
+ systemClasses[PKIX_CRLSELECTOR_TYPE] = entry;
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/* --CRLSelector-Public-Functions---------------------------------------- */
+PKIX_Error *
+pkix_CRLSelector_Create(
+ PKIX_CRLSelector_MatchCallback callback,
+ PKIX_PL_Object *crlSelectorContext,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Create");
+ PKIX_NULLCHECK_ONE(pSelector);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLSELECTOR_TYPE,
+ sizeof (PKIX_CRLSelector),
+ (PKIX_PL_Object **)&selector,
+ plContext),
+ PKIX_COULDNOTCREATECRLSELECTOROBJECT);
+
+ /*
+ * if user specified a particular match callback, we use that one.
+ * otherwise, we use the default match provided.
+ */
+
+ if (callback != NULL){
+ selector->matchCallback = callback;
+ } else {
+ selector->matchCallback = pkix_CRLSelector_DefaultMatch;
+ }
+
+ /* initialize other fields */
+ selector->params = NULL;
+
+ PKIX_INCREF(crlSelectorContext);
+ selector->context = crlSelectorContext;
+
+ *pSelector = selector;
+ selector = NULL;
+
+cleanup:
+
+ PKIX_DECREF(selector);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_Create (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_Create(
+ PKIX_PL_Cert *issuer,
+ PKIX_List *crldpList,
+ PKIX_PL_Date *date,
+ PKIX_CRLSelector **pCrlSelector,
+ void *plContext)
+{
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CrlSelector_Create");
+ PKIX_NULLCHECK_ONE(issuer);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetSubject(issuer, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (date != NULL) {
+ PKIX_INCREF(date);
+ nowDate = date;
+ } else {
+ PKIX_CHECK(
+ PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+ }
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_Create(&comCrlSelParams, plContext),
+ PKIX_COMCRLSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_AddIssuerName(comCrlSelParams, issuerName,
+ plContext),
+ PKIX_COMCRLSELPARAMSADDISSUERNAMEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_SetCrlDp(comCrlSelParams, crldpList,
+ plContext),
+ PKIX_COMCRLSELPARAMSSETCERTFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_SetDateAndTime(comCrlSelParams, nowDate,
+ plContext),
+ PKIX_COMCRLSELPARAMSSETDATEANDTIMEFAILED);
+
+ PKIX_CHECK(
+ pkix_CRLSelector_Create(NULL, NULL, &crlSelector, plContext),
+ PKIX_CRLSELECTORCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_CRLSelector_SetCommonCRLSelectorParams(crlSelector,
+ comCrlSelParams,
+ plContext),
+ PKIX_CRLSELECTORSETCOMMONCRLSELECTORPARAMSFAILED);
+
+ *pCrlSelector = crlSelector;
+ crlSelector = NULL;
+
+cleanup:
+
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(nowDate);
+ PKIX_DECREF(comCrlSelParams);
+ PKIX_DECREF(crlSelector);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetMatchCallback (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_CRLSelector_MatchCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetMatchCallback");
+ PKIX_NULLCHECK_TWO(selector, pCallback);
+
+ *pCallback = selector->matchCallback;
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCRLSelectorContext
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCRLSelectorContext(
+ PKIX_CRLSelector *selector,
+ void **pCrlSelectorContext,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCRLSelectorContext");
+ PKIX_NULLCHECK_TWO(selector, pCrlSelectorContext);
+
+ PKIX_INCREF(selector->context);
+
+ *pCrlSelectorContext = selector->context;
+
+cleanup:
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCommonCRLSelectorParams
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCommonCRLSelectorParams");
+ PKIX_NULLCHECK_TWO(selector, pParams);
+
+ PKIX_INCREF(selector->params);
+
+ *pParams = selector->params;
+
+cleanup:
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_SetCommonCRLSelectorParams
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_SetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams *params,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_SetCommonCRLSelectorParams");
+ PKIX_NULLCHECK_TWO(selector, params);
+
+ PKIX_DECREF(selector->params);
+
+ PKIX_INCREF(params);
+ selector->params = params;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)selector, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Select
+ * DESCRIPTION:
+ *
+ * This function applies the selector pointed to by "selector" to each CRL,
+ * in turn, in the List pointed to by "before", and creates a List containing
+ * all the CRLs that matched, or passed the selection process, storing that
+ * List at "pAfter". If no CRLs match, an empty List is stored at "pAfter".
+ *
+ * The List returned in "pAfter" is immutable.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelelector to be applied to the List. Must be non-NULL.
+ * "before"
+ * Address of List that is to be filtered. Must be non-NULL.
+ * "pAfter"
+ * Address at which resulting List, possibly empty, is 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 CRLSelector 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_CRLSelector_Select(
+ PKIX_CRLSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext)
+{
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_UInt32 numBefore = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *filtered = NULL;
+ PKIX_PL_CRL *candidate = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Select");
+ PKIX_NULLCHECK_THREE(selector, before, pAfter);
+
+ PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numBefore; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (before, i, (PKIX_PL_Object **)&candidate, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(selector->matchCallback
+ (selector, candidate, &match, plContext),
+ PKIX_CRLSELECTORMATCHCALLBACKFAILED);
+
+ if (!(PKIX_ERROR_RECEIVED) && match == PKIX_TRUE) {
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (filtered,
+ (PKIX_PL_Object *)candidate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(candidate);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* Don't throw away the list if one CRL was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pAfter = filtered;
+ filtered = NULL;
+
+cleanup:
+
+ PKIX_DECREF(filtered);
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CRLSELECTOR);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h
new file mode 100644
index 0000000000..4f44cc7683
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h
@@ -0,0 +1,40 @@
+/* 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_crlselector.h
+ *
+ * CrlSelector Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CRLSELECTOR_H
+#define _PKIX_CRLSELECTOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CRLSelectorStruct {
+ PKIX_CRLSelector_MatchCallback matchCallback;
+ PKIX_ComCRLSelParams *params;
+ PKIX_PL_Object *context;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CRLSelector_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_CRLSelector_Select(
+ PKIX_CRLSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CRLSELECTOR_H */
diff --git a/security/nss/lib/libpkix/pkix/manifest.mn b/security/nss/lib/libpkix/pkix/manifest.mn
new file mode 100644
index 0000000000..dcb6f0ce61
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/manifest.mn
@@ -0,0 +1,11 @@
+#
+# 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 = ../../..
+DEPTH = ../../..
+
+#
+DIRS = certsel crlsel checker params results store top util \
+ $(NULL)
+
diff --git a/security/nss/lib/libpkix/pkix/params/Makefile b/security/nss/lib/libpkix/pkix/params/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/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/params/exports.gyp b/security/nss/lib/libpkix/pkix/params/exports.gyp
new file mode 100644
index 0000000000..921f2ceae3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/exports.gyp
@@ -0,0 +1,28 @@
+# 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_params_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_procparams.h',
+ 'pkix_resourcelimits.h',
+ 'pkix_trustanchor.h',
+ 'pkix_valparams.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/params/manifest.mn b/security/nss/lib/libpkix/pkix/params/manifest.mn
new file mode 100644
index 0000000000..2a77bf0eea
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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_procparams.h \
+ pkix_trustanchor.h \
+ pkix_valparams.h \
+ pkix_resourcelimits.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_trustanchor.c \
+ pkix_procparams.c \
+ pkix_valparams.c \
+ pkix_resourcelimits.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixparams
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/params/params.gyp b/security/nss/lib/libpkix/pkix/params/params.gyp
new file mode 100644
index 0000000000..a1463c4c7c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/params.gyp
@@ -0,0 +1,26 @@
+# 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': 'pkixparams',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_procparams.c',
+ 'pkix_resourcelimits.c',
+ 'pkix_trustanchor.c',
+ 'pkix_valparams.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.c b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c
new file mode 100644
index 0000000000..260b0074c7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c
@@ -0,0 +1,1417 @@
+/* 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_procparams.c
+ *
+ * ProcessingParams Object Functions
+ *
+ */
+
+#include "pkix_procparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a processing params object */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ params = (PKIX_ProcessingParams *)object;
+
+ PKIX_DECREF(params->trustAnchors);
+ PKIX_DECREF(params->hintCerts);
+ PKIX_DECREF(params->constraints);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->initialPolicies);
+ PKIX_DECREF(params->certChainCheckers);
+ PKIX_DECREF(params->revChecker);
+ PKIX_DECREF(params->certStores);
+ PKIX_DECREF(params->resourceLimits);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ProcessingParams *firstProcParams = NULL;
+ PKIX_ProcessingParams *secondProcParams = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPROCESSINGPARAMS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_PROCESSINGPARAMS_TYPE) goto cleanup;
+
+ firstProcParams = (PKIX_ProcessingParams *)first;
+ secondProcParams = (PKIX_ProcessingParams *)second;
+
+ /* Do the simplest tests first */
+ if ((firstProcParams->qualifiersRejected) !=
+ (secondProcParams->qualifiersRejected)) {
+ goto cleanup;
+ }
+
+ if (firstProcParams->isCrlRevocationCheckingEnabled !=
+ secondProcParams->isCrlRevocationCheckingEnabled) {
+ goto cleanup;
+ }
+ if (firstProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy !=
+ secondProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy) {
+ goto cleanup;
+ }
+
+ /* trustAnchors can never be NULL */
+
+ PKIX_EQUALS
+ (firstProcParams->trustAnchors,
+ secondProcParams->trustAnchors,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->hintCerts,
+ secondProcParams->hintCerts,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->date,
+ secondProcParams->date,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->constraints,
+ secondProcParams->constraints,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->initialPolicies,
+ secondProcParams->initialPolicies,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ /* There is no Equals function for CertChainCheckers */
+
+ PKIX_EQUALS
+ ((PKIX_PL_Object *)firstProcParams->certStores,
+ (PKIX_PL_Object *)secondProcParams->certStores,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->resourceLimits,
+ secondProcParams->resourceLimits,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult == PKIX_FALSE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 anchorsHash = 0;
+ PKIX_UInt32 hintCertsHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 constraintsHash = 0;
+ PKIX_UInt32 initialHash = 0;
+ PKIX_UInt32 rejectedHash = 0;
+ PKIX_UInt32 certChainCheckersHash = 0;
+ PKIX_UInt32 revCheckerHash = 0;
+ PKIX_UInt32 certStoresHash = 0;
+ PKIX_UInt32 resourceLimitsHash = 0;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ procParams = (PKIX_ProcessingParams*)object;
+
+ PKIX_HASHCODE(procParams->trustAnchors, &anchorsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->hintCerts, &hintCertsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->date, &dateHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->constraints, &constraintsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->initialPolicies, &initialHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ rejectedHash = procParams->qualifiersRejected;
+
+ /* There is no Hash function for CertChainCheckers */
+
+ PKIX_HASHCODE(procParams->certStores, &certStoresHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->resourceLimits,
+ &resourceLimitsHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = (31 * ((31 * anchorsHash) + hintCertsHash + dateHash)) +
+ constraintsHash + initialHash + rejectedHash;
+
+ hash += ((((certStoresHash + resourceLimitsHash) << 7) +
+ certChainCheckersHash + revCheckerHash +
+ procParams->isCrlRevocationCheckingEnabled +
+ procParams->isCrlRevocationCheckingEnabledWithNISTPolicy) << 7);
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *procParamsString = NULL;
+ PKIX_PL_String *anchorsString = NULL;
+ PKIX_PL_String *dateString = NULL;
+ PKIX_PL_String *constraintsString = NULL;
+ PKIX_PL_String *InitialPoliciesString = NULL;
+ PKIX_PL_String *qualsRejectedString = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_PL_String *certStoresString = NULL;
+ PKIX_PL_String *resourceLimitsString = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ asciiFormat =
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t%s\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\t%s\n"
+ "\tTarget Constraints: %s\n"
+ "\tInitial Policies: %s\n"
+ "\tQualifiers Rejected: %s\n"
+ "\tCert Stores: %s\n"
+ "\tResource Limits: %s\n"
+ "\tCRL Checking Enabled: %d\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ procParams = (PKIX_ProcessingParams*)object;
+
+ PKIX_TOSTRING(procParams->trustAnchors, &anchorsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->date, &dateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->constraints, &constraintsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (procParams->initialPolicies, &InitialPoliciesString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (procParams->qualifiersRejected)?"TRUE":"FALSE",
+ 0,
+ &qualsRejectedString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* There is no ToString function for CertChainCheckers */
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_TOSTRING(certStores, &certStoresString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->resourceLimits,
+ &resourceLimitsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&procParamsString,
+ plContext,
+ formatString,
+ anchorsString,
+ dateString,
+ constraintsString,
+ InitialPoliciesString,
+ qualsRejectedString,
+ certStoresString,
+ resourceLimitsString,
+ procParams->isCrlRevocationCheckingEnabled,
+ procParams->isCrlRevocationCheckingEnabledWithNISTPolicy),
+ PKIX_SPRINTFFAILED);
+
+ *pString = procParamsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(anchorsString);
+ PKIX_DECREF(dateString);
+ PKIX_DECREF(constraintsString);
+ PKIX_DECREF(InitialPoliciesString);
+ PKIX_DECREF(qualsRejectedString);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(certStoresString);
+ PKIX_DECREF(resourceLimitsString);
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+ PKIX_ProcessingParams *paramsDuplicate = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ params = (PKIX_ProcessingParams *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PROCESSINGPARAMS_TYPE,
+ sizeof (PKIX_ProcessingParams),
+ (PKIX_PL_Object **)&paramsDuplicate,
+ plContext),
+ PKIX_PROCESSINGPARAMSCREATEFAILED);
+
+ /* initialize fields */
+ PKIX_DUPLICATE
+ (params->trustAnchors,
+ &(paramsDuplicate->trustAnchors),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->hintCerts, &(paramsDuplicate->hintCerts), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->constraints,
+ &(paramsDuplicate->constraints),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->date, &(paramsDuplicate->date), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->initialPolicies,
+ &(paramsDuplicate->initialPolicies),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->initialPolicyMappingInhibit =
+ params->initialPolicyMappingInhibit;
+ paramsDuplicate->initialAnyPolicyInhibit =
+ params->initialAnyPolicyInhibit;
+ paramsDuplicate->initialExplicitPolicy = params->initialExplicitPolicy;
+ paramsDuplicate->qualifiersRejected = params->qualifiersRejected;
+
+ PKIX_DUPLICATE
+ (params->certChainCheckers,
+ &(paramsDuplicate->certChainCheckers),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->revChecker,
+ &(paramsDuplicate->revChecker),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->certStores, &(paramsDuplicate->certStores), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->resourceLimits,
+ &(paramsDuplicate->resourceLimits),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->isCrlRevocationCheckingEnabled =
+ params->isCrlRevocationCheckingEnabled;
+
+ paramsDuplicate->isCrlRevocationCheckingEnabledWithNISTPolicy =
+ params->isCrlRevocationCheckingEnabledWithNISTPolicy;
+
+ *pNewObject = (PKIX_PL_Object *)paramsDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(paramsDuplicate);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PROCESSINGPARAMS_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_ProcessingParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_RegisterSelf");
+
+ entry.description = "ProcessingParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ProcessingParams);
+ entry.destructor = pkix_ProcessingParams_Destroy;
+ entry.equalsFunction = pkix_ProcessingParams_Equals;
+ entry.hashcodeFunction = pkix_ProcessingParams_Hashcode;
+ entry.toStringFunction = pkix_ProcessingParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_ProcessingParams_Duplicate;
+
+ systemClasses[PKIX_PROCESSINGPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_Create(
+ PKIX_ProcessingParams **pParams,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PROCESSINGPARAMS_TYPE,
+ sizeof (PKIX_ProcessingParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATEPROCESSINGPARAMSOBJECT);
+
+ /* initialize fields */
+ PKIX_CHECK(PKIX_List_Create(&params->trustAnchors, plContext),
+ PKIX_LISTCREATEFAILED);
+ PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &params->date, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+
+ params->hintCerts = NULL;
+ params->constraints = NULL;
+ params->initialPolicies = NULL;
+ params->initialPolicyMappingInhibit = PKIX_FALSE;
+ params->initialAnyPolicyInhibit = PKIX_FALSE;
+ params->initialExplicitPolicy = PKIX_FALSE;
+ params->qualifiersRejected = PKIX_FALSE;
+ params->certChainCheckers = NULL;
+ params->revChecker = NULL;
+ params->certStores = NULL;
+ params->resourceLimits = NULL;
+
+ params->isCrlRevocationCheckingEnabled = PKIX_TRUE;
+
+ params->isCrlRevocationCheckingEnabledWithNISTPolicy = PKIX_TRUE;
+
+ params->useAIAForCertFetching = PKIX_FALSE;
+ params->qualifyTargetCert = PKIX_TRUE;
+ params->useOnlyTrustAnchors = PKIX_TRUE;
+
+ *pParams = params;
+ params = NULL;
+
+cleanup:
+
+ PKIX_DECREF(params);
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetUseAIAForCertFetching
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseAIA, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetUseAIAForCertFetching");
+ PKIX_NULLCHECK_TWO(params, pUseAIA);
+
+ *pUseAIA = params->useAIAForCertFetching;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetUseAIAForCertFetching
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useAIA,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetUseAIAForCertFetching");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->useAIAForCertFetching = useAIA;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetQualifyTargetCert
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetValidateTargetCert(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pQualifyTargetCert,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetValidateTargetCert");
+ PKIX_NULLCHECK_TWO(params, pQualifyTargetCert);
+
+ *pQualifyTargetCert = params->qualifyTargetCert;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetQualifyTargetCert
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetQualifyTargetCert(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean qualifyTargetCert,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetQualifyTargetCert");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->qualifyTargetCert = qualifyTargetCert;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List *anchors, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetTrustAnchors");
+ PKIX_NULLCHECK_TWO(params, anchors);
+
+ PKIX_DECREF(params->trustAnchors);
+
+ PKIX_INCREF(anchors);
+ params->trustAnchors = anchors;
+ PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pAnchors, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetTrustAnchors");
+ PKIX_NULLCHECK_TWO(params, pAnchors);
+
+ PKIX_INCREF(params->trustAnchors);
+
+ *pAnchors = params->trustAnchors;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/**
+ * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseOnlyTrustAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetUseTrustAnchorsOnly");
+ PKIX_NULLCHECK_TWO(params, pUseOnlyTrustAnchors);
+
+ *pUseOnlyTrustAnchors = params->useOnlyTrustAnchors;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/**
+ * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useOnlyTrustAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetUseTrustAnchorsOnly");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->useOnlyTrustAnchors = useOnlyTrustAnchors;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetDate (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetDate");
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetDate (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetDate");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->date);
+
+ PKIX_INCREF(date);
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->date);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTargetCertConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector **pConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetTargetCertConstraints");
+
+ PKIX_NULLCHECK_TWO(params, pConstraints);
+
+ PKIX_INCREF(params->constraints);
+ *pConstraints = params->constraints;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTargetCertConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector *constraints,
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetTargetCertConstraints");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->constraints);
+
+ PKIX_INCREF(constraints);
+ params->constraints = constraints;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->constraints);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetInitialPolicies
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pInitPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetInitialPolicies");
+
+ PKIX_NULLCHECK_TWO(params, pInitPolicies);
+
+ if (params->initialPolicies == NULL) {
+ PKIX_CHECK(PKIX_List_Create
+ (&params->initialPolicies, plContext),
+ PKIX_UNABLETOCREATELIST);
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (params->initialPolicies, plContext),
+ PKIX_UNABLETOMAKELISTIMMUTABLE);
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_INCREF(params->initialPolicies);
+ *pInitPolicies = params->initialPolicies;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetInitialPolicies
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List *initPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetInitialPolicies");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->initialPolicies);
+
+ PKIX_INCREF(initPolicies);
+ params->initialPolicies = initPolicies;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->initialPolicies);
+ }
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRejected,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetPolicyQualifiersRejected");
+
+ PKIX_NULLCHECK_TWO(params, pRejected);
+
+ *pRejected = params->qualifiersRejected;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyQualifiersRejected
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean rejected,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetPolicyQualifiersRejected");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->qualifiersRejected = rejected;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pCheckers, /* list of PKIX_CertChainChecker */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetCertChainCheckers");
+ PKIX_NULLCHECK_TWO(params, pCheckers);
+
+ PKIX_INCREF(params->certChainCheckers);
+ *pCheckers = params->certChainCheckers;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List *checkers, /* list of PKIX_CertChainChecker */
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetCertChainCheckers");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->certChainCheckers);
+
+ PKIX_INCREF(checkers);
+ params->certChainCheckers = checkers;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->certChainCheckers);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertChainChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker *checker,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_AddCertChainChecker");
+ PKIX_NULLCHECK_TWO(params, checker);
+
+ if (params->certChainCheckers == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ params->certChainCheckers = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->certChainCheckers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ list = NULL;
+
+cleanup:
+
+ if (list && params) {
+ PKIX_DECREF(params->certChainCheckers);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetRevocationChecker
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker **pChecker,
+ void *plContext)
+{
+
+ PKIX_ENTER
+ (PROCESSINGPARAMS, "PKIX_ProcessingParams_GetRevocationCheckers");
+ PKIX_NULLCHECK_TWO(params, pChecker);
+
+ PKIX_INCREF(params->revChecker);
+ *pChecker = params->revChecker;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetRevocationChecker
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker *checker,
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_InitRevocationChecker");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->revChecker);
+ PKIX_INCREF(checker);
+ params->revChecker = checker;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertStores
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pStores, /* list of PKIX_CertStore */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetCertStores");
+
+ PKIX_NULLCHECK_TWO(params, pStores);
+
+ if (!params->certStores){
+ PKIX_CHECK(PKIX_List_Create(&params->certStores, plContext),
+ PKIX_UNABLETOCREATELIST);
+ }
+
+ PKIX_INCREF(params->certStores);
+ *pStores = params->certStores;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertStores
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List *stores, /* list of PKIX_CertStore */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetCertStores");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->certStores);
+
+ PKIX_INCREF(stores);
+ params->certStores = stores;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->certStores);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertStore
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertStore(
+ PKIX_ProcessingParams *params,
+ PKIX_CertStore *store,
+ void *plContext)
+{
+ PKIX_List *certStores = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_AddCertStore");
+ PKIX_NULLCHECK_TWO(params, store);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (params, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(certStores);
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetResourceLimits
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits *resourceLimits,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetResourceLimits");
+
+ PKIX_NULLCHECK_TWO(params, resourceLimits);
+
+ PKIX_DECREF(params->resourceLimits);
+ PKIX_INCREF(resourceLimits);
+ params->resourceLimits = resourceLimits;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->resourceLimits);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetResourceLimits
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetResourceLimits");
+
+ PKIX_NULLCHECK_TWO(params, pResourceLimits);
+
+ PKIX_INCREF(params->resourceLimits);
+ *pResourceLimits = params->resourceLimits;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsAnyPolicyInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsAnyPolicyInhibited");
+
+ PKIX_NULLCHECK_TWO(params, pInhibited);
+
+ *pInhibited = params->initialAnyPolicyInhibit;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetAnyPolicyInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetAnyPolicyInhibited");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialAnyPolicyInhibit = inhibited;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsExplicitPolicyRequired
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRequired,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsExplicitPolicyRequired");
+
+ PKIX_NULLCHECK_TWO(params, pRequired);
+
+ *pRequired = params->initialExplicitPolicy;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetExplicitPolicyRequired
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean required,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetExplicitPolicyRequired");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialExplicitPolicy = required;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsPolicyMappingInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsPolicyMappingInhibited");
+
+ PKIX_NULLCHECK_TWO(params, pInhibited);
+
+ *pInhibited = params->initialPolicyMappingInhibit;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyMappingInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetPolicyMappingInhibited");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialPolicyMappingInhibit = inhibited;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetHintCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List *hintCerts,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetHintCerts");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->hintCerts);
+ PKIX_INCREF(hintCerts);
+ params->hintCerts = hintCerts;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->hintCerts);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetHintCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pHintCerts,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetHintCerts");
+
+ PKIX_NULLCHECK_TWO(params, pHintCerts);
+
+ PKIX_INCREF(params->hintCerts);
+ *pHintCerts = params->hintCerts;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.h b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h
new file mode 100644
index 0000000000..599f5d4988
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h
@@ -0,0 +1,50 @@
+/* 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_procparams.h
+ *
+ * ProcessingParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PROCESSINGPARAMS_H
+#define _PKIX_PROCESSINGPARAMS_H
+
+#include "pkix_tools.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ProcessingParamsStruct {
+ PKIX_List *trustAnchors; /* Never NULL */
+ PKIX_List *hintCerts; /* user-supplied partial chain, may be NULL */
+ PKIX_CertSelector *constraints;
+ PKIX_PL_Date *date;
+ PKIX_List *initialPolicies; /* list of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit;
+ PKIX_Boolean initialAnyPolicyInhibit;
+ PKIX_Boolean initialExplicitPolicy;
+ PKIX_Boolean qualifiersRejected;
+ PKIX_List *certChainCheckers;
+ PKIX_List *certStores;
+ PKIX_Boolean isCrlRevocationCheckingEnabled;
+ PKIX_Boolean isCrlRevocationCheckingEnabledWithNISTPolicy;
+ PKIX_RevocationChecker *revChecker;
+ PKIX_ResourceLimits *resourceLimits;
+ PKIX_Boolean useAIAForCertFetching;
+ PKIX_Boolean qualifyTargetCert;
+ PKIX_Boolean useOnlyTrustAnchors;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ProcessingParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PROCESSINGPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c
new file mode 100644
index 0000000000..de93e9d771
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c
@@ -0,0 +1,433 @@
+/* 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_resourcelimits.c
+ *
+ * Resourcelimits Params Object Functions
+ *
+ */
+
+#include "pkix_resourcelimits.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a ResourceLimits object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ rLimits = (PKIX_ResourceLimits *)object;
+
+ rLimits->maxTime = 0;
+ rLimits->maxFanout = 0;
+ rLimits->maxDepth = 0;
+ rLimits->maxCertsNumber = 0;
+ rLimits->maxCrlsNumber = 0;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ResourceLimits *firstRLimits = NULL;
+ PKIX_ResourceLimits *secondRLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTRESOURCELIMITS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_RESOURCELIMITS_TYPE) goto cleanup;
+
+ firstRLimits = (PKIX_ResourceLimits *)first;
+ secondRLimits = (PKIX_ResourceLimits *)second;
+
+ cmpResult = (firstRLimits->maxTime == secondRLimits->maxTime) &&
+ (firstRLimits->maxFanout == secondRLimits->maxFanout) &&
+ (firstRLimits->maxDepth == secondRLimits->maxDepth) &&
+ (firstRLimits->maxCertsNumber ==
+ secondRLimits->maxCertsNumber) &&
+ (firstRLimits->maxCrlsNumber ==
+ secondRLimits->maxCrlsNumber);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ rLimits = (PKIX_ResourceLimits*)object;
+
+ hash = 31 * rLimits->maxTime + (rLimits->maxFanout << 1) +
+ (rLimits->maxDepth << 2) + (rLimits->maxCertsNumber << 3) +
+ rLimits->maxCrlsNumber;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *rLimitsString = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ /* maxCertsNumber and maxCrlsNumber are not supported */
+ asciiFormat =
+ "[\n"
+ "\tMaxTime: \t\t%d\n"
+ "\tMaxFanout: \t\t%d\n"
+ "\tMaxDepth: \t\t%d\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ rLimits = (PKIX_ResourceLimits*)object;
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&rLimitsString,
+ plContext,
+ formatString,
+ rLimits->maxTime,
+ rLimits->maxFanout,
+ rLimits->maxDepth),
+ PKIX_SPRINTFFAILED);
+
+ *pString = rLimitsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_RESOURCELIMITS_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_ResourceLimits_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_RegisterSelf");
+
+ entry.description = "ResourceLimits";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ResourceLimits);
+ entry.destructor = pkix_ResourceLimits_Destroy;
+ entry.equalsFunction = pkix_ResourceLimits_Equals;
+ entry.hashcodeFunction = pkix_ResourceLimits_Hashcode;
+ entry.toStringFunction = pkix_ResourceLimits_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_RESOURCELIMITS_TYPE] = entry;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_Create(
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_Create");
+ PKIX_NULLCHECK_ONE(pResourceLimits);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_RESOURCELIMITS_TYPE,
+ sizeof (PKIX_ResourceLimits),
+ (PKIX_PL_Object **)&rLimits,
+ plContext),
+ PKIX_COULDNOTCREATERESOURCELIMITOBJECT);
+
+ /* initialize fields */
+ rLimits->maxTime = 0;
+ rLimits->maxFanout = 0;
+ rLimits->maxDepth = 0;
+ rLimits->maxCertsNumber = 0;
+ rLimits->maxCrlsNumber = 0;
+
+ *pResourceLimits = rLimits;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxTime
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxTime(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxTime,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxTime");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxTime);
+
+ *pMaxTime = rLimits->maxTime;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxTime
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxTime(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxTime,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxTime");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxTime = maxTime;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxFanout
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxFanout(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxFanout,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxFanout");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxFanout);
+
+ *pMaxFanout = rLimits->maxFanout;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxFanout
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxFanout(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxFanout,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxFanout");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxFanout = maxFanout;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxDepth
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxDepth(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxDepth,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxDepth");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxDepth);
+
+ *pMaxDepth = rLimits->maxDepth;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxDepth
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxDepth(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxDepth,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxDepth");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxDepth = maxDepth;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCerts(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCerts");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxNumber);
+
+ *pMaxNumber = rLimits->maxCertsNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCerts(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCerts");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxCertsNumber = maxNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCRLs
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCRLs");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxNumber);
+
+ *pMaxNumber = rLimits->maxCrlsNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCRLs
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCRLs");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxCrlsNumber = maxNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h
new file mode 100644
index 0000000000..c4f582ce6f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.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_resourcelimits.h
+ *
+ * ResourceLimits Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_RESOURCELIMITS_H
+#define _PKIX_RESOURCELIMITS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ResourceLimitsStruct {
+ PKIX_UInt32 maxTime;
+ PKIX_UInt32 maxFanout;
+ PKIX_UInt32 maxDepth;
+ PKIX_UInt32 maxCertsNumber;
+ PKIX_UInt32 maxCrlsNumber;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ResourceLimits_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_RESOURCELIMITS_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c
new file mode 100644
index 0000000000..ced16d2902
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c
@@ -0,0 +1,525 @@
+/* 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_trustanchor.c
+ *
+ * TrustAnchor Object Functions
+ *
+ */
+
+#include "pkix_trustanchor.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a trust anchor */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor *)object;
+
+ PKIX_DECREF(anchor->trustedCert);
+ PKIX_DECREF(anchor->caName);
+ PKIX_DECREF(anchor->caPubKey);
+ PKIX_DECREF(anchor->nameConstraints);
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTTRUSTANCHOR);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_TRUSTANCHOR_TYPE) goto cleanup;
+
+ firstAnchor = (PKIX_TrustAnchor *)first;
+ secondAnchor = (PKIX_TrustAnchor *)second;
+
+ firstCert = firstAnchor->trustedCert;
+ secondCert = secondAnchor->trustedCert;
+
+ if ((firstCert && !secondCert) || (!firstCert && secondCert)){
+ goto cleanup;
+ }
+
+ if (firstCert && secondCert){
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstCert,
+ (PKIX_PL_Object *)secondCert,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor->caName,
+ (PKIX_PL_Object *)secondAnchor->caName,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor->caPubKey,
+ (PKIX_PL_Object *)secondAnchor->caPubKey,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstAnchor->nameConstraints,
+ secondAnchor->nameConstraints,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 nameHash = 0;
+ PKIX_UInt32 pubKeyHash = 0;
+ PKIX_UInt32 ncHash = 0;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor*)object;
+ cert = anchor->trustedCert;
+
+ if (cert){
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)cert,
+ &certHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = certHash;
+
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)anchor->caName,
+ &nameHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)anchor->caPubKey,
+ &pubKeyHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(anchor->nameConstraints, &ncHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * nameHash + pubKeyHash + ncHash;
+
+ }
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *anchorString = NULL;
+ PKIX_PL_String *certString = NULL;
+ PKIX_PL_String *nameString = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor*)object;
+
+ if (anchor->trustedCert){
+ asciiFormat =
+ "[\n"
+ "\tTrusted Cert: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->trustedCert,
+ &certString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&anchorString,
+ plContext,
+ formatString,
+ certString),
+ PKIX_SPRINTFFAILED);
+ } else {
+ asciiFormat =
+ "[\n"
+ "\tTrusted CA Name: %s\n"
+ "\tTrusted CA PublicKey: %s\n"
+ "\tInitial Name Constraints:%s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->caName,
+ &nameString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->caPubKey,
+ &pubKeyString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (anchor->nameConstraints,
+ &nameConstraintsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&anchorString,
+ plContext,
+ formatString,
+ nameString,
+ pubKeyString,
+ nameConstraintsString),
+ PKIX_SPRINTFFAILED);
+ }
+
+ *pString = anchorString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(certString);
+ PKIX_DECREF(nameString);
+ PKIX_DECREF(pubKeyString);
+ PKIX_DECREF(nameConstraintsString);
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_TRUSTANCHOR_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_TrustAnchor_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_RegisterSelf");
+
+ entry.description = "TrustAnchor";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_TrustAnchor);
+ entry.destructor = pkix_TrustAnchor_Destroy;
+ entry.equalsFunction = pkix_TrustAnchor_Equals;
+ entry.hashcodeFunction = pkix_TrustAnchor_Hashcode;
+ entry.toStringFunction = pkix_TrustAnchor_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_TRUSTANCHOR_TYPE] = entry;
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithCert (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithCert(
+ PKIX_PL_Cert *cert,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithCert");
+ PKIX_NULLCHECK_TWO(cert, pAnchor);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_TRUSTANCHOR_TYPE,
+ sizeof (PKIX_TrustAnchor),
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
+
+ /* initialize fields */
+ PKIX_CHECK(
+ PKIX_PL_Cert_SetAsTrustAnchor(cert, plContext),
+ PKIX_CERTSETASTRUSTANCHORFAILED);
+
+ PKIX_INCREF(cert);
+ anchor->trustedCert = cert;
+
+ anchor->caName = NULL;
+ anchor->caPubKey = NULL;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (anchor->trustedCert, &anchor->nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+
+ *pAnchor = anchor;
+ anchor = NULL;
+
+cleanup:
+
+ PKIX_DECREF(anchor);
+
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithNameKeyPair(
+ PKIX_PL_X500Name *name,
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair");
+
+#ifndef BUILD_LIBPKIX_TESTS
+ /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert
+ * function as the complete trusted cert structure, and not only cert
+ * public key, is required for chain building and validation processes.
+ * Restricting this function for been used only in libpkix unit
+ * tests. */
+ PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED);
+#endif
+
+ PKIX_NULLCHECK_THREE(name, pubKey, pAnchor);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_TRUSTANCHOR_TYPE,
+ sizeof (PKIX_TrustAnchor),
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
+
+ /* initialize fields */
+ anchor->trustedCert = NULL;
+
+ PKIX_INCREF(name);
+ anchor->caName = name;
+
+ PKIX_INCREF(pubKey);
+ anchor->caPubKey = pubKey;
+
+ PKIX_INCREF(nameConstraints);
+ anchor->nameConstraints = nameConstraints;
+
+ *pAnchor = anchor;
+ anchor = NULL;
+cleanup:
+
+ PKIX_DECREF(anchor);
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetTrustedCert (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetTrustedCert(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetTrustedCert");
+ PKIX_NULLCHECK_TWO(anchor, pCert);
+
+ PKIX_INCREF(anchor->trustedCert);
+
+ *pCert = anchor->trustedCert;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAName (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAName(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_X500Name **pCAName,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAName");
+ PKIX_NULLCHECK_TWO(anchor, pCAName);
+
+ PKIX_INCREF(anchor->caName);
+
+ *pCAName = anchor->caName;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAPublicKey(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_PublicKey **pPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAPublicKey");
+ PKIX_NULLCHECK_TWO(anchor, pPubKey);
+
+ PKIX_INCREF(anchor->caPubKey);
+
+ *pPubKey = anchor->caPubKey;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetNameConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetNameConstraints(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetNameConstraints");
+ PKIX_NULLCHECK_TWO(anchor, pNameConstraints);
+
+ PKIX_INCREF(anchor->nameConstraints);
+
+ *pNameConstraints = anchor->nameConstraints;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h
new file mode 100644
index 0000000000..e3ceb7fd33
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h
@@ -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/. */
+/*
+ * pkix_trustanchor.h
+ *
+ * TrustAnchor Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_TRUSTANCHOR_H
+#define _PKIX_TRUSTANCHOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_TrustAnchorStruct {
+ PKIX_PL_Cert *trustedCert;
+ PKIX_PL_X500Name *caName;
+ PKIX_PL_PublicKey *caPubKey;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_TrustAnchor_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TRUSTANCHOR_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.c b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c
new file mode 100644
index 0000000000..83c3d2b08f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c
@@ -0,0 +1,335 @@
+/* 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_valparams.c
+ *
+ * Validate Params Object Functions
+ *
+ */
+
+#include "pkix_valparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ValidateParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ValidateParams *params = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a validate params object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ params = (PKIX_ValidateParams *)object;
+
+ PKIX_DECREF(params->procParams);
+ PKIX_DECREF(params->chain);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ValidateParams *firstValParams = NULL;
+ PKIX_ValidateParams *secondValParams = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVALIDATEPARAMS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_VALIDATEPARAMS_TYPE) goto cleanup;
+
+ firstValParams = (PKIX_ValidateParams *)first;
+ secondValParams = (PKIX_ValidateParams *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValParams->procParams,
+ (PKIX_PL_Object *)secondValParams->procParams,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValParams->chain,
+ (PKIX_PL_Object *)secondValParams->chain,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 procParamsHash = 0;
+ PKIX_UInt32 chainHash = 0;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ valParams = (PKIX_ValidateParams*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valParams->procParams,
+ &procParamsHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valParams->chain,
+ &chainHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * procParamsHash + chainHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ValidateParams *valParams = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *valParamsString = NULL;
+
+ PKIX_PL_String *procParamsString = NULL;
+ PKIX_PL_String *chainString = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ asciiFormat =
+ "[\n"
+ "\tProcessing Params: \n"
+ "\t********BEGIN PROCESSING PARAMS********\n"
+ "\t\t%s\n"
+ "\t********END PROCESSING PARAMS********\n"
+ "\tChain: \t\t%s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ valParams = (PKIX_ValidateParams*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)valParams->procParams,
+ &procParamsString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)valParams->chain,
+ &chainString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&valParamsString,
+ plContext,
+ formatString,
+ procParamsString,
+ chainString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = valParamsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(procParamsString);
+ PKIX_DECREF(chainString);
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_VALIDATEPARAMS_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_ValidateParams_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_RegisterSelf");
+
+ entry.description = "ValidateParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ValidateParams);
+ entry.destructor = pkix_ValidateParams_Destroy;
+ entry.equalsFunction = pkix_ValidateParams_Equals;
+ entry.hashcodeFunction = pkix_ValidateParams_Hashcode;
+ entry.toStringFunction = pkix_ValidateParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_VALIDATEPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateParams_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_Create(
+ PKIX_ProcessingParams *procParams,
+ PKIX_List *chain,
+ PKIX_ValidateParams **pParams,
+ void *plContext)
+{
+ PKIX_ValidateParams *params = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_Create");
+ PKIX_NULLCHECK_THREE(procParams, chain, pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VALIDATEPARAMS_TYPE,
+ sizeof (PKIX_ValidateParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATEVALIDATEPARAMSOBJECT);
+
+ /* initialize fields */
+ PKIX_INCREF(procParams);
+ params->procParams = procParams;
+
+ PKIX_INCREF(chain);
+ params->chain = chain;
+
+ *pParams = params;
+ params = NULL;
+
+cleanup:
+
+ PKIX_DECREF(params);
+
+ PKIX_RETURN(VALIDATEPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetProcessingParams
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetProcessingParams(
+ PKIX_ValidateParams *valParams,
+ PKIX_ProcessingParams **pProcParams,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetProcessingParams");
+ PKIX_NULLCHECK_TWO(valParams, pProcParams);
+
+ PKIX_INCREF(valParams->procParams);
+
+ *pProcParams = valParams->procParams;
+
+cleanup:
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetCertChain (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetCertChain(
+ PKIX_ValidateParams *valParams,
+ PKIX_List **pChain,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetCertChain");
+ PKIX_NULLCHECK_TWO(valParams, pChain);
+
+ PKIX_INCREF(valParams->chain);
+
+ *pChain = valParams->chain;
+
+cleanup:
+ PKIX_RETURN(VALIDATEPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.h b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h
new file mode 100644
index 0000000000..93b754f712
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h
@@ -0,0 +1,33 @@
+/* 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_valparams.h
+ *
+ * ValidateParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_VALIDATEPARAMS_H
+#define _PKIX_VALIDATEPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ValidateParamsStruct {
+ PKIX_ProcessingParams *procParams; /* Never NULL */
+ PKIX_List *chain; /* Never NULL */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ValidateParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATEPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/results/Makefile b/security/nss/lib/libpkix/pkix/results/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/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/results/exports.gyp b/security/nss/lib/libpkix/pkix/results/exports.gyp
new file mode 100644
index 0000000000..dfff689033
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/exports.gyp
@@ -0,0 +1,28 @@
+# 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_results_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_buildresult.h',
+ 'pkix_policynode.h',
+ 'pkix_valresult.h',
+ 'pkix_verifynode.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/results/manifest.mn b/security/nss/lib/libpkix/pkix/results/manifest.mn
new file mode 100644
index 0000000000..bec0270fb6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/manifest.mn
@@ -0,0 +1,24 @@
+#
+# 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_buildresult.h \
+ pkix_policynode.h \
+ pkix_valresult.h \
+ pkix_verifynode.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_buildresult.c \
+ pkix_policynode.c \
+ pkix_valresult.c \
+ pkix_verifynode.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixresults
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c
new file mode 100644
index 0000000000..7d35119bcb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c
@@ -0,0 +1,362 @@
+/* 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_buildresult.c
+ *
+ * BuildResult Object Functions
+ *
+ */
+
+#include "pkix_buildresult.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_BuildResult_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_BuildResult *result = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a build result object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ result = (PKIX_BuildResult *)object;
+
+ PKIX_DECREF(result->valResult);
+ PKIX_DECREF(result->certChain);
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_BuildResult *firstBuildResult = NULL;
+ PKIX_BuildResult *secondBuildResult = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTBUILDRESULT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_BUILDRESULT_TYPE) goto cleanup;
+
+ firstBuildResult = (PKIX_BuildResult *)first;
+ secondBuildResult = (PKIX_BuildResult *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstBuildResult->valResult,
+ (PKIX_PL_Object *)secondBuildResult->valResult,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstBuildResult->certChain,
+ (PKIX_PL_Object *)secondBuildResult->certChain,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ /*
+ * The remaining case is that both are null,
+ * which we consider equality.
+ * cmpResult = PKIX_TRUE;
+ */
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 valResultHash = 0;
+ PKIX_UInt32 certChainHash = 0;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ buildResult = (PKIX_BuildResult*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)buildResult->valResult,
+ &valResultHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)buildResult->certChain,
+ &certChainHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31*(31 * valResultHash + certChainHash);
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *buildResultString = NULL;
+
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *certChain = NULL;
+
+ PKIX_PL_String *valResultString = NULL;
+ PKIX_PL_String *certChainString = NULL;
+
+ char *asciiFormat =
+ "[\n"
+ "\tValidateResult: \t\t%s"
+ "\tCertChain: \t\t%s\n"
+ "]\n";
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ buildResult = (PKIX_BuildResult*)object;
+
+ valResult = buildResult->valResult;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)valResult, &valResultString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ certChain = buildResult->certChain;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certChain, &certChainString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&buildResultString,
+ plContext,
+ formatString,
+ valResultString,
+ certChainString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = buildResultString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(valResultString);
+ PKIX_DECREF(certChainString);
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BUILDRESULT_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_BuildResult_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_RegisterSelf");
+
+ entry.description = "BuildResult";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_BuildResult);
+ entry.destructor = pkix_BuildResult_Destroy;
+ entry.equalsFunction = pkix_BuildResult_Equals;
+ entry.hashcodeFunction = pkix_BuildResult_Hashcode;
+ entry.toStringFunction = pkix_BuildResult_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BUILDRESULT_TYPE] = entry;
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Create
+ * DESCRIPTION:
+ *
+ * Creates a new BuildResult Object using the ValidateResult pointed to by
+ * "valResult" and the List pointed to by "certChain", and stores it at
+ * "pResult".
+ *
+ * PARAMETERS
+ * "valResult"
+ * Address of ValidateResult component. Must be non-NULL.
+ * "certChain
+ * Address of List component. Must be non-NULL.
+ * "pResult"
+ * 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_BuildResult_Create(
+ PKIX_ValidateResult *valResult,
+ PKIX_List *certChain,
+ PKIX_BuildResult **pResult,
+ void *plContext)
+{
+ PKIX_BuildResult *result = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Create");
+ PKIX_NULLCHECK_THREE(valResult, certChain, pResult);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BUILDRESULT_TYPE,
+ sizeof (PKIX_BuildResult),
+ (PKIX_PL_Object **)&result,
+ plContext),
+ PKIX_COULDNOTCREATEBUILDRESULTOBJECT);
+
+ /* initialize fields */
+
+ PKIX_INCREF(valResult);
+ result->valResult = valResult;
+
+ PKIX_INCREF(certChain);
+ result->certChain = certChain;
+
+ PKIX_CHECK(PKIX_List_SetImmutable(result->certChain, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pResult = result;
+ result = NULL;
+
+cleanup:
+
+ PKIX_DECREF(result);
+
+ PKIX_RETURN(BUILDRESULT);
+
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetValidateResult
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_BuildResult_GetValidateResult(
+ PKIX_BuildResult *result,
+ PKIX_ValidateResult **pResult,
+ void *plContext)
+{
+ PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetValidateResult");
+ PKIX_NULLCHECK_TWO(result, pResult);
+
+ PKIX_INCREF(result->valResult);
+ *pResult = result->valResult;
+
+cleanup:
+ PKIX_RETURN(BUILDRESULT);
+}
+
+
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetCertChain
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_BuildResult_GetCertChain(
+ PKIX_BuildResult *result,
+ PKIX_List **pChain,
+ void *plContext)
+{
+ PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetCertChain");
+ PKIX_NULLCHECK_TWO(result, pChain);
+
+ PKIX_INCREF(result->certChain);
+ *pChain = result->certChain;
+
+cleanup:
+ PKIX_RETURN(BUILDRESULT);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h
new file mode 100644
index 0000000000..b43f12ba14
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h
@@ -0,0 +1,40 @@
+/* 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_buildresult.h
+ *
+ * BuildResult Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_BUILDRESULT_H
+#define _PKIX_BUILDRESULT_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_BuildResultStruct {
+ PKIX_ValidateResult *valResult;
+ PKIX_List *certChain;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_BuildResult_Create(
+ PKIX_ValidateResult *valResult,
+ PKIX_List *certChain,
+ PKIX_BuildResult **pResult,
+ void *plContext);
+
+PKIX_Error *pkix_BuildResult_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BUILDRESULT_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.c b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c
new file mode 100644
index 0000000000..fd8cee982b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c
@@ -0,0 +1,1377 @@
+/* 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_policynode.c
+ *
+ * Policy Node Object Type Definition
+ *
+ */
+
+#include "pkix_policynode.h"
+
+/* --Private-PolicyNode-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_PolicyNode_GetChildrenMutable
+ * DESCRIPTION:
+ *
+ * Retrieves the List of PolicyNodes representing the child nodes of the
+ * Policy Node pointed to by "node" and stores it at "pChildren". If "node"
+ * has no List of child nodes, this function stores NULL at "pChildren".
+ *
+ * Note that the List returned by this function may be mutable. This function
+ * differs from the public function PKIX_PolicyNode_GetChildren in that
+ * respect. (It also differs in that the public function creates an empty
+ * List, if necessary, rather than storing NULL.)
+ *
+ * During certificate processing, children Lists are created and modified.
+ * Once the list is accessed using the public call, the List is set immutable.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose child nodes are to be stored.
+ * Must be non-NULL.
+ * "pChildren"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode 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_PolicyNode_GetChildrenMutable(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* list of PKIX_PolicyNode */
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable");
+
+ PKIX_NULLCHECK_TWO(node, pChildren);
+
+ PKIX_INCREF(node->children);
+
+ *pChildren = node->children;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Create
+ * DESCRIPTION:
+ *
+ * Creates a new PolicyNode using the OID pointed to by "validPolicy", the List
+ * of CertPolicyQualifiers pointed to by "qualifierSet", the criticality
+ * indicated by the Boolean value of "criticality", and the List of OIDs
+ * pointed to by "expectedPolicySet", and stores the result at "pObject". The
+ * criticality should be derived from whether the certificate policy extension
+ * was marked as critical in the certificate that led to creation of this
+ * PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made
+ * immutable. The PolicyNode pointers to parent and to children are initialized
+ * to NULL, and the depth is set to zero; those values should be set by using
+ * the pkix_PolicyNode_AddToParent function.
+ *
+ * PARAMETERS
+ * "validPolicy"
+ * Address of OID of the valid policy for the path. Must be non-NULL
+ * "qualifierSet"
+ * Address of List of CertPolicyQualifiers associated with the validpolicy.
+ * May be NULL
+ * "criticality"
+ * Boolean indicator of whether the criticality should be set in this
+ * PolicyNode
+ * "expectedPolicySet"
+ * Address of List of OIDs that would satisfy this policy in the next
+ * certificate. Must be non-NULL
+ * "pObject"
+ * Address where the PolicyNode 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 PolicyNode 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_PolicyNode_Create(
+ PKIX_PL_OID *validPolicy,
+ PKIX_List *qualifierSet,
+ PKIX_Boolean criticality,
+ PKIX_List *expectedPolicySet,
+ PKIX_PolicyNode **pObject,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create");
+
+ PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYNODE_TYPE,
+ sizeof (PKIX_PolicyNode),
+ (PKIX_PL_Object **)&node,
+ plContext),
+ PKIX_COULDNOTCREATEPOLICYNODEOBJECT);
+
+ PKIX_INCREF(validPolicy);
+ node->validPolicy = validPolicy;
+
+ PKIX_INCREF(qualifierSet);
+ node->qualifierSet = qualifierSet;
+ if (qualifierSet) {
+ PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ node->criticality = criticality;
+
+ PKIX_INCREF(expectedPolicySet);
+ node->expectedPolicySet = expectedPolicySet;
+ PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ node->parent = NULL;
+ node->children = NULL;
+ node->depth = 0;
+
+ *pObject = node;
+ node = NULL;
+
+cleanup:
+
+ PKIX_DECREF(node);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_AddToParent
+ * DESCRIPTION:
+ *
+ * Adds the PolicyNode pointed to by "child" to the List of children of
+ * the PolicyNode pointed to by "parentNode". If "parentNode" had a
+ * NULL pointer for the List of children, a new List is created containing
+ * "child". Otherwise "child" is appended to the existing List. The
+ * parent field in "child" is set to "parent", and the depth field is
+ * set to one more than the corresponding value in "parent".
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of PolicyNode whose List of child PolicyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of PolicyNode to be added to parentNode's List. 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 PolicyNode 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_PolicyNode_AddToParent(
+ PKIX_PolicyNode *parentNode,
+ PKIX_PolicyNode *child,
+ void *plContext)
+{
+ PKIX_List *listOfChildren = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent");
+
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+ parentNode->children = listOfChildren;
+ }
+
+ /*
+ * Note: this link is not reference-counted. The link from parent
+ * to child is counted (actually, the parent "owns" a List which
+ * "owns" children), but the children do not "own" the parent.
+ * Otherwise, there would be loops.
+ */
+ child->parent = parentNode;
+
+ child->depth = 1 + (parentNode->depth);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (listOfChildren, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)parentNode, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)child, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Prune
+ * DESCRIPTION:
+ *
+ * Prunes a tree below the PolicyNode whose address is pointed to by "node",
+ * using the UInt32 value of "height" as the distance from the leaf level,
+ * and storing at "pDelete" the Boolean value of whether this PolicyNode is,
+ * after pruning, childless and should be pruned.
+ *
+ * Any PolicyNode at height 0 is allowed to survive. If the height is greater
+ * than zero, pkix_PolicyNode_Prune is called recursively for each child of
+ * the current PolicyNode. After this process, a node with no children
+ * stores PKIX_TRUE in "pDelete" to indicate that it should be deleted.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of the PolicyNode to be pruned. Must be non-NULL.
+ * "height"
+ * UInt32 value for the distance from the leaf level
+ * "pDelete"
+ * Address to store the Boolean return value of PKIX_TRUE if this node
+ * should be pruned, or PKIX_FALSE if there remains at least one
+ * branch of the required height. 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 PolicyNode 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_PolicyNode_Prune(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 height,
+ PKIX_Boolean *pDelete,
+ void *plContext)
+{
+ PKIX_Boolean childless = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_UInt32 listSize = 0;
+ PKIX_UInt32 listIndex = 0;
+ PKIX_PolicyNode *candidate = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune");
+
+ PKIX_NULLCHECK_TWO(node, pDelete);
+
+ /* Don't prune at the leaf */
+ if (height == 0) {
+ goto cleanup;
+ }
+
+ /* Above the bottom level, childless nodes get pruned */
+ if (!(node->children)) {
+ childless = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * This node has children. If they are leaf nodes,
+ * we know they will live. Otherwise, check them out.
+ */
+ if (height > 1) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (node->children, &listSize, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ /*
+ * By working backwards from the end of the list,
+ * we avoid having to worry about possible
+ * decreases in the size of the list, as we
+ * delete items. The only nuisance is that since the
+ * index is UInt32, we can't check for it to reach -1;
+ * we have to use the 1-based index, rather than the
+ * 0-based index that PKIX_List functions require.
+ */
+ for (listIndex = listSize; listIndex > 0; listIndex--) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (node->children,
+ (listIndex - 1),
+ (PKIX_PL_Object **)&candidate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_Prune
+ (candidate,
+ height - 1,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYNODEPRUNEFAILED);
+
+ if (shouldBePruned == PKIX_TRUE) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (node->children,
+ (listIndex - 1),
+ plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ }
+
+ PKIX_DECREF(candidate);
+ }
+ }
+
+ /* Prune if this node has *become* childless */
+ PKIX_CHECK(PKIX_List_GetLength
+ (node->children, &listSize, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (listSize == 0) {
+ childless = PKIX_TRUE;
+ }
+
+ /*
+ * Even if we did not change this node, or any of its children,
+ * maybe a [great-]*grandchild was pruned.
+ */
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)node, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ *pDelete = childless;
+
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_ToString
+ * DESCRIPTION:
+ *
+ * Creates a String representation of the attributes of the PolicyNode
+ * pointed to by "node", other than its parents or children, and
+ * stores the result at "pString".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode to be described by the string. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+PKIX_Error *
+pkix_SinglePolicyNode_ToString(
+ PKIX_PolicyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *fmtString = NULL;
+ PKIX_PL_String *validString = NULL;
+ PKIX_PL_String *qualifierString = NULL;
+ PKIX_PL_String *criticalityString = NULL;
+ PKIX_PL_String *expectedString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString");
+ PKIX_NULLCHECK_TWO(node, pString);
+ PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "{%s,%s,%s,%s,%d}",
+ 0,
+ &fmtString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->validPolicy),
+ &validString,
+ plContext),
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->expectedPolicySet),
+ &expectedString,
+ plContext),
+ PKIX_LISTTOSTRINGFAILED);
+
+ if (node->qualifierSet) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->qualifierSet),
+ &qualifierString,
+ plContext),
+ PKIX_LISTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "{}",
+ 0,
+ &qualifierString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (node->criticality)?"Critical":"Not Critical",
+ 0,
+ &criticalityString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ fmtString,
+ validString,
+ qualifierString,
+ criticalityString,
+ expectedString,
+ node->depth),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(fmtString);
+ PKIX_DECREF(validString);
+ PKIX_DECREF(qualifierString);
+ PKIX_DECREF(criticalityString);
+ PKIX_DECREF(expectedString);
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Produces a String representation of a PolicyNode tree below the PolicyNode
+ * pointed to by "rootNode", with each line of output prefixed by the String
+ * pointed to by "indent", and stores the result at "pTreeString". It is
+ * called recursively, with ever-increasing indentation, for successively
+ * lower nodes on the tree.
+ *
+ * PARAMETERS:
+ * "rootNode"
+ * Address of PolicyNode subtree. Must be non-NULL.
+ * "indent"
+ * Address of String to be prefixed to each line of output. May be NULL
+ * if no indentation is desired
+ * "pTreeString"
+ * Address where the resulting String will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode 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_PolicyNode_ToString_Helper(
+ PKIX_PolicyNode *rootNode,
+ PKIX_PL_String *indent,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PL_String *nextIndentFormat = NULL;
+ PKIX_PL_String *thisNodeFormat = NULL;
+ PKIX_PL_String *childrenFormat = NULL;
+ PKIX_PL_String *nextIndentString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *thisItemString = NULL;
+ PKIX_PL_String *childString = NULL;
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_UInt32 numberOfChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper");
+
+ PKIX_NULLCHECK_TWO(rootNode, pTreeString);
+
+ /* Create a string for this node */
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (rootNode, &thisItemString, plContext),
+ PKIX_ERRORINSINGLEPOLICYNODETOSTRING);
+
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ indent,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ }
+
+ PKIX_DECREF(thisItemString);
+ thisItemString = resultString;
+
+ /* if no children, we are done */
+ if (rootNode->children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (rootNode->children, &numberOfChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numberOfChildren != 0) {
+ /*
+ * We create a string for each child in turn,
+ * concatenating them to thisItemString.
+ */
+
+ /* Prepare an indent string for each child */
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s. ",
+ 0,
+ &nextIndentFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nextIndentString,
+ plContext,
+ nextIndentFormat,
+ indent),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ ". ",
+ 0,
+ &nextIndentString,
+ plContext),
+ PKIX_ERRORCREATINGINDENTSTRING);
+ }
+
+ /* Prepare the format for concatenation. */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s\n%s",
+ 0,
+ &childrenFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ for (childIndex = 0;
+ childIndex < numberOfChildren;
+ childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (rootNode->children,
+ childIndex,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_ToString_Helper
+ (childNode,
+ nextIndentString,
+ &childString,
+ plContext),
+ PKIX_ERRORCREATINGCHILDSTRING);
+
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ childrenFormat,
+ thisItemString,
+ childString),
+ PKIX_ERRORINSPRINTF);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(thisItemString);
+
+ thisItemString = resultString;
+ }
+ }
+
+ *pTreeString = thisItemString;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(thisItemString);
+ }
+
+ PKIX_DECREF(nextIndentFormat);
+ PKIX_DECREF(thisNodeFormat);
+ PKIX_DECREF(childrenFormat);
+ PKIX_DECREF(nextIndentString);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PolicyNode *rootNode = NULL;
+ PKIX_PL_String *resultString = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pTreeString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ rootNode = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_PolicyNode_ToString_Helper
+ (rootNode, NULL, &resultString, plContext),
+ PKIX_ERRORCREATINGSUBTREESTRING);
+
+ *pTreeString = resultString;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ node = (PKIX_PolicyNode*)object;
+
+ node->criticality = PKIX_FALSE;
+ PKIX_DECREF(node->validPolicy);
+ PKIX_DECREF(node->qualifierSet);
+ PKIX_DECREF(node->expectedPolicySet);
+ PKIX_DECREF(node->children);
+
+ /*
+ * Note: the link to parent is not reference-counted. See comment
+ * in pkix_PolicyNode_AddToParent for more details.
+ */
+ node->parent = NULL;
+ node->depth = 0;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_Hashcode
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the attributes of the PolicyNode pointed to by
+ * "node", other than its parents and children, and stores the result at
+ * "pHashcode".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode to be hashcoded; must be non-NULL
+ * "pHashcode"
+ * Address where UInt32 result will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SinglePolicyNode_Hashcode(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 componentHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(node, pHashcode);
+ PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
+
+ PKIX_HASHCODE
+ (node->qualifierSet,
+ &nodeHash,
+ plContext,
+ PKIX_FAILUREHASHINGLISTQUALIFIERSET);
+
+ if (PKIX_TRUE == (node->criticality)) {
+ nodeHash = 31*nodeHash + 0xff;
+ } else {
+ nodeHash = 31*nodeHash + 0x00;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->validPolicy,
+ &componentHash,
+ plContext),
+ PKIX_FAILUREHASHINGOIDVALIDPOLICY);
+
+ nodeHash = 31*nodeHash + componentHash;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->expectedPolicySet,
+ &componentHash,
+ plContext),
+ PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET);
+
+ nodeHash = 31*nodeHash + componentHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+ PKIX_UInt32 childrenHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ node = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
+ (node, &nodeHash, plContext),
+ PKIX_SINGLEPOLICYNODEHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL);
+
+ PKIX_HASHCODE
+ (node->children,
+ &childrenHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + childrenHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_Equals
+ * DESCRIPTION:
+ *
+ * Compares for equality the components of the PolicyNode pointed to by
+ * "firstPN", other than its parents and children, with those of the
+ * PolicyNode pointed to by "secondPN" and stores the result at "pResult"
+ * (PKIX_TRUE if equal; PKIX_FALSE if not).
+ *
+ * PARAMETERS:
+ * "firstPN"
+ * Address of first of the PolicyNodes to be compared; must be non-NULL
+ * "secondPN"
+ * Address of second of the PolicyNodes to be compared; must be non-NULL
+ * "pResult"
+ * Address where Boolean will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SinglePolicyNode_Equals(
+ PKIX_PolicyNode *firstPN,
+ PKIX_PolicyNode *secondPN,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult);
+
+ /* If both references are identical, they must be equal */
+ if (firstPN == secondPN) {
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * It seems we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ if ((firstPN->criticality) != (secondPN->criticality)) {
+ goto cleanup;
+ }
+ if ((firstPN->depth) != (secondPN->depth)) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstPN->qualifierSet,
+ secondPN->qualifierSet,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy);
+
+ PKIX_EQUALS
+ (firstPN->validPolicy,
+ secondPN->validPolicy,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO
+ (firstPN->expectedPolicySet, secondPN->expectedPolicySet);
+
+ PKIX_EQUALS
+ (firstPN->expectedPolicySet,
+ secondPN->expectedPolicySet,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PolicyNode *firstPN = NULL;
+ PKIX_PolicyNode *secondPN = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a PolicyNode */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPOLICYNODE);
+
+ /*
+ * Since we know firstObject is a PolicyNode,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a PolicyNode, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CERTPOLICYNODE_TYPE) {
+ goto cleanup;
+ }
+
+ /*
+ * Oh, well, we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ firstPN = (PKIX_PolicyNode *)firstObject;
+ secondPN = (PKIX_PolicyNode *)secondObject;
+
+ /*
+ * We don't require the parents to be identical. In the
+ * course of traversing the tree, we will have checked the
+ * attributes of the parent nodes, and checking the lists
+ * of children will determine whether they match.
+ */
+
+ PKIX_EQUALS
+ (firstPN->children,
+ secondPN->children,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONCHILDREN);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_SinglePolicyNode_Equals
+ (firstPN, secondPN, &compResult, plContext),
+ PKIX_SINGLEPOLICYNODEEQUALSFAILED);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_DuplicateHelper
+ * DESCRIPTION:
+ *
+ * Duplicates the PolicyNode whose address is pointed to by "original",
+ * and stores the result at "pNewNode", if a non-NULL pointer is provided
+ * for "pNewNode". In addition, the created PolicyNode is added as a child
+ * to "parent", if a non-NULL pointer is provided for "parent". Then this
+ * function is called recursively to duplicate each of the children of
+ * "original". At the top level this function is called with a null
+ * "parent" and a non-NULL "pNewNode". Below the top level "parent" will
+ * be non-NULL and "pNewNode" will be NULL.
+ *
+ * PARAMETERS:
+ * "original"
+ * Address of PolicyNode to be copied; must be non-NULL
+ * "parent"
+ * Address of PolicyNode to which the created node is to be added as a
+ * child; NULL for the top-level call and non-NULL below the top level
+ * "pNewNode"
+ * Address to store the node created; should be NULL if "parent" is
+ * non-NULL and vice versa
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_PolicyNode_DuplicateHelper(
+ PKIX_PolicyNode *original,
+ PKIX_PolicyNode *parent,
+ PKIX_PolicyNode **pNewNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_List *children = NULL; /* List of PKIX_PolicyNode */
+ PKIX_PolicyNode *copy = NULL;
+ PKIX_PolicyNode *child = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper");
+
+ PKIX_NULLCHECK_THREE
+ (original, original->validPolicy, original->expectedPolicySet);
+
+ /*
+ * These components are immutable, so copying the pointers
+ * is sufficient. The create function increments the reference
+ * counts as it stores the pointers into the new object.
+ */
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (original->validPolicy,
+ original->qualifierSet,
+ original->criticality,
+ original->expectedPolicySet,
+ &copy,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+
+ if (parent) {
+ PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext),
+ PKIX_POLICYNODEADDTOPARENTFAILED);
+ }
+
+ /* Are there any children to duplicate? */
+ children = original->children;
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIndex = 0; childIndex < numChildren; childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
+ (child, copy, NULL, plContext),
+ PKIX_POLICYNODEDUPLICATEHELPERFAILED);
+
+ PKIX_DECREF(child);
+ }
+
+ if (pNewNode) {
+ *pNewNode = copy;
+ copy = NULL; /* no DecRef if we give our handle away */
+ }
+
+cleanup:
+ PKIX_DECREF(copy);
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PolicyNode *original = NULL;
+ PKIX_PolicyNode *copy = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ original = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
+ (original, NULL, &copy, plContext),
+ PKIX_POLICYNODEDUPLICATEHELPERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_CERTPOLICYNODE_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_PolicyNode_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf");
+
+ entry.description = "PolicyNode";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PolicyNode);
+ entry.destructor = pkix_PolicyNode_Destroy;
+ entry.equalsFunction = pkix_PolicyNode_Equals;
+ entry.hashcodeFunction = pkix_PolicyNode_Hashcode;
+ entry.toStringFunction = pkix_PolicyNode_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_PolicyNode_Duplicate;
+
+ systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+
+/* --Public-PolicyNode-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetChildren
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetChildren(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* list of PKIX_PolicyNode */
+ void *plContext)
+{
+ PKIX_List *children = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren");
+
+ PKIX_NULLCHECK_TWO(node, pChildren);
+
+ PKIX_INCREF(node->children);
+ children = node->children;
+
+ if (!children) {
+ PKIX_CHECK(PKIX_List_Create(&children, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(children, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pChildren = children;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(children);
+ }
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetParent
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetParent(
+ PKIX_PolicyNode *node,
+ PKIX_PolicyNode **pParent,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent");
+
+ PKIX_NULLCHECK_TWO(node, pParent);
+
+ PKIX_INCREF(node->parent);
+ *pParent = node->parent;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetValidPolicy
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetValidPolicy(
+ PKIX_PolicyNode *node,
+ PKIX_PL_OID **pValidPolicy,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy");
+
+ PKIX_NULLCHECK_TWO(node, pValidPolicy);
+
+ PKIX_INCREF(node->validPolicy);
+ *pValidPolicy = node->validPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetPolicyQualifiers(
+ PKIX_PolicyNode *node,
+ PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */
+ void *plContext)
+{
+ PKIX_List *qualifiers = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers");
+
+ PKIX_NULLCHECK_TWO(node, pQualifiers);
+
+ PKIX_INCREF(node->qualifierSet);
+ qualifiers = node->qualifierSet;
+
+ if (!qualifiers) {
+ PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pQualifiers = qualifiers;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetExpectedPolicies(
+ PKIX_PolicyNode *node,
+ PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies");
+
+ PKIX_NULLCHECK_TWO(node, pExpPolicies);
+
+ PKIX_INCREF(node->expectedPolicySet);
+ *pExpPolicies = node->expectedPolicySet;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_IsCritical
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_IsCritical(
+ PKIX_PolicyNode *node,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical");
+
+ PKIX_NULLCHECK_TWO(node, pCritical);
+
+ *pCritical = node->criticality;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetDepth
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetDepth(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 *pDepth,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth");
+
+ PKIX_NULLCHECK_TWO(node, pDepth);
+
+ *pDepth = node->depth;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.h b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h
new file mode 100644
index 0000000000..799b7a60aa
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h
@@ -0,0 +1,74 @@
+/* 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_policynode.h
+ *
+ * PolicyNode Type Definitions
+ *
+ */
+
+#ifndef _PKIX_POLICYNODE_H
+#define _PKIX_POLICYNODE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of a policy node...
+ */
+struct PKIX_PolicyNodeStruct {
+ PKIX_PL_OID *validPolicy;
+ PKIX_List *qualifierSet; /* CertPolicyQualifiers */
+ PKIX_Boolean criticality;
+ PKIX_List *expectedPolicySet; /* OIDs */
+ PKIX_PolicyNode *parent;
+ PKIX_List *children; /* PolicyNodes */
+ PKIX_UInt32 depth;
+};
+
+PKIX_Error *
+pkix_SinglePolicyNode_ToString(
+ PKIX_PolicyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_GetChildrenMutable(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* PolicyNodes */
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_Create(
+ PKIX_PL_OID *validPolicy,
+ PKIX_List *qualifierSet, /* CertPolicyQualifiers */
+ PKIX_Boolean criticality,
+ PKIX_List *expectedPolicySet, /* OIDs */
+ PKIX_PolicyNode **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_AddToParent(
+ PKIX_PolicyNode *parentNode,
+ PKIX_PolicyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_Prune(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 depth,
+ PKIX_Boolean *pDelete,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_POLICYNODE_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.c b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c
new file mode 100644
index 0000000000..25b69e59c3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c
@@ -0,0 +1,442 @@
+/* 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_valresult.c
+ *
+ * ValidateResult Object Functions
+ *
+ */
+
+#include "pkix_valresult.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ValidateResult_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ValidateResult *result = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a validate result object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ result = (PKIX_ValidateResult *)object;
+
+ PKIX_DECREF(result->anchor);
+ PKIX_DECREF(result->pubKey);
+ PKIX_DECREF(result->policyTree);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ValidateResult *firstValResult = NULL;
+ PKIX_ValidateResult *secondValResult = NULL;
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_PolicyNode *firstTree = NULL;
+ PKIX_PolicyNode *secondTree = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVALIDATERESULT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_VALIDATERESULT_TYPE) goto cleanup;
+
+ firstValResult = (PKIX_ValidateResult *)first;
+ secondValResult = (PKIX_ValidateResult *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValResult->pubKey,
+ (PKIX_PL_Object *)secondValResult->pubKey,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ firstAnchor = firstValResult->anchor;
+ secondAnchor = secondValResult->anchor;
+
+ if ((firstAnchor != NULL) && (secondAnchor != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor,
+ (PKIX_PL_Object *)secondAnchor,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ cmpResult = (firstAnchor == secondAnchor);
+ }
+
+ if (!cmpResult) goto cleanup;
+
+ firstTree = firstValResult->policyTree;
+ secondTree = secondValResult->policyTree;
+
+ if ((firstTree != NULL) && (secondTree != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstTree,
+ (PKIX_PL_Object *)secondTree,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ cmpResult = (firstTree == secondTree);
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 pubKeyHash = 0;
+ PKIX_UInt32 anchorHash = 0;
+ PKIX_UInt32 policyTreeHash = 0;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ valResult = (PKIX_ValidateResult*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->pubKey, &pubKeyHash, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ if (valResult->anchor) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->anchor,
+ &anchorHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+ }
+
+ if (valResult->policyTree) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->policyTree,
+ &policyTreeHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+ }
+
+ hash = 31*(31 * pubKeyHash + anchorHash) + policyTreeHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *valResultString = NULL;
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+ PKIX_PolicyNode *policyTree = NULL;
+
+ PKIX_PL_String *anchorString = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+ PKIX_PL_String *treeString = NULL;
+ char *asciiNullString = "(null)";
+ char *asciiFormat =
+ "[\n"
+ "\tTrustAnchor: \t\t%s"
+ "\tPubKey: \t\t%s\n"
+ "\tPolicyTree: \t\t%s\n"
+ "]\n";
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ valResult = (PKIX_ValidateResult*)object;
+
+ anchor = valResult->anchor;
+
+ if (anchor) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor, &anchorString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiNullString,
+ 0,
+ &anchorString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ pubKey = valResult->pubKey;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pubKey, &pubKeyString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ policyTree = valResult->policyTree;
+
+ if (policyTree) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)policyTree, &treeString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiNullString,
+ 0,
+ &treeString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&valResultString,
+ plContext,
+ formatString,
+ anchorString,
+ pubKeyString,
+ treeString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = valResultString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(anchorString);
+ PKIX_DECREF(pubKeyString);
+ PKIX_DECREF(treeString);
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_VALIDATERESULT_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_ValidateResult_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_RegisterSelf");
+
+ entry.description = "ValidateResult";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ValidateResult);
+ entry.destructor = pkix_ValidateResult_Destroy;
+ entry.equalsFunction = pkix_ValidateResult_Equals;
+ entry.hashcodeFunction = pkix_ValidateResult_Hashcode;
+ entry.toStringFunction = pkix_ValidateResult_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_VALIDATERESULT_TYPE] = entry;
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ValidateResult Object using the PublicKey pointed to by
+ * "pubKey", the TrustAnchor pointed to by "anchor", and the PolicyNode
+ * pointed to by "policyTree", and stores it at "pResult".
+ *
+ * PARAMETERS
+ * "pubKey"
+ * PublicKey of the desired ValidateResult. Must be non-NULL.
+ * "anchor"
+ * TrustAnchor of the desired Validateresult. May be NULL.
+ * "policyTree"
+ * PolicyNode of the desired ValidateResult; may be NULL
+ * "pResult"
+ * 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_ValidateResult_Create(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_TrustAnchor *anchor,
+ PKIX_PolicyNode *policyTree,
+ PKIX_ValidateResult **pResult,
+ void *plContext)
+{
+ PKIX_ValidateResult *result = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Create");
+ PKIX_NULLCHECK_TWO(pubKey, pResult);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VALIDATERESULT_TYPE,
+ sizeof (PKIX_ValidateResult),
+ (PKIX_PL_Object **)&result,
+ plContext),
+ PKIX_COULDNOTCREATEVALIDATERESULTOBJECT);
+
+ /* initialize fields */
+
+ PKIX_INCREF(pubKey);
+ result->pubKey = pubKey;
+
+ PKIX_INCREF(anchor);
+ result->anchor = anchor;
+
+ PKIX_INCREF(policyTree);
+ result->policyTree = policyTree;
+
+ *pResult = result;
+ result = NULL;
+
+cleanup:
+
+ PKIX_DECREF(result);
+
+ PKIX_RETURN(VALIDATERESULT);
+
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPublicKey
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPublicKey(
+ PKIX_ValidateResult *result,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPublicKey");
+ PKIX_NULLCHECK_TWO(result, pPublicKey);
+
+ PKIX_INCREF(result->pubKey);
+ *pPublicKey = result->pubKey;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetTrustAnchor
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetTrustAnchor(
+ PKIX_ValidateResult *result,
+ PKIX_TrustAnchor **pTrustAnchor,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetTrustAnchor");
+ PKIX_NULLCHECK_TWO(result, pTrustAnchor);
+
+ PKIX_INCREF(result->anchor);
+ *pTrustAnchor = result->anchor;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPolicyTree
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPolicyTree(
+ PKIX_ValidateResult *result,
+ PKIX_PolicyNode **pPolicyTree,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPolicyTree");
+ PKIX_NULLCHECK_TWO(result, pPolicyTree);
+
+ PKIX_INCREF(result->policyTree);
+ (*pPolicyTree) = result->policyTree;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.h b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h
new file mode 100644
index 0000000000..8011ae8c8f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.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_valresult.h
+ *
+ * ValidateResult Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_VALIDATERESULT_H
+#define _PKIX_VALIDATERESULT_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ValidateResultStruct {
+ PKIX_PL_PublicKey *pubKey;
+ PKIX_TrustAnchor *anchor;
+ PKIX_PolicyNode *policyTree;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_ValidateResult_Create(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_TrustAnchor *anchor,
+ PKIX_PolicyNode *policyTree,
+ PKIX_ValidateResult **pResult,
+ void *plContext);
+
+PKIX_Error *pkix_ValidateResult_RegisterSelf(void *plContext);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATERESULT_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c
new file mode 100644
index 0000000000..b52f83fcab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c
@@ -0,0 +1,1182 @@
+/* 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_verifynode.c
+ *
+ * Verify Node Object Type Definition
+ *
+ */
+
+#include "pkix_verifynode.h"
+
+/* --Private-VerifyNode-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_VerifyNode_Create
+ * DESCRIPTION:
+ *
+ * This function creates a VerifyNode using the Cert pointed to by "cert",
+ * the depth given by "depth", and the Error pointed to by "error", storing
+ * the result at "pObject".
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert for the node. Must be non-NULL
+ * "depth"
+ * UInt32 value of the depth for this node.
+ * "error"
+ * Address of Error for the node.
+ * "pObject"
+ * Address where the VerifyNode 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pObject,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create");
+ PKIX_NULLCHECK_TWO(cert, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VERIFYNODE_TYPE,
+ sizeof (PKIX_VerifyNode),
+ (PKIX_PL_Object **)&node,
+ plContext),
+ PKIX_COULDNOTCREATEVERIFYNODEOBJECT);
+
+ PKIX_INCREF(cert);
+ node->verifyCert = cert;
+
+ PKIX_INCREF(error);
+ node->error = error;
+
+ node->depth = depth;
+
+ node->children = NULL;
+
+ *pObject = node;
+ node = NULL;
+
+cleanup:
+
+ PKIX_DECREF(node);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_AddToChain
+ * DESCRIPTION:
+ *
+ * Adds the VerifyNode pointed to by "child", at the appropriate depth, to the
+ * List of children of the VerifyNode pointed to by "parentNode". The chain of
+ * VerifyNodes is traversed until a VerifyNode is found at a depth one less
+ * than that specified in "child". An Error is returned if there is no parent
+ * at a suitable depth.
+ *
+ * If "parentNode" has a NULL pointer for the List of children, a new List is
+ * created containing "child". Otherwise "child" is appended to the existing
+ * List.
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of VerifyNode whose List of child VerifyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of VerifyNode to be added to parentNode's List. 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 VerifyNode 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_VerifyNode_AddToChain(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext)
+{
+ PKIX_VerifyNode *successor = NULL;
+ PKIX_List *listOfChildren = NULL;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 parentDepth = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain");
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ parentDepth = parentNode->depth;
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+
+ if (parentDepth != (child->depth - 1)) {
+ PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN);
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (listOfChildren, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
+
+ parentNode->children = listOfChildren;
+ } else {
+ /* get number of children */
+ PKIX_CHECK(PKIX_List_GetLength
+ (listOfChildren, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numChildren != 1) {
+ PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE);
+ }
+
+ /* successor = listOfChildren[0] */
+ PKIX_CHECK(PKIX_List_GetItem
+ (listOfChildren,
+ 0,
+ (PKIX_PL_Object **)&successor,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_AddToChain
+ (successor, child, plContext),
+ PKIX_VERIFYNODEADDTOCHAINFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)parentNode, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_DECREF(successor);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_SetDepth
+ * DESCRIPTION:
+ *
+ * The function sets the depth field of each VerifyNode in the List "children"
+ * to the value given by "depth", and recursively sets the depth of any
+ * successive generations to the successive values.
+ *
+ * PARAMETERS:
+ * "children"
+ * The List of VerifyNodes. Must be non-NULL.
+ * "depth"
+ * The value of the depth field to be set in members of the List.
+ * "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 Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_VerifyNode_SetDepth(PKIX_List *children,
+ PKIX_UInt32 depth,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 chIx = 0;
+ PKIX_VerifyNode *child = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth");
+ PKIX_NULLCHECK_ONE(children);
+
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (chIx = 0; chIx < numChildren; chIx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children, chIx, (PKIX_PL_Object **)&child, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ child->depth = depth;
+
+ if (child->children != NULL) {
+ PKIX_CHECK(pkix_VerifyNode_SetDepth
+ (child->children, depth + 1, plContext),
+ PKIX_VERIFYNODESETDEPTHFAILED);
+ }
+
+ PKIX_DECREF(child);
+ }
+
+cleanup:
+
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_AddToTree
+ * DESCRIPTION:
+ *
+ * Adds the VerifyNode pointed to by "child" to the List of children of the
+ * VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer
+ * for the List of children, a new List is created containing "child".
+ * Otherwise "child" is appended to the existing List. The depth field of
+ * "child" is set to one more than the corresponding value in "parent", and
+ * if the "child" itself has child nodes, their depth fields are updated
+ * accordingly.
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of VerifyNode whose List of child VerifyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of VerifyNode to be added to parentNode's List. 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_AddToTree(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext)
+{
+ PKIX_List *listOfChildren = NULL;
+ PKIX_UInt32 parentDepth = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree");
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ parentDepth = parentNode->depth;
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ parentNode->children = listOfChildren;
+ }
+
+ child->depth = parentDepth + 1;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (parentNode->children, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
+
+ if (child->children != NULL) {
+ PKIX_CHECK(pkix_VerifyNode_SetDepth
+ (child->children, child->depth + 1, plContext),
+ PKIX_VERIFYNODESETDEPTHFAILED);
+ }
+
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_ToString
+ * DESCRIPTION:
+ *
+ * Creates a String representation of the attributes of the VerifyNode pointed
+ * to by "node", other than its children, and stores the result at "pString".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of VerifyNode to be described by the string. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+PKIX_Error *
+pkix_SingleVerifyNode_ToString(
+ PKIX_VerifyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *fmtString = NULL;
+ PKIX_PL_String *errorString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_String *subjectString = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString");
+ PKIX_NULLCHECK_THREE(node, pString, node->verifyCert);
+
+ PKIX_TOSTRING(node->error, &errorString, plContext,
+ PKIX_ERRORTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (node->verifyCert, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_TOSTRING(issuerName, &issuerString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (node->verifyCert, &subjectName, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_TOSTRING(subjectName, &subjectString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s",
+ 0,
+ &fmtString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ fmtString,
+ issuerString,
+ subjectString,
+ node->depth,
+ errorString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(fmtString);
+ PKIX_DECREF(errorString);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(issuerString);
+ PKIX_DECREF(subjectString);
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Produces a String representation of a VerifyNode tree below the VerifyNode
+ * pointed to by "rootNode", with each line of output prefixed by the String
+ * pointed to by "indent", and stores the result at "pTreeString". It is
+ * called recursively, with ever-increasing indentation, for successively
+ * lower nodes on the tree.
+ *
+ * PARAMETERS:
+ * "rootNode"
+ * Address of VerifyNode subtree. Must be non-NULL.
+ * "indent"
+ * Address of String to be prefixed to each line of output. May be NULL
+ * if no indentation is desired
+ * "pTreeString"
+ * Address where the resulting String will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a VerifyNode 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_VerifyNode_ToString_Helper(
+ PKIX_VerifyNode *rootNode,
+ PKIX_PL_String *indent,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PL_String *nextIndentFormat = NULL;
+ PKIX_PL_String *thisNodeFormat = NULL;
+ PKIX_PL_String *childrenFormat = NULL;
+ PKIX_PL_String *nextIndentString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *thisItemString = NULL;
+ PKIX_PL_String *childString = NULL;
+ PKIX_VerifyNode *childNode = NULL;
+ PKIX_UInt32 numberOfChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper");
+
+ PKIX_NULLCHECK_TWO(rootNode, pTreeString);
+
+ /* Create a string for this node */
+ PKIX_CHECK(pkix_SingleVerifyNode_ToString
+ (rootNode, &thisItemString, plContext),
+ PKIX_ERRORINSINGLEVERIFYNODETOSTRING);
+
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ indent,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ }
+
+ PKIX_DECREF(thisItemString);
+ thisItemString = resultString;
+
+ /* if no children, we are done */
+ if (rootNode->children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (rootNode->children, &numberOfChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numberOfChildren != 0) {
+ /*
+ * We create a string for each child in turn,
+ * concatenating them to thisItemString.
+ */
+
+ /* Prepare an indent string for each child */
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s. ",
+ 0,
+ &nextIndentFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nextIndentString,
+ plContext,
+ nextIndentFormat,
+ indent),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ ". ",
+ 0,
+ &nextIndentString,
+ plContext),
+ PKIX_ERRORCREATINGINDENTSTRING);
+ }
+
+ /* Prepare the format for concatenation. */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s\n%s",
+ 0,
+ &childrenFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ for (childIndex = 0;
+ childIndex < numberOfChildren;
+ childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (rootNode->children,
+ childIndex,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_ToString_Helper
+ (childNode,
+ nextIndentString,
+ &childString,
+ plContext),
+ PKIX_ERRORCREATINGCHILDSTRING);
+
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ childrenFormat,
+ thisItemString,
+ childString),
+ PKIX_ERRORINSPRINTF);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(thisItemString);
+
+ thisItemString = resultString;
+ }
+ }
+
+ *pTreeString = thisItemString;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(thisItemString);
+ }
+
+ PKIX_DECREF(nextIndentFormat);
+ PKIX_DECREF(thisNodeFormat);
+ PKIX_DECREF(childrenFormat);
+ PKIX_DECREF(nextIndentString);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_VerifyNode *rootNode = NULL;
+ PKIX_PL_String *resultString = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pTreeString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ rootNode = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_VerifyNode_ToString_Helper
+ (rootNode, NULL, &resultString, plContext),
+ PKIX_ERRORCREATINGSUBTREESTRING);
+
+ *pTreeString = resultString;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ node = (PKIX_VerifyNode*)object;
+
+ PKIX_DECREF(node->verifyCert);
+ PKIX_DECREF(node->children);
+ PKIX_DECREF(node->error);
+
+ node->depth = 0;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_Hashcode
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the attributes of the VerifyNode pointed to by
+ * "node", other than its parents and children, and stores the result at
+ * "pHashcode".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of VerifyNode to be hashcoded; must be non-NULL
+ * "pHashcode"
+ * Address where UInt32 result will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SingleVerifyNode_Hashcode(
+ PKIX_VerifyNode *node,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 errorHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(node, pHashcode);
+
+ PKIX_HASHCODE
+ (node->verifyCert,
+ &nodeHash,
+ plContext,
+ PKIX_FAILUREHASHINGCERT);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->error,
+ &errorHash,
+ plContext),
+ PKIX_FAILUREHASHINGERROR);
+
+ nodeHash = 31*nodeHash + errorHash;
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+ PKIX_UInt32 childrenHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ node = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_SingleVerifyNode_Hashcode
+ (node, &nodeHash, plContext),
+ PKIX_SINGLEVERIFYNODEHASHCODEFAILED);
+
+ PKIX_HASHCODE
+ (node->children,
+ &childrenHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + childrenHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_Equals
+ * DESCRIPTION:
+ *
+ * Compares for equality the components of the VerifyNode pointed to by
+ * "firstPN", other than its parents and children, with those of the
+ * VerifyNode pointed to by "secondPN" and stores the result at "pResult"
+ * (PKIX_TRUE if equal; PKIX_FALSE if not).
+ *
+ * PARAMETERS:
+ * "firstPN"
+ * Address of first of the VerifyNodes to be compared; must be non-NULL
+ * "secondPN"
+ * Address of second of the VerifyNodes to be compared; must be non-NULL
+ * "pResult"
+ * Address where Boolean will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SingleVerifyNode_Equals(
+ PKIX_VerifyNode *firstVN,
+ PKIX_VerifyNode *secondVN,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult);
+
+ /* If both references are identical, they must be equal */
+ if (firstVN == secondVN) {
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * It seems we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ if ((firstVN->depth) != (secondVN->depth)) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert);
+
+ PKIX_EQUALS
+ (firstVN->verifyCert,
+ secondVN->verifyCert,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstVN->error,
+ secondVN->error,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_VerifyNode *firstVN = NULL;
+ PKIX_VerifyNode *secondVN = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a VerifyNode */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVERIFYNODE);
+
+ /*
+ * Since we know firstObject is a VerifyNode,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a VerifyNode, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_VERIFYNODE_TYPE) {
+ goto cleanup;
+ }
+
+ /*
+ * Oh, well, we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ firstVN = (PKIX_VerifyNode *)firstObject;
+ secondVN = (PKIX_VerifyNode *)secondObject;
+
+ PKIX_CHECK(pkix_SingleVerifyNode_Equals
+ (firstVN, secondVN, &compResult, plContext),
+ PKIX_SINGLEVERIFYNODEEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstVN->children,
+ secondVN->children,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONCHILDREN);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_DuplicateHelper
+ * DESCRIPTION:
+ *
+ * Duplicates the VerifyNode whose address is pointed to by "original",
+ * and stores the result at "pNewNode", if a non-NULL pointer is provided
+ * for "pNewNode". In addition, the created VerifyNode is added as a child
+ * to "parent", if a non-NULL pointer is provided for "parent". Then this
+ * function is called recursively to duplicate each of the children of
+ * "original". At the top level this function is called with a null
+ * "parent" and a non-NULL "pNewNode". Below the top level "parent" will
+ * be non-NULL and "pNewNode" will be NULL.
+ *
+ * PARAMETERS:
+ * "original"
+ * Address of VerifyNode to be copied; must be non-NULL
+ * "parent"
+ * Address of VerifyNode to which the created node is to be added as a
+ * child; NULL for the top-level call and non-NULL below the top level
+ * "pNewNode"
+ * Address to store the node created; should be NULL if "parent" is
+ * non-NULL and vice versa
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_VerifyNode_DuplicateHelper(
+ PKIX_VerifyNode *original,
+ PKIX_VerifyNode *parent,
+ PKIX_VerifyNode **pNewNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_List *children = NULL; /* List of PKIX_VerifyNode */
+ PKIX_VerifyNode *copy = NULL;
+ PKIX_VerifyNode *child = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper");
+
+ PKIX_NULLCHECK_TWO
+ (original, original->verifyCert);
+
+ /*
+ * These components are immutable, so copying the pointers
+ * is sufficient. The create function increments the reference
+ * counts as it stores the pointers into the new object.
+ */
+ PKIX_CHECK(pkix_VerifyNode_Create
+ (original->verifyCert,
+ original->depth,
+ original->error,
+ &copy,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+
+ /* Are there any children to duplicate? */
+ children = original->children;
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIndex = 0; childIndex < numChildren; childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
+ (child, copy, NULL, plContext),
+ PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
+
+ PKIX_DECREF(child);
+ }
+
+ if (pNewNode) {
+ *pNewNode = copy;
+ copy = NULL; /* no DecRef if we give our handle away */
+ }
+
+cleanup:
+ PKIX_DECREF(copy);
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_VerifyNode *original = NULL;
+ PKIX_VerifyNode *copy = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ original = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
+ (original, NULL, &copy, plContext),
+ PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_VERIFYNODE_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_VerifyNode_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf");
+
+ entry.description = "VerifyNode";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_VerifyNode);
+ entry.destructor = pkix_VerifyNode_Destroy;
+ entry.equalsFunction = pkix_VerifyNode_Equals;
+ entry.hashcodeFunction = pkix_VerifyNode_Hashcode;
+ entry.toStringFunction = pkix_VerifyNode_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_VerifyNode_Duplicate;
+
+ systemClasses[PKIX_VERIFYNODE_TYPE] = entry;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/* --Public-VerifyNode-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_VerifyNode_SetError
+ * DESCRIPTION:
+ *
+ * This function sets the Error field of the VerifyNode pointed to by "node"
+ * to contain the Error pointed to by "error".
+ *
+ * PARAMETERS:
+ * "node"
+ * The address of the VerifyNode to be modified. Must be non-NULL.
+ * "error"
+ * The address of the Error to be stored.
+ * "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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_SetError(
+ PKIX_VerifyNode *node,
+ PKIX_Error *error,
+ void *plContext)
+{
+
+ PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError");
+
+ PKIX_NULLCHECK_TWO(node, error);
+
+ PKIX_DECREF(node->error); /* should have been NULL */
+ PKIX_INCREF(error);
+ node->error = error;
+
+cleanup:
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_VerifyNode_FindError
+ * DESCRIPTION:
+ *
+ * Finds meaningful error in the log. For now, just returns the first
+ * error it finds in. In the future the function should be changed to
+ * return a top priority error.
+ *
+ * PARAMETERS:
+ * "node"
+ * The address of the VerifyNode to be modified. Must be non-NULL.
+ * "error"
+ * The address of a pointer the error will be returned to.
+ * "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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_FindError(
+ PKIX_VerifyNode *node,
+ PKIX_Error **error,
+ void *plContext)
+{
+ PKIX_VerifyNode *childNode = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError");
+
+ /* Make sure the return address is initialized with NULL */
+ PKIX_DECREF(*error);
+
+ if (!node)
+ goto cleanup;
+
+ /* First, try to get error from lowest level. */
+ if (node->children) {
+ PKIX_UInt32 length = 0;
+ PKIX_UInt32 index = 0;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(node->children, &length,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ for (index = 0;index < length;index++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(node->children, index,
+ (PKIX_PL_Object**)&childNode, plContext),
+ PKIX_LISTGETITEMFAILED);
+ if (!childNode)
+ continue;
+ PKIX_CHECK(
+ pkix_VerifyNode_FindError(childNode, error,
+ plContext),
+ PKIX_VERIFYNODEFINDERRORFAILED);
+ PKIX_DECREF(childNode);
+ if (*error) {
+ goto cleanup;
+ }
+ }
+ }
+
+ if (node->error && node->error->plErr) {
+ PKIX_INCREF(node->error);
+ *error = node->error;
+ }
+
+cleanup:
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(VERIFYNODE);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h
new file mode 100644
index 0000000000..c943ae4ddc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h
@@ -0,0 +1,75 @@
+/* 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_verifynode.h
+ *
+ * VerifyNode Type Definitions
+ *
+ */
+
+#ifndef _PKIX_VERIFYNODE_H
+#define _PKIX_VERIFYNODE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of a verify node...
+ */
+struct PKIX_VerifyNodeStruct {
+ PKIX_PL_Cert *verifyCert;
+ PKIX_List *children; /* VerifyNodes */
+ PKIX_UInt32 depth;
+ PKIX_Error *error;
+};
+
+PKIX_Error *
+pkix_SingleVerifyNode_ToString(
+ PKIX_VerifyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_Create(
+ PKIX_PL_Cert *verifyCert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_AddToChain(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_AddToTree(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_SetError(
+ PKIX_VerifyNode *node,
+ PKIX_Error *error,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_RegisterSelf(
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_FindError(
+ PKIX_VerifyNode *node,
+ PKIX_Error **error,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VERIFYNODE_H */
diff --git a/security/nss/lib/libpkix/pkix/results/results.gyp b/security/nss/lib/libpkix/pkix/results/results.gyp
new file mode 100644
index 0000000000..962fdb9481
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/results.gyp
@@ -0,0 +1,26 @@
+# 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': 'pkixresults',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_buildresult.c',
+ 'pkix_policynode.c',
+ 'pkix_valresult.c',
+ 'pkix_verifynode.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/store/Makefile b/security/nss/lib/libpkix/pkix/store/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/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/store/exports.gyp b/security/nss/lib/libpkix/pkix/store/exports.gyp
new file mode 100644
index 0000000000..52f13f5ae7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/exports.gyp
@@ -0,0 +1,25 @@
+# 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_store_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_store.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/store/manifest.mn b/security/nss/lib/libpkix/pkix/store/manifest.mn
new file mode 100644
index 0000000000..53a54d6cc6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/manifest.mn
@@ -0,0 +1,18 @@
+#
+# 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_store.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_store.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixstore
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.c b/security/nss/lib/libpkix/pkix/store/pkix_store.c
new file mode 100644
index 0000000000..af8be2bb2c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/pkix_store.c
@@ -0,0 +1,415 @@
+/* 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_store.c
+ *
+ * CertStore Function Definitions
+ *
+ */
+
+#include "pkix_store.h"
+
+/* --CertStore-Private-Functions----------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertStore_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a CertStore object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSTORE);
+
+ certStore = (PKIX_CertStore *)object;
+
+ certStore->certCallback = NULL;
+ certStore->crlCallback = NULL;
+ certStore->certContinue = NULL;
+ certStore->crlContinue = NULL;
+ certStore->trustCallback = NULL;
+
+ PKIX_DECREF(certStore->certStoreContext);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSTORE);
+
+ certStore = (PKIX_CertStore *)object;
+
+ if (certStore->certStoreContext) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *) certStore->certStoreContext,
+ &tempHash,
+ plContext),
+ PKIX_CERTSTOREHASHCODEFAILED);
+ }
+
+ *pHashcode = (PKIX_UInt32)((char *)certStore->certCallback - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->crlCallback - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->certContinue - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->crlContinue - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->trustCallback - (char *)NULL) +
+ (tempHash << 7);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_CertStore *firstCS = NULL;
+ PKIX_CertStore *secondCS = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_ARGUMENTSNOTDATES);
+
+ firstCS = (PKIX_CertStore *)firstObject;
+ secondCS = (PKIX_CertStore *)secondObject;
+
+ cmpResult = (firstCS->certCallback == secondCS->certCallback) &&
+ (firstCS->crlCallback == secondCS->crlCallback) &&
+ (firstCS->certContinue == secondCS->certContinue) &&
+ (firstCS->crlContinue == secondCS->crlContinue) &&
+ (firstCS->trustCallback == secondCS->trustCallback);
+
+ if (cmpResult &&
+ (firstCS->certStoreContext != secondCS->certStoreContext)) {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *) firstCS->certStoreContext,
+ (PKIX_PL_Object *) secondCS->certStoreContext,
+ &cmpResult,
+ plContext),
+ PKIX_CERTSTOREEQUALSFAILED);
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTSTORE_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_CertStore_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_RegisterSelf");
+
+ entry.description = "CertStore";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertStore);
+ entry.destructor = pkix_CertStore_Destroy;
+ entry.equalsFunction = pkix_CertStore_Equals;
+ entry.hashcodeFunction = pkix_CertStore_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTSTORE_TYPE] = entry;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/* --CertStore-Public-Functions------------------------------------------ */
+
+/*
+ * FUNCTION: PKIX_CertStore_Create (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_Create(
+ PKIX_CertStore_CertCallback certCallback,
+ PKIX_CertStore_CRLCallback crlCallback,
+ PKIX_CertStore_CertContinueFunction certContinue,
+ PKIX_CertStore_CrlContinueFunction crlContinue,
+ PKIX_CertStore_CheckTrustCallback trustCallback,
+ PKIX_CertStore_ImportCrlCallback importCrlCallback,
+ PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback,
+ PKIX_PL_Object *certStoreContext,
+ PKIX_Boolean cacheFlag,
+ PKIX_Boolean localFlag,
+ PKIX_CertStore **pStore,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_Create");
+ PKIX_NULLCHECK_THREE(certCallback, crlCallback, pStore);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTSTORE_TYPE,
+ sizeof (PKIX_CertStore),
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_COULDNOTCREATECERTSTOREOBJECT);
+
+ certStore->certCallback = certCallback;
+ certStore->crlCallback = crlCallback;
+ certStore->certContinue = certContinue;
+ certStore->crlContinue = crlContinue;
+ certStore->trustCallback = trustCallback;
+ certStore->importCrlCallback = importCrlCallback;
+ certStore->checkRevByCrlCallback = checkRevByCrlCallback;
+ certStore->cacheFlag = cacheFlag;
+ certStore->localFlag = localFlag;
+
+ PKIX_INCREF(certStoreContext);
+ certStore->certStoreContext = certStoreContext;
+
+ *pStore = certStore;
+ certStore = NULL;
+
+cleanup:
+
+ PKIX_DECREF(certStore);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CertCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->certCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCRLCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CRLCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCRLCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->crlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_CertContinue (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_CertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CertContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);
+
+ PKIX_CHECK(store->certContinue
+ (store, selector, verifyNode,
+ pNBIOContext, pCertList, plContext),
+ PKIX_CERTSTORECERTCONTINUEFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_CrlContinue (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_CrlContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CrlContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);
+
+ PKIX_CHECK(store->crlContinue
+ (store, selector, pNBIOContext, pCrlList, plContext),
+ PKIX_CERTSTORECRLCONTINUEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetTrustCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetTrustCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckTrustCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->trustCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetImportCrlCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetImportCrlCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_ImportCrlCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->importCrlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCheckRevByCrl (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCrlCheckerFn(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckRevokationByCrlCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->checkRevByCrlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreContext
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreContext(
+ PKIX_CertStore *store,
+ PKIX_PL_Object **pCertStoreContext,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreContext");
+ PKIX_NULLCHECK_TWO(store, pCertStoreContext);
+
+ PKIX_INCREF(store->certStoreContext);
+ *pCertStoreContext = store->certStoreContext;
+
+cleanup:
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreCacheFlag
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreCacheFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreCacheFlag");
+ PKIX_NULLCHECK_TWO(store, pCacheFlag);
+
+ *pCacheFlag = store->cacheFlag;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetLocalFlag
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetLocalFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pLocalFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetLocalFlag");
+ PKIX_NULLCHECK_TWO(store, pLocalFlag);
+
+ *pLocalFlag = store->localFlag;
+
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.h b/security/nss/lib/libpkix/pkix/store/pkix_store.h
new file mode 100644
index 0000000000..9d116ffbda
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/pkix_store.h
@@ -0,0 +1,41 @@
+/* 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_store.h
+ *
+ * CertStore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_STORE_H
+#define _PKIX_STORE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertStoreStruct {
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore_CertContinueFunction certContinue;
+ PKIX_CertStore_CrlContinueFunction crlContinue;
+ PKIX_CertStore_CheckTrustCallback trustCallback;
+ PKIX_CertStore_ImportCrlCallback importCrlCallback;
+ PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback;
+ PKIX_PL_Object *certStoreContext;
+ PKIX_Boolean cacheFlag;
+ PKIX_Boolean localFlag; /* TRUE if CertStore is local */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CertStore_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_STORE_H */
diff --git a/security/nss/lib/libpkix/pkix/store/store.gyp b/security/nss/lib/libpkix/pkix/store/store.gyp
new file mode 100644
index 0000000000..43aa177688
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/store.gyp
@@ -0,0 +1,23 @@
+# 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': 'pkixstore',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_store.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/top/Makefile b/security/nss/lib/libpkix/pkix/top/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/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/top/exports.gyp b/security/nss/lib/libpkix/pkix/top/exports.gyp
new file mode 100644
index 0000000000..d41f2b5ec4
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/exports.gyp
@@ -0,0 +1,27 @@
+# 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_top_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_build.h',
+ 'pkix_lifecycle.h',
+ 'pkix_validate.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/top/manifest.mn b/security/nss/lib/libpkix/pkix/top/manifest.mn
new file mode 100644
index 0000000000..5bdd3f300d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/manifest.mn
@@ -0,0 +1,22 @@
+#
+# 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_build.h \
+ pkix_lifecycle.h \
+ pkix_validate.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_validate.c \
+ pkix_lifecycle.c \
+ pkix_build.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtop
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.c b/security/nss/lib/libpkix/pkix/top/pkix_build.c
new file mode 100644
index 0000000000..aebfeebade
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c
@@ -0,0 +1,3763 @@
+/* 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_build.c
+ *
+ * Top level buildChain function
+ *
+ */
+
+/* #define PKIX_BUILDDEBUG 1 */
+/* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */
+
+#include "pkix_build.h"
+
+extern PRLogModuleInfo *pkixLog;
+
+/*
+ * List of critical extension OIDs associate with what build chain has
+ * checked. Those OIDs need to be removed from the unresolved critical
+ * extension OIDs list manually (instead of by checker automatically).
+ */
+static SECOidTag buildCheckedCritExtOIDs[] = {
+ PKIX_CERTKEYUSAGE_OID,
+ PKIX_CERTSUBJALTNAME_OID,
+ PKIX_BASICCONSTRAINTS_OID,
+ PKIX_NAMECONSTRAINTS_OID,
+ PKIX_EXTENDEDKEYUSAGE_OID,
+ PKIX_NSCERTTYPE_OID,
+ PKIX_UNKNOWN_OID
+};
+
+/* --Private-ForwardBuilderState-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ForwardBuilderState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTFORWARDBUILDERSTATE);
+
+ state = (PKIX_ForwardBuilderState *)object;
+
+ state->status = BUILD_INITIAL;
+ state->traversedCACerts = 0;
+ state->certStoreIndex = 0;
+ state->numCerts = 0;
+ state->numAias = 0;
+ state->certIndex = 0;
+ state->aiaIndex = 0;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->hintCertIndex = 0;
+ state->numFanout = 0;
+ state->numDepth = 0;
+ state->reasonCode = 0;
+ state->canBeCached = PKIX_FALSE;
+ state->useOnlyLocal = PKIX_FALSE;
+ state->revChecking = PKIX_FALSE;
+ state->usingHintCerts = PKIX_FALSE;
+ state->certLoopingDetected = PKIX_FALSE;
+ PKIX_DECREF(state->validityDate);
+ PKIX_DECREF(state->prevCert);
+ PKIX_DECREF(state->candidateCert);
+ PKIX_DECREF(state->traversedSubjNames);
+ PKIX_DECREF(state->trustChain);
+ PKIX_DECREF(state->aia);
+ PKIX_DECREF(state->candidateCerts);
+ PKIX_DECREF(state->reversedCertChain);
+ PKIX_DECREF(state->checkedCritExtOIDs);
+ PKIX_DECREF(state->checkerChain);
+ PKIX_DECREF(state->certSel);
+ PKIX_DECREF(state->verifyNode);
+ PKIX_DECREF(state->client);
+
+ /*
+ * If we ever add a child link we have to be careful not to have loops
+ * in the Destroy process. But with one-way links we should be okay.
+ */
+ if (state->parentState == NULL) {
+ state->buildConstants.numAnchors = 0;
+ state->buildConstants.numCertStores = 0;
+ state->buildConstants.numHintCerts = 0;
+ state->buildConstants.procParams = 0;
+ PKIX_DECREF(state->buildConstants.testDate);
+ PKIX_DECREF(state->buildConstants.timeLimit);
+ PKIX_DECREF(state->buildConstants.targetCert);
+ PKIX_DECREF(state->buildConstants.targetPubKey);
+ PKIX_DECREF(state->buildConstants.certStores);
+ PKIX_DECREF(state->buildConstants.anchors);
+ PKIX_DECREF(state->buildConstants.userCheckers);
+ PKIX_DECREF(state->buildConstants.hintCerts);
+ PKIX_DECREF(state->buildConstants.revChecker);
+ PKIX_DECREF(state->buildConstants.aiaMgr);
+ } else {
+ PKIX_DECREF(state->parentState);
+ }
+
+cleanup:
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize a ForwardBuilderState.
+ *
+ * PARAMETERS
+ * "traversedCACerts"
+ * Number of CA certificates traversed.
+ * "numFanout"
+ * Number of Certs that can be considered at this level (0 = no limit)
+ * "numDepth"
+ * Number of additional levels that can be searched (0 = no limit)
+ * "canBeCached"
+ * Boolean value indicating whether all certs on the chain can be cached.
+ * "validityDate"
+ * Address of Date at which build chain Certs' most restricted validity
+ * time is kept. May be NULL.
+ * "prevCert"
+ * Address of Cert just traversed. Must be non-NULL.
+ * "traversedSubjNames"
+ * Address of List of GeneralNames that have been traversed.
+ * Must be non-NULL.
+ * "trustChain"
+ * Address of List of certificates traversed. Must be non-NULL.
+ * "parentState"
+ * Address of previous ForwardBuilderState
+ * "pState"
+ * Address where ForwardBuilderState 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 Build 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_ForwardBuilderState_Create(
+ PKIX_Int32 traversedCACerts,
+ PKIX_UInt32 numFanout,
+ PKIX_UInt32 numDepth,
+ PKIX_Boolean canBeCached,
+ PKIX_PL_Date *validityDate,
+ PKIX_PL_Cert *prevCert,
+ PKIX_List *traversedSubjNames,
+ PKIX_List *trustChain,
+ PKIX_ForwardBuilderState *parentState,
+ PKIX_ForwardBuilderState **pState,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create");
+ PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_FORWARDBUILDERSTATE_TYPE,
+ sizeof (PKIX_ForwardBuilderState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT);
+
+ state->status = BUILD_INITIAL;
+ state->traversedCACerts = traversedCACerts;
+ state->certStoreIndex = 0;
+ state->numCerts = 0;
+ state->numAias = 0;
+ state->certIndex = 0;
+ state->aiaIndex = 0;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->hintCertIndex = 0;
+ state->numFanout = numFanout;
+ state->numDepth = numDepth;
+ state->reasonCode = 0;
+ state->revChecking = numDepth;
+ state->canBeCached = canBeCached;
+ state->useOnlyLocal = PKIX_TRUE;
+ state->revChecking = PKIX_FALSE;
+ state->usingHintCerts = PKIX_FALSE;
+ state->certLoopingDetected = PKIX_FALSE;
+
+ PKIX_INCREF(validityDate);
+ state->validityDate = validityDate;
+
+ PKIX_INCREF(prevCert);
+ state->prevCert = prevCert;
+
+ state->candidateCert = NULL;
+
+ PKIX_INCREF(traversedSubjNames);
+ state->traversedSubjNames = traversedSubjNames;
+
+ PKIX_INCREF(trustChain);
+ state->trustChain = trustChain;
+
+ state->aia = NULL;
+ state->candidateCerts = NULL;
+ state->reversedCertChain = NULL;
+ state->checkedCritExtOIDs = NULL;
+ state->checkerChain = NULL;
+ state->certSel = NULL;
+ state->verifyNode = NULL;
+ state->client = NULL;
+
+ PKIX_INCREF(parentState);
+ state->parentState = parentState;
+
+ if (parentState != NULL) {
+ state->buildConstants.numAnchors =
+ parentState->buildConstants.numAnchors;
+ state->buildConstants.numCertStores =
+ parentState->buildConstants.numCertStores;
+ state->buildConstants.numHintCerts =
+ parentState->buildConstants.numHintCerts;
+ state->buildConstants.maxFanout =
+ parentState->buildConstants.maxFanout;
+ state->buildConstants.maxDepth =
+ parentState->buildConstants.maxDepth;
+ state->buildConstants.maxTime =
+ parentState->buildConstants.maxTime;
+ state->buildConstants.procParams =
+ parentState->buildConstants.procParams;
+ state->buildConstants.testDate =
+ parentState->buildConstants.testDate;
+ state->buildConstants.timeLimit =
+ parentState->buildConstants.timeLimit;
+ state->buildConstants.targetCert =
+ parentState->buildConstants.targetCert;
+ state->buildConstants.targetPubKey =
+ parentState->buildConstants.targetPubKey;
+ state->buildConstants.certStores =
+ parentState->buildConstants.certStores;
+ state->buildConstants.anchors =
+ parentState->buildConstants.anchors;
+ state->buildConstants.userCheckers =
+ parentState->buildConstants.userCheckers;
+ state->buildConstants.hintCerts =
+ parentState->buildConstants.hintCerts;
+ state->buildConstants.revChecker =
+ parentState->buildConstants.revChecker;
+ state->buildConstants.aiaMgr =
+ parentState->buildConstants.aiaMgr;
+ state->buildConstants.trustOnlyUserAnchors =
+ parentState->buildConstants.trustOnlyUserAnchors;
+ }
+
+ *pState = state;
+ state = NULL;
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_Build_GetResourceLimits
+ *
+ * DESCRIPTION:
+ * Retrieve Resource Limits from ProcessingParams and initialize them in
+ * BuildConstants.
+ *
+ * PARAMETERS
+ * "buildConstants"
+ * Address of a BuildConstants structure containing objects and values
+ * that remain constant throughout the building of a chain. 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 Build 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_Build_GetResourceLimits(
+ BuildConstants *buildConstants,
+ void *plContext)
+{
+ PKIX_ResourceLimits *resourceLimits = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits");
+ PKIX_NULLCHECK_ONE(buildConstants);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits
+ (buildConstants->procParams, &resourceLimits, plContext),
+ PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED);
+
+ buildConstants->maxFanout = 0;
+ buildConstants->maxDepth = 0;
+ buildConstants->maxTime = 0;
+
+ if (resourceLimits) {
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout
+ (resourceLimits, &buildConstants->maxFanout, plContext),
+ PKIX_RESOURCELIMITSGETMAXFANOUTFAILED);
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth
+ (resourceLimits, &buildConstants->maxDepth, plContext),
+ PKIX_RESOURCELIMITSGETMAXDEPTHFAILED);
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime
+ (resourceLimits, &buildConstants->maxTime, plContext),
+ PKIX_RESOURCELIMITSGETMAXTIMEFAILED);
+ }
+
+cleanup:
+
+ PKIX_DECREF(resourceLimits);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ForwardBuilderState_ToString
+ (PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *buildStatusString = NULL;
+ PKIX_PL_String *validityDateString = NULL;
+ PKIX_PL_String *prevCertString = NULL;
+ PKIX_PL_String *candidateCertString = NULL;
+ PKIX_PL_String *traversedSubjNamesString = NULL;
+ PKIX_PL_String *trustChainString = NULL;
+ PKIX_PL_String *candidateCertsString = NULL;
+ PKIX_PL_String *certSelString = NULL;
+ PKIX_PL_String *verifyNodeString = NULL;
+ PKIX_PL_String *parentStateString = NULL;
+ char *asciiFormat = "\n"
+ "\t{buildStatus: \t%s\n"
+ "\ttraversedCACerts: \t%d\n"
+ "\tcertStoreIndex: \t%d\n"
+ "\tnumCerts: \t%d\n"
+ "\tnumAias: \t%d\n"
+ "\tcertIndex: \t%d\n"
+ "\taiaIndex: \t%d\n"
+ "\tnumFanout: \t%d\n"
+ "\tnumDepth: \t%d\n"
+ "\treasonCode: \t%d\n"
+ "\tcanBeCached: \t%d\n"
+ "\tuseOnlyLocal: \t%d\n"
+ "\trevChecking: \t%d\n"
+ "\tvalidityDate: \t%s\n"
+ "\tprevCert: \t%s\n"
+ "\tcandidateCert: \t%s\n"
+ "\ttraversedSubjNames: \t%s\n"
+ "\ttrustChain: \t%s\n"
+ "\tcandidateCerts: \t%s\n"
+ "\tcertSel: \t%s\n"
+ "\tverifyNode: \t%s\n"
+ "\tparentState: \t%s}\n";
+ char *asciiStatus = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTFORWARDBUILDERSTATE);
+
+ state = (PKIX_ForwardBuilderState *)object;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ switch (state->status) {
+ case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING";
+ break;
+ case BUILD_INITIAL: asciiStatus = "BUILD_INITIAL";
+ break;
+ case BUILD_TRYAIA: asciiStatus = "BUILD_TRYAIA";
+ break;
+ case BUILD_AIAPENDING: asciiStatus = "BUILD_AIAPENDING";
+ break;
+ case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS";
+ break;
+ case BUILD_GATHERPENDING: asciiStatus = "BUILD_GATHERPENDING";
+ break;
+ case BUILD_CERTVALIDATING: asciiStatus = "BUILD_CERTVALIDATING";
+ break;
+ case BUILD_ABANDONNODE: asciiStatus = "BUILD_ABANDONNODE";
+ break;
+ case BUILD_DATEPREP: asciiStatus = "BUILD_DATEPREP";
+ break;
+ case BUILD_CHECKTRUSTED: asciiStatus = "BUILD_CHECKTRUSTED";
+ break;
+ case BUILD_CHECKTRUSTED2: asciiStatus = "BUILD_CHECKTRUSTED2";
+ break;
+ case BUILD_ADDTOCHAIN: asciiStatus = "BUILD_ADDTOCHAIN";
+ break;
+ case BUILD_VALCHAIN: asciiStatus = "BUILD_VALCHAIN";
+ break;
+ case BUILD_VALCHAIN2: asciiStatus = "BUILD_VALCHAIN2";
+ break;
+ case BUILD_EXTENDCHAIN: asciiStatus = "BUILD_EXTENDCHAIN";
+ break;
+ case BUILD_GETNEXTCERT: asciiStatus = "BUILD_GETNEXTCERT";
+ break;
+ default: asciiStatus = "INVALID STATUS";
+ break;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING
+ (state->validityDate, &validityDateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->prevCert, &prevCertString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->candidateCert, &candidateCertString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->traversedSubjNames,
+ &traversedSubjNamesString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->trustChain, &trustChainString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->candidateCerts, &candidateCertsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->certSel, &certSelString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->verifyNode, &verifyNodeString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->parentState, &parentStateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ formatString,
+ buildStatusString,
+ (PKIX_Int32)state->traversedCACerts,
+ (PKIX_UInt32)state->certStoreIndex,
+ (PKIX_UInt32)state->numCerts,
+ (PKIX_UInt32)state->numAias,
+ (PKIX_UInt32)state->certIndex,
+ (PKIX_UInt32)state->aiaIndex,
+ (PKIX_UInt32)state->numFanout,
+ (PKIX_UInt32)state->numDepth,
+ (PKIX_UInt32)state->reasonCode,
+ state->canBeCached,
+ state->useOnlyLocal,
+ state->revChecking,
+ validityDateString,
+ prevCertString,
+ candidateCertString,
+ traversedSubjNamesString,
+ trustChainString,
+ candidateCertsString,
+ certSelString,
+ verifyNodeString,
+ parentStateString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = resultString;
+
+cleanup:
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(buildStatusString);
+ PKIX_DECREF(validityDateString);
+ PKIX_DECREF(prevCertString);
+ PKIX_DECREF(candidateCertString);
+ PKIX_DECREF(traversedSubjNamesString);
+ PKIX_DECREF(trustChainString);
+ PKIX_DECREF(candidateCertsString);
+ PKIX_DECREF(certSelString);
+ PKIX_DECREF(verifyNodeString);
+ PKIX_DECREF(parentStateString);
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_FORWARDBUILDERSTATE_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_ForwardBuilderState_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE,
+ "pkix_ForwardBuilderState_RegisterSelf");
+
+ entry.description = "ForwardBuilderState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState);
+ entry.destructor = pkix_ForwardBuilderState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = pkix_ForwardBuilderState_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+/*
+ * FUNCTION: pkix_ForwardBuilderState_DumpState
+ *
+ * DESCRIPTION:
+ * This function invokes the ToString function on the argument pointed to
+ * by "state".
+ * PARAMETERS:
+ * "state"
+ * The address of the ForwardBuilderState object. Must be non-NULL.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ */
+PKIX_Error *
+pkix_ForwardBuilderState_DumpState(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState");
+ PKIX_NULLCHECK_ONE(state);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ 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("In Phase 1: state = %s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+
+cleanup:
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+#endif
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_IsIOPending
+ * DESCRIPTION:
+ *
+ * This function determines whether the state of the ForwardBuilderState
+ * pointed to by "state" indicates I/O is in progress, and stores the Boolean
+ * result at "pPending".
+ *
+ * PARAMETERS:
+ * "state"
+ * The address of the ForwardBuilderState object. Must be non-NULL.
+ * "pPending"
+ * The address at which the result is 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 ForwardBuilderState 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_ForwardBuilderState_IsIOPending(
+ PKIX_ForwardBuilderState *state,
+ PKIX_Boolean *pPending,
+ void *plContext)
+{
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending");
+ PKIX_NULLCHECK_TWO(state, pPending);
+
+ if ((state->status == BUILD_GATHERPENDING) ||
+ (state->status == BUILD_CHECKTRUSTED2) ||
+ (state->status == BUILD_VALCHAIN2) ||
+ (state->status == BUILD_AIAPENDING)) {
+ *pPending = PKIX_TRUE;
+ } else {
+ *pPending = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/* --Private-BuildChain-Functions------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Build_SortCertComparator
+ * DESCRIPTION:
+ *
+ * This Function takes two Certificates cast in "obj1" and "obj2",
+ * compares them to determine which is a more preferable certificate
+ * for chain building. This Function is suitable for use as a
+ * comparator callback for pkix_List_BubbleSort, setting "*pResult" to
+ * > 0 if "obj1" is less desirable than "obj2" and < 0 if "obj1"
+ * is more desirable than "obj2".
+ *
+ * PARAMETERS:
+ * "obj1"
+ * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
+ * Must be non-NULL.
+ * "obj2"
+ * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where the comparison 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 Build 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_Build_SortCertComparator(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_Date *date1 = NULL;
+ PKIX_PL_Date *date2 = NULL;
+ PKIX_Int32 result = 0;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator");
+ PKIX_NULLCHECK_THREE(obj1, obj2, pResult);
+
+ /*
+ * For sorting candidate certificates, we use NotAfter date as the
+ * comparison key for now (can be expanded if desired in the future).
+ *
+ * In PKIX_BuildChain, the List of CertStores was reordered so that
+ * trusted CertStores are ahead of untrusted CertStores. That sort, or
+ * this one, could be taken out if it is determined that it doesn't help
+ * performance, or in some way hinders the solution of choosing desired
+ * candidates.
+ */
+
+ PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+ PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ ((PKIX_PL_Cert *)obj1, &date1, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ ((PKIX_PL_Cert *)obj2, &date2, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)date1,
+ (PKIX_PL_Object *)date2,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ /*
+ * Invert the result, so that if date1 is greater than date2,
+ * obj1 is sorted before obj2. This is because pkix_List_BubbleSort
+ * sorts in ascending order.
+ */
+ *pResult = -result;
+
+cleanup:
+
+ PKIX_DECREF(date1);
+ PKIX_DECREF(date2);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* This local error check macro */
+#define ERROR_CHECK(errCode) \
+ if (pkixErrorResult) { \
+ if (pkixLog) { \
+ PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCode)); \
+ } \
+ pkixTempErrorReceived = PKIX_TRUE; \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ if (pkixErrorClass == PKIX_FATAL_ERROR) { \
+ goto cleanup; \
+ } \
+ if (verifyNode) { \
+ PKIX_DECREF(verifyNode->error); \
+ PKIX_INCREF(pkixErrorResult); \
+ verifyNode->error = pkixErrorResult; \
+ } \
+ pkixErrorCode = errCode; \
+ goto cleanup; \
+ }
+
+/*
+ * FUNCTION: pkix_Build_VerifyCertificate
+ * DESCRIPTION:
+ *
+ * Checks whether the previous Cert stored in the ForwardBuilderState pointed
+ * to by "state" successfully chains, including signature verification, to the
+ * candidate Cert also stored in "state", using the Boolean value in "trusted"
+ * to determine whether "candidateCert" is trusted.
+ *
+ * First it checks whether "candidateCert" has already been traversed by
+ * determining whether it is contained in the List of traversed Certs. It then
+ * checks the candidate Cert with user checkers, if any, in the List pointed to
+ * by "userCheckers". Finally, it runs the signature validation.
+ *
+ * If this Certificate fails verification, and state->verifyNode is non-NULL,
+ * this function sets the Error code into the verifyNode.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "userCheckers"
+ * Address of a List of CertChainCheckers to be used, if present, to
+ * validate the candidateCert.
+ * "trusted"
+ * Boolean value of trust for the candidate Cert
+ * "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 Build 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_Build_VerifyCertificate(
+ PKIX_ForwardBuilderState *state,
+ PKIX_List *userCheckers,
+ PKIX_Boolean *pTrusted,
+ PKIX_VerifyNode *verifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean loopFound = PKIX_FALSE;
+ PKIX_Boolean supportForwardChecking = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_PL_Cert *candidateCert = NULL;
+ PKIX_PL_PublicKey *candidatePubKey = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
+ PKIX_PL_TrustAnchorMode trustAnchorMode =
+ PKIX_PL_TrustAnchorMode_Ignore;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate");
+ PKIX_NULLCHECK_TWO(state, pTrusted);
+ PKIX_NULLCHECK_THREE
+ (state->candidateCerts, state->prevCert, state->trustChain);
+
+ PKIX_INCREF(state->candidateCert);
+ candidateCert = state->candidateCert;
+
+ if (state->buildConstants.numAnchors) {
+ if (state->buildConstants.trustOnlyUserAnchors) {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive;
+ } else {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive;
+ }
+ } else {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode,
+ &trusted, plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+
+ *pTrusted = trusted;
+
+ /* check for loops */
+ PKIX_CHECK(pkix_List_Contains
+ (state->trustChain,
+ (PKIX_PL_Object *)candidateCert,
+ &loopFound,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (loopFound) {
+ if (verifyNode != NULL) {
+ PKIX_Error *verifyError = NULL;
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
+ verifyError);
+ PKIX_DECREF(verifyNode->error);
+ verifyNode->error = verifyError;
+ }
+ /* Even if error logged, still need to abort
+ * if cert is not trusted. */
+ if (!trusted) {
+ PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
+ }
+ state->certLoopingDetected = PKIX_TRUE;
+ }
+
+ if (userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwardChecking, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwardChecking == PKIX_TRUE) {
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
+ (userChecker, &checkerCheck, plContext),
+ PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
+
+ pkixErrorResult =
+ checkerCheck(userChecker, candidateCert, NULL,
+ &nbioContext, plContext);
+
+ ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED);
+ }
+
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ /* Check that public key of the trusted dsa cert has
+ * dsa parameters */
+ if (trusted) {
+ PKIX_Boolean paramsNeeded = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (candidateCert, &candidatePubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+ PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters
+ (candidatePubKey, &paramsNeeded, plContext),
+ PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED);
+ if (paramsNeeded) {
+ PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS);
+ }
+ }
+
+cleanup:
+ PKIX_DECREF(candidateCert);
+ PKIX_DECREF(candidatePubKey);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ValidationCheckers
+ * DESCRIPTION:
+ *
+ * Creates a List of Objects to be used in determining whether the List of
+ * Certs pointed to by "certChain" successfully validates using the
+ * ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by
+ * "anchor". These objects are a reversed Cert Chain, consisting of the certs
+ * in "certChain" in reversed order, suitable for presenting to the
+ * CertChainCheckers; a List of critical extension OIDS that have already been
+ * processed in forward building; a List of CertChainCheckers to be called, and
+ * a List of RevocationCheckers to be called. These results are stored in
+ * fields of "state".
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "certChain"
+ * Address of List of Certs to be validated. Must be non-NULL.
+ * "anchor"
+ * Address of TrustAnchor to be used. Must be non-NULL.
+ * "addEkuChecker"
+ * Boolean flags that tells to add eku checker to the list
+ * of checkers. Only needs to be done for existing chain revalidation.
+ * "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 Build 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_Build_ValidationCheckers(
+ PKIX_ForwardBuilderState *state,
+ PKIX_List *certChain,
+ PKIX_TrustAnchor *anchor,
+ PKIX_Boolean chainRevalidationStage,
+ void *plContext)
+{
+ PKIX_List *checkers = NULL;
+ PKIX_List *initialPolicies = NULL;
+ PKIX_List *reversedCertChain = NULL;
+ PKIX_List *buildCheckedCritExtOIDsList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_PL_CertNameConstraints *trustedNC = NULL;
+ PKIX_CertChainChecker *sigChecker = NULL;
+ PKIX_CertChainChecker *policyChecker = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_CertChainChecker *nameConstraintsChecker = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_PL_OID *oid = NULL;
+ PKIX_Boolean supportForwardChecking = PKIX_FALSE;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_UInt32 numChainCerts;
+ PKIX_UInt32 numCertCheckers;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers");
+ PKIX_NULLCHECK_THREE(state, certChain, anchor);
+
+ PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_ReverseList
+ (certChain, &reversedCertChain, plContext),
+ PKIX_LISTREVERSELISTFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (reversedCertChain, &numChainCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ procParams = state->buildConstants.procParams;
+
+ /* Do need to add a number of checker to revalidate
+ * a built chain. KU, EKU, CertType and Validity Date
+ * get checked by certificate selector during chain
+ * construction, but needed to be checked for chain from
+ * the cache.*/
+ if (chainRevalidationStage) {
+ PKIX_CHECK(pkix_ExpirationChecker_Initialize
+ (state->buildConstants.testDate, &checker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(checker);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_TargetCertChecker_Initialize
+ (certSelector, numChainCerts, &checker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(checker);
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
+ (procParams, &initialPolicies, plContext),
+ PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ (procParams, &policyQualifiersRejected, plContext),
+ PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
+ (procParams, &initialPolicyMappingInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
+ (procParams, &initialAnyPolicyInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
+ (procParams, &initialExplicitPolicy, plContext),
+ PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Initialize
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numChainCerts,
+ &policyChecker,
+ plContext),
+ PKIX_POLICYCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)policyChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /*
+ * Create an OID list that contains critical extensions processed
+ * by BuildChain. These are specified in a static const array.
+ */
+ PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) {
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (buildCheckedCritExtOIDs[i], &oid, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (buildCheckedCritExtOIDsList,
+ (PKIX_PL_Object *) oid,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(oid);
+ }
+
+ if (state->buildConstants.userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->buildConstants.userCheckers,
+ &numCertCheckers,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numCertCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwardChecking, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ /*
+ * If this userChecker supports forwardChecking then it
+ * should have been checked during build chain. Skip
+ * checking but need to add checker's extension OIDs
+ * to buildCheckedCritExtOIDsList.
+ */
+ if (supportForwardChecking == PKIX_TRUE) {
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (buildCheckedCritExtOIDsList,
+ userCheckerExtOIDs,
+ plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)userChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ /* Enabling post chain building signature check on the certs. */
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(pkix_SignatureChecker_Initialize
+ (trustedPubKey,
+ numChainCerts,
+ &sigChecker,
+ plContext),
+ PKIX_SIGNATURECHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)sigChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /* Enabling post chain building name constraints check on the certs. */
+ PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
+ (anchor, &trustedNC, plContext),
+ PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
+ (trustedNC, numChainCerts, &nameConstraintsChecker,
+ plContext),
+ PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)nameConstraintsChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+
+ PKIX_DECREF(state->reversedCertChain);
+ PKIX_INCREF(reversedCertChain);
+ state->reversedCertChain = reversedCertChain;
+ PKIX_DECREF(state->checkedCritExtOIDs);
+ PKIX_INCREF(buildCheckedCritExtOIDsList);
+ state->checkedCritExtOIDs = buildCheckedCritExtOIDsList;
+ PKIX_DECREF(state->checkerChain);
+ state->checkerChain = checkers;
+ checkers = NULL;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->revChecking = PKIX_FALSE;
+
+
+cleanup:
+
+ PKIX_DECREF(oid);
+ PKIX_DECREF(reversedCertChain);
+ PKIX_DECREF(buildCheckedCritExtOIDsList);
+ PKIX_DECREF(checker);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(initialPolicies);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(trustedPubKey);
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(sigChecker);
+ PKIX_DECREF(trustedNC);
+ PKIX_DECREF(nameConstraintsChecker);
+ PKIX_DECREF(policyChecker);
+ PKIX_DECREF(userChecker);
+ PKIX_DECREF(userCheckerExtOIDs);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ValidateEntireChain
+ * DESCRIPTION:
+ *
+ * Checks whether the current List of Certs successfully validates using the
+ * TrustAnchor pointed to by "anchor" and other parameters contained, as was
+ * the Cert List, in "state".
+ *
+ * If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O
+ * context (NBIOContext), an indication that I/O is in progress and the
+ * checking has not been completed, this function stores that context at
+ * "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext".
+ *
+ * If not awaiting I/O and if successful, a ValidateResult is created
+ * containing the Public Key of the target certificate (including DSA parameter
+ * inheritance, if any) and the PolicyNode representing the policy tree output
+ * by the validation algorithm. If not successful, an Error pointer is
+ * returned.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "anchor"
+ * Address of TrustAnchor to be used. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pValResult"
+ * Address at which the ValidateResult is 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 Build 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_Build_ValidateEntireChain(
+ PKIX_ForwardBuilderState *state,
+ PKIX_TrustAnchor *anchor,
+ void **pNBIOContext,
+ PKIX_ValidateResult **pValResult,
+ PKIX_VerifyNode *verifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChainCerts = 0;
+ PKIX_PL_PublicKey *subjPubKey = NULL;
+ PKIX_PolicyNode *policyTree = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain");
+ PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult);
+
+ *pNBIOContext = NULL; /* prepare for case of error exit */
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->reversedCertChain, &numChainCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ pkixErrorResult =
+ pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor,
+ state->checkerChain,
+ state->buildConstants.revChecker,
+ state->checkedCritExtOIDs,
+ state->buildConstants.procParams,
+ &state->certCheckedIndex, &state->checkerIndex,
+ &state->revChecking, &state->reasonCode,
+ &nbioContext, &subjPubKey, &policyTree, NULL,
+ plContext);
+
+ if (nbioContext != NULL) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ ERROR_CHECK(PKIX_CHECKCHAINFAILED);
+
+ /* XXX Remove this assertion after 2014-12-31. See bug 946984. */
+ PORT_Assert(state->reasonCode == 0);
+
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (subjPubKey, anchor, policyTree, &valResult, plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pValResult = valResult;
+ valResult = NULL;
+
+cleanup:
+ PKIX_DECREF(subjPubKey);
+ PKIX_DECREF(policyTree);
+ PKIX_DECREF(valResult);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_SortCandidateCerts
+ * DESCRIPTION:
+ *
+ * This function sorts a List of candidate Certs pointed to by "candidates"
+ * using an algorithm that places Certs most likely to produce a successful
+ * chain at the front of the list, storing the resulting sorted List at
+ * "pSortedCandidates".
+ *
+ * At present the only sort criterion is that trusted Certs go ahead of
+ * untrusted Certs.
+ *
+ * PARAMETERS:
+ * "candidates"
+ * Address of List of Candidate Certs to be sorted. Must be non-NULL.
+ * "pSortedCandidates"
+ * Address at which sorted List is 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 Build 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_Build_SortCandidateCerts(
+ PKIX_List *candidates,
+ PKIX_List **pSortedCandidates,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts");
+ PKIX_NULLCHECK_TWO(candidates, pSortedCandidates);
+
+ /*
+ * Both bubble and quick sort algorithms are available.
+ * For a list of fewer than around 100 items, the bubble sort is more
+ * efficient. (This number was determined by experimenting with both
+ * algorithms on a Java List.)
+ * If the candidate list is very small, using the sort can drag down
+ * the performance a little bit.
+ */
+
+ PKIX_CHECK(pkix_List_BubbleSort
+ (candidates,
+ pkix_Build_SortCertComparator,
+ &sortedList,
+ plContext),
+ PKIX_LISTBUBBLESORTFAILED);
+
+ *pSortedCandidates = sortedList;
+
+cleanup:
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_BuildSelectorAndParams
+ * DESCRIPTION:
+ *
+ * This function creates a CertSelector, initialized with an appropriate
+ * ComCertSelParams, using the variables provided in the ForwardBuilderState
+ * pointed to by "state". The CertSelector created is stored in the certsel
+ * element of "state".
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. 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 Build 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_Build_BuildSelectorAndParams(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_PL_X500Name *currentIssuer = NULL;
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_CertSelector *callerCertSelector = NULL;
+ PKIX_ComCertSelParams *callerComCertSelParams = NULL;
+ PKIX_UInt32 reqKu = 0;
+ PKIX_List *reqEkuOids = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams");
+ PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (state->prevCert, &currentIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (state->prevCert, &authKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetSubject
+ (certSelParams, currentIssuer, plContext),
+ PKIX_COMCERTSELPARAMSSETSUBJECTFAILED);
+
+ if (authKeyId != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ (certSelParams, authKeyId, plContext),
+ PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED);
+ }
+
+ PKIX_INCREF(state->buildConstants.testDate);
+ testDate = state->buildConstants.testDate;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid
+ (certSelParams, testDate, plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints
+ (certSelParams, state->traversedCACerts, plContext),
+ PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames
+ (certSelParams, state->traversedSubjNames, plContext),
+ PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (state->buildConstants.procParams,
+ &callerCertSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ if (callerCertSelector != NULL) {
+
+ /* Get initial EKU OIDs from ComCertSelParams, if set */
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (callerCertSelector, &callerComCertSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ if (callerComCertSelParams != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (callerComCertSelParams, &reqEkuOids, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
+ (callerComCertSelParams, &reqKu, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+ }
+ }
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams,
+ reqEkuOids,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &state->certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (state->certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ state->certStoreIndex = 0;
+
+cleanup:
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(certSel);
+ PKIX_DECREF(currentIssuer);
+ PKIX_DECREF(authKeyId);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(reqEkuOids);
+ PKIX_DECREF(callerComCertSelParams);
+ PKIX_DECREF(callerCertSelector);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* Match trust anchor to select params in order to find next cert. */
+static PKIX_Error*
+pkix_Build_SelectCertsFromTrustAnchors(
+ PKIX_List *trustAnchorsList,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List **pMatchList,
+ void *plContext)
+{
+ unsigned int anchorIndex = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_List *matchList = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_CertSelector_MatchCallback selectorMatchCB = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors");
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (certSel, &selectorMatchCB, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(trustAnchorsList,
+ anchorIndex,
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+ pkixErrorResult =
+ (*selectorMatchCB)(certSel, trustedCert, plContext);
+ if (!pkixErrorResult) {
+ if (!matchList) {
+ PKIX_CHECK(PKIX_List_Create(&matchList,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ PKIX_CHECK(
+ PKIX_List_AppendItem(matchList,
+ (PKIX_PL_Object*)trustedCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(anchor);
+ }
+
+ *pMatchList = matchList;
+ matchList = NULL;
+
+cleanup:
+ PKIX_DECREF(matchList);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(certSel);
+
+ PKIX_RETURN(BUILD);
+}
+
+
+static PKIX_Error*
+pkix_Build_RemoveDupUntrustedCerts(
+ PKIX_List *trustedCertList,
+ PKIX_List *certsFound,
+ void *plContext)
+{
+ PKIX_UInt32 trustIndex;
+ PKIX_PL_Cert *trustCert = NULL, *cert = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts");
+ if (trustedCertList == NULL || certsFound == NULL) {
+ goto cleanup;
+ }
+ for (trustIndex = 0;trustIndex < trustedCertList->length;
+ trustIndex++) {
+ PKIX_UInt32 certIndex = 0;
+ PKIX_CHECK(
+ PKIX_List_GetItem(trustedCertList,
+ trustIndex,
+ (PKIX_PL_Object **)&trustCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ while (certIndex < certsFound->length) {
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_DECREF(cert);
+ PKIX_CHECK(
+ PKIX_List_GetItem(certsFound, certIndex,
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(
+ PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert,
+ (PKIX_PL_Object *)cert,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ if (!result) {
+ certIndex += 1;
+ continue;
+ }
+ PKIX_CHECK(
+ PKIX_List_DeleteItem(certsFound, certIndex,
+ plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ }
+ PKIX_DECREF(trustCert);
+ }
+cleanup:
+ PKIX_DECREF(cert);
+ PKIX_DECREF(trustCert);
+
+ PKIX_RETURN(BUILD);
+}
+
+
+/*
+ * FUNCTION: pkix_Build_GatherCerts
+ * DESCRIPTION:
+ *
+ * This function traverses the CertStores in the List of CertStores contained
+ * in "state", using the certSelector and other parameters contained in
+ * "state", to obtain a List of all available Certs that satisfy the criteria.
+ * If a CertStore has a cache, "certSelParams" is used both to query the cache
+ * and, if an actual CertStore search occurred, to update the cache. (Behavior
+ * is undefined if "certSelParams" is different from the parameters that were
+ * used to initialize the certSelector in "state".)
+ *
+ * If a CertStore using non-blocking I/O returns with an indication that I/O is
+ * in progress and the checking has not been completed, this function stores
+ * platform-dependent information at "pNBIOContext". Otherwise it stores NULL
+ * at "pNBIOContext", and state is updated with the results of the search.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams which were used in creating the current
+ * CertSelector, and to be used in querying and updating any caches that
+ * may be associated with with the CertStores.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is returned if request
+ * is suspended for non-blocking I/O. 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 Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+/* return NULL if wouldblock, empty list if none found, else list of found */
+static PKIX_Error *
+pkix_Build_GatherCerts(
+ PKIX_ForwardBuilderState *state,
+ PKIX_ComCertSelParams *certSelParams,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_Boolean certStoreIsCached = PKIX_FALSE;
+ PKIX_Boolean certStoreIsLocal = PKIX_FALSE;
+ PKIX_Boolean foundInCache = PKIX_FALSE;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore_CertCallback getCerts = NULL;
+ PKIX_List *certsFound = NULL;
+ PKIX_List *trustedCertList = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_GatherCerts");
+ PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_DECREF(state->candidateCerts);
+
+ while (state->certStoreIndex < state->buildConstants.numCertStores) {
+
+ /* Get the current CertStore */
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.certStores,
+ state->certStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetLocalFlag
+ (certStore, &certStoreIsLocal, plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+
+ if (state->useOnlyLocal == certStoreIsLocal) {
+ /* If GATHERPENDING, we've already checked the cache */
+ if (state->status == BUILD_GATHERPENDING) {
+ certStoreIsCached = PKIX_FALSE;
+ foundInCache = PKIX_FALSE;
+ } else {
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
+ (certStore, &certStoreIsCached, plContext),
+ PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
+
+ if (certStoreIsCached) {
+ /*
+ * Look for Certs in the cache, using the SubjectName as
+ * the key. Then the ComCertSelParams are used to filter
+ * for qualified certs. If none are found, then the
+ * certStores are queried. When we eventually add items
+ * to the cache, we will only add items that passed the
+ * ComCertSelParams filter, rather than all Certs which
+ * matched the SubjectName.
+ */
+
+ PKIX_CHECK(pkix_CacheCert_Lookup
+ (certStore,
+ certSelParams,
+ state->buildConstants.testDate,
+ &foundInCache,
+ &certsFound,
+ plContext),
+ PKIX_CACHECERTCHAINLOOKUPFAILED);
+
+ }
+ }
+
+ /*
+ * XXX need to verify if Cert is trusted, hence may not
+ * be worth it to have the Cert Cached or
+ * If it is trusted, don't cache, but once there is cached
+ * certs, we won't get certs from database any more.
+ * can use flag to force not getting certs from cache
+ */
+ if (!foundInCache) {
+
+ if (nbioContext == NULL) {
+ PKIX_CHECK(PKIX_CertStore_GetCertCallback
+ (certStore, &getCerts, plContext),
+ PKIX_CERTSTOREGETCERTCALLBACKFAILED);
+
+ PKIX_CHECK(getCerts
+ (certStore,
+ state->certSel,
+ state->verifyNode,
+ &nbioContext,
+ &certsFound,
+ plContext),
+ PKIX_GETCERTSFAILED);
+ } else {
+ PKIX_CHECK(PKIX_CertStore_CertContinue
+ (certStore,
+ state->certSel,
+ state->verifyNode,
+ &nbioContext,
+ &certsFound,
+ plContext),
+ PKIX_CERTSTORECERTCONTINUEFAILED);
+ }
+
+ if (certStoreIsCached && certsFound) {
+
+ PKIX_CHECK(pkix_CacheCert_Add
+ (certStore,
+ certSelParams,
+ certsFound,
+ plContext),
+ PKIX_CACHECERTADDFAILED);
+ }
+ }
+
+ /*
+ * getCerts returns an empty list for "NONE FOUND",
+ * a NULL list for "would block"
+ */
+ if (certsFound == NULL) {
+ state->status = BUILD_GATHERPENDING;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ }
+
+ /* Are there any more certStores to query? */
+ PKIX_DECREF(certStore);
+ ++(state->certStoreIndex);
+ }
+
+ if (certsFound && certsFound->length > 1) {
+ PKIX_List *sorted = NULL;
+
+ /* sort Certs to try to optimize search */
+ PKIX_CHECK(pkix_Build_SortCandidateCerts
+ (certsFound, &sorted, plContext),
+ PKIX_BUILDSORTCANDIDATECERTSFAILED);
+ PKIX_DECREF(certsFound);
+ certsFound = sorted;
+ }
+
+ PKIX_CHECK(
+ pkix_Build_SelectCertsFromTrustAnchors(
+ state->buildConstants.anchors,
+ certSelParams, &trustedCertList,
+ plContext),
+ PKIX_FAILTOSELECTCERTSFROMANCHORS);
+ PKIX_CHECK(
+ pkix_Build_RemoveDupUntrustedCerts(trustedCertList,
+ certsFound,
+ plContext),
+ PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED);
+
+ PKIX_CHECK(
+ pkix_List_MergeLists(trustedCertList,
+ certsFound,
+ &state->candidateCerts,
+ plContext),
+ PKIX_LISTMERGEFAILED);
+
+ /* No, return the list we have gathered */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->candidateCerts, &state->numCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ state->certIndex = 0;
+
+cleanup:
+ PKIX_DECREF(trustedCertList);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(certsFound);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_UpdateDate
+ * DESCRIPTION:
+ *
+ * This function updates the validityDate contained in "state", for the current
+ * CertChain contained in "state", to include the validityDate of the
+ * candidateCert contained in "state". The validityDate of a chain is the
+ * earliest of all the notAfter dates contained in the respective Certificates.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. 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 Build 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_Build_UpdateDate(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_Boolean canBeCached = PKIX_FALSE;
+ PKIX_Int32 comparison = 0;
+ PKIX_PL_Date *notAfter = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_UpdateDate");
+ PKIX_NULLCHECK_ONE(state);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag
+ (state->candidateCert, &canBeCached, plContext),
+ PKIX_CERTGETCACHEFLAGFAILED);
+
+ state->canBeCached = state->canBeCached && canBeCached;
+ if (state->canBeCached == PKIX_TRUE) {
+
+ /*
+ * So far, all certs can be cached. Update cert
+ * chain validity time, which is the earliest of
+ * all certs' notAfter times.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ (state->candidateCert, &notAfter, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ if (state->validityDate == NULL) {
+ state->validityDate = notAfter;
+ notAfter = NULL;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)state->validityDate,
+ (PKIX_PL_Object *)notAfter,
+ &comparison,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ if (comparison > 0) {
+ PKIX_DECREF(state->validityDate);
+ state->validityDate = notAfter;
+ notAfter = NULL;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(notAfter);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* Prepare 'state' for the AIA round. */
+static void
+pkix_PrepareForwardBuilderStateForAIA(
+ PKIX_ForwardBuilderState *state)
+{
+ PORT_Assert(state->useOnlyLocal == PKIX_TRUE);
+ state->useOnlyLocal = PKIX_FALSE;
+ state->certStoreIndex = 0;
+ state->numFanout = state->buildConstants.maxFanout;
+ state->status = BUILD_TRYAIA;
+}
+
+extern SECStatus
+isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
+ CERTCertificate *referenceCert);
+
+/*
+ * FUNCTION: pkix_BuildForwardDepthFirstSearch
+ * DESCRIPTION:
+ *
+ * This function performs a depth first search in the "forward" direction (from
+ * the target Cert to the trust anchor). A non-NULL targetCert must be stored
+ * in the ForwardBuilderState before this function is called. It is not written
+ * recursively since execution may be suspended in in any of several places
+ * pending completion of non-blocking I/O. This iterative structure makes it
+ * much easier to resume where it left off.
+ *
+ * Since the nature of the search is recursive, the recursion is handled by
+ * chaining states. That is, each new step involves creating a new
+ * ForwardBuilderState linked to its predecessor. If a step turns out to be
+ * fruitless, the state of the predecessor is restored and the next alternative
+ * is tried. When a search is successful, values needed from the last state
+ * (canBeCached and validityDate) are copied to the state provided by the
+ * caller, so that the caller can retrieve those values.
+ *
+ * There are three return arguments, the NBIOContext, the ValidateResult and
+ * the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is
+ * suspended until the results of a non-blocking IO become available. The
+ * caller may wait for the completion using platform-dependent methods and then
+ * call this function again, allowing it to resume the search. If NBIOContext
+ * is NULL and the ValidateResult is non-NULL, it means the search has
+ * concluded successfully. If the NBIOContext is NULL but the ValidateResult is
+ * NULL, it means the search was unsuccessful.
+ *
+ * This function performs several steps at each node in the constructed chain:
+ *
+ * 1) It retrieves Certs from the registered CertStores that match the
+ * criteria established by the ForwardBuilderState pointed to by "state", such
+ * as a subject name matching the issuer name of the previous Cert. If there
+ * are no matching Certs, the function returns to the previous, or "parent",
+ * state and tries to continue the chain building with another of the Certs
+ * obtained from the CertStores as possible issuers for that parent Cert.
+ *
+ * 2) For each candidate Cert returned by the CertStores, this function checks
+ * whether the Cert is valid. If it is trusted, this function checks whether
+ * this Cert might serve as a TrustAnchor for a complete chain.
+ *
+ * 3) It determines whether this Cert, in conjunction with any of the
+ * TrustAnchors, might complete a chain. A complete chain, from this or the
+ * preceding step, is checked to see whether it is valid as a complete
+ * chain, including the checks that cannot be done in the forward direction.
+ *
+ * 4) If this Cert chains successfully, but is not a complete chain, that is,
+ * we have not reached a trusted Cert, a new ForwardBuilderState is created
+ * with this Cert as the immediate predecessor, and we continue in step (1),
+ * attempting to get Certs from the CertStores with this Certs "issuer" as
+ * their subject.
+ *
+ * 5) If an entire chain validates successfully, then we are done. A
+ * ValidateResult is created containing the Public Key of the target
+ * certificate (including DSA parameter inheritance, if any) and the
+ * PolicyNode representing the policy tree output by the validation algorithm,
+ * and stored at pValResult, and the function exits returning NULL.
+ *
+ * 5) If the entire chain does not validate successfully, the algorithm
+ * discards the latest Cert and continues in step 2 with the next candidate
+ * Cert, backing up to a parent state when no more possibilities exist at a
+ * given level, and returning failure when we try to back up but discover we
+ * are at the top level.
+ *
+ * PARAMETERS:
+ * "pNBIOContext"
+ * Address at which platform-dependent information is returned if building
+ * is suspended for non-blocking I/O. Must be non-NULL.
+ * "pState"
+ * Address at which input ForwardBuilderState is found, and at which output
+ * ForwardBuilderState is stored. Must be non-NULL.
+ * "pValResult"
+ * Address at which the ValidateResult is 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 Build 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_BuildForwardDepthFirstSearch(
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState *state,
+ PKIX_ValidateResult **pValResult,
+ void *plContext)
+{
+ PKIX_Boolean outOfOptions = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean canBeCached = PKIX_FALSE;
+ PKIX_Boolean ioPending = PKIX_FALSE;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_PL_Date *currTime = NULL;
+ PKIX_Int32 childTraversedCACerts = 0;
+ PKIX_UInt32 numSubjectNames = 0;
+ PKIX_UInt32 numChained = 0;
+ PKIX_Int32 cmpTimeResult = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 certsSoFar = 0;
+ PKIX_List *childTraversedSubjNames = NULL;
+ PKIX_List *subjectNames = NULL;
+ PKIX_List *unfilteredCerts = NULL;
+ PKIX_List *filteredCerts = NULL;
+ PKIX_PL_Object *subjectName = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_ForwardBuilderState *childState = NULL;
+ PKIX_ForwardBuilderState *parentState = NULL;
+ PKIX_PL_Object *revCheckerState = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_TrustAnchor *trustAnchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_VerifyNode *verifyNode = NULL;
+ PKIX_Error *verifyError = NULL;
+ PKIX_Error *finalError = NULL;
+ void *nbio = NULL;
+ PKIX_UInt32 numIterations = 0;
+
+ PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch");
+ PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ canBeCached = state->canBeCached;
+ PKIX_DECREF(*pValResult);
+ targetCert = state->buildConstants.targetCert;
+
+ /*
+ * We return if successful; if we fall off the end
+ * of this "while" clause our search has failed.
+ */
+ while (outOfOptions == PKIX_FALSE) {
+ /*
+ * The maximum number of iterations works around a bug that
+ * causes this while loop to never exit when AIA and cross
+ * certificates are involved. See bug xxxxx.
+ */
+ if (numIterations++ > 250)
+ PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
+
+ if (state->buildConstants.maxTime != 0) {
+ PKIX_DECREF(currTime);
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &currTime, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)state->buildConstants.timeLimit,
+ (PKIX_PL_Object *)currTime,
+ &cmpTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (cmpTimeResult < 0) {
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if we logged error, we still have to abort */
+ PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
+ }
+ }
+
+ if (state->status == BUILD_INITIAL) {
+
+ PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext),
+ PKIX_BUILDBUILDSELECTORANDPARAMSFAILED);
+
+ /*
+ * If the caller supplied a partial certChain (hintCerts) try
+ * the next one from that List before we go to the certStores.
+ */
+ if (state->buildConstants.numHintCerts > 0) {
+ /* How many Certs does our trust chain have already? */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->trustChain, &certsSoFar, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* That includes the target Cert. Don't count it. */
+ certsSoFar--;
+
+ /* Are we still within range of the partial chain? */
+ if (certsSoFar >= state->buildConstants.numHintCerts) {
+ state->status = BUILD_TRYAIA;
+ } else {
+ /*
+ * If we already have n certs, we want the n+1th
+ * (i.e., index = n) from the list of hints.
+ */
+ PKIX_DECREF(state->candidateCert);
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.hintCerts,
+ certsSoFar,
+ (PKIX_PL_Object **)&state->candidateCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->candidateCerts,
+ (PKIX_PL_Object *)state->candidateCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ state->numCerts = 1;
+ state->usingHintCerts = PKIX_TRUE;
+ state->status = BUILD_CERTVALIDATING;
+ }
+ } else {
+ state->status = BUILD_TRYAIA;
+ }
+
+ }
+
+ if (state->status == BUILD_TRYAIA) {
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ state->status = BUILD_COLLECTINGCERTS;
+ } else {
+ state->status = BUILD_AIAPENDING;
+ }
+ }
+
+ if (state->status == BUILD_AIAPENDING &&
+ state->buildConstants.aiaMgr) {
+ pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts
+ (state->buildConstants.aiaMgr,
+ state->prevCert,
+ &nbio,
+ &unfilteredCerts,
+ plContext);
+
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+ state->numCerts = 0;
+ if (pkixErrorResult) {
+ pkixErrorClass = pkixErrorResult->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto fatal;
+ }
+ PKIX_DECREF(finalError);
+ finalError = pkixErrorResult;
+ pkixErrorResult = NULL;
+ if (state->verifyNode != NULL) {
+ /* state->verifyNode is the object that contains a list
+ * of verifyNodes. verifyNodes contains cert chain
+ * build failures that occurred on this level of chain
+ * building. Here, creating new verify node
+ * to log the failure and adding it to the list. */
+ PKIX_CHECK_FATAL(pkix_VerifyNode_Create
+ (state->prevCert,
+ 0, NULL,
+ &verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, finalError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ }
+#ifdef PKIX_BUILDDEBUG
+ /* Turn this on to trace the List of Certs, before CertSelect */
+ {
+ PKIX_PL_String *unString;
+ char *unAscii;
+ PKIX_UInt32 length;
+ PKIX_TOSTRING
+ ((PKIX_PL_Object*)unfilteredCerts,
+ &unString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (unString,
+ PKIX_ESCASCII,
+ (void **)&unAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG
+ ("unfilteredCerts = %s\n", unAscii);
+ PKIX_DECREF(unString);
+ PKIX_FREE(unAscii);
+ }
+#endif
+
+ /* Note: Certs winnowed here don't get into VerifyTree. */
+ if (unfilteredCerts) {
+ PKIX_CHECK(pkix_CertSelector_Select
+ (state->certSel,
+ unfilteredCerts,
+ &filteredCerts,
+ plContext),
+ PKIX_CERTSELECTORSELECTFAILED);
+
+ PKIX_DECREF(unfilteredCerts);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (filteredCerts, &(state->numCerts), plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+#ifdef PKIX_BUILDDEBUG
+ /* Turn this on to trace the List of Certs, after CertSelect */
+ {
+ PKIX_PL_String *unString;
+ char *unAscii;
+ PKIX_UInt32 length;
+ PKIX_TOSTRING
+ ((PKIX_PL_Object*)filteredCerts,
+ &unString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (unString,
+ PKIX_ESCASCII,
+ (void **)&unAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii);
+ PKIX_DECREF(unString);
+ PKIX_FREE(unAscii);
+ }
+#endif
+
+ PKIX_DECREF(state->candidateCerts);
+ state->candidateCerts = filteredCerts;
+ state->certIndex = 0;
+ filteredCerts = NULL;
+ }
+
+ /* Are there any Certs to try? */
+ if (state->numCerts > 0) {
+ state->status = BUILD_CERTVALIDATING;
+ } else {
+ state->status = BUILD_COLLECTINGCERTS;
+ }
+ }
+
+ PKIX_DECREF(certSelParams);
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (state->certSel, &certSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ /* **** Querying the CertStores ***** */
+ if ((state->status == BUILD_COLLECTINGCERTS) ||
+ (state->status == BUILD_GATHERPENDING)) {
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+ PKIX_CHECK(pkix_ForwardBuilderState_DumpState
+ (state, plContext),
+ PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
+#endif
+
+ PKIX_CHECK(pkix_Build_GatherCerts
+ (state, certSelParams, &nbio, plContext),
+ PKIX_BUILDGATHERCERTSFAILED);
+
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+
+ /* Are there any Certs to try? */
+ if (state->numCerts > 0) {
+ state->status = BUILD_CERTVALIDATING;
+ } else {
+ state->status = BUILD_ABANDONNODE;
+ }
+ }
+
+ /* ****Phase 2 - Chain building***** */
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+ PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext),
+ PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
+#endif
+
+ if (state->status == BUILD_CERTVALIDATING) {
+ PKIX_DECREF(state->candidateCert);
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->candidateCerts,
+ state->certIndex,
+ (PKIX_PL_Object **)&(state->candidateCert),
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (isIssuerCertAllowedAtCertIssuanceTime(
+ state->candidateCert->nssCert, targetCert->nssCert)
+ != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTISBLOCKLISTEDATISSUANCETIME);
+ }
+
+ if ((state->verifyNode) != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_Create
+ (state->candidateCert,
+ 0,
+ NULL,
+ &verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ }
+
+ /* If failure, this function sets Error in verifyNode */
+ verifyError = pkix_Build_VerifyCertificate
+ (state,
+ state->buildConstants.userCheckers,
+ &trusted,
+ verifyNode,
+ plContext);
+
+ if (verifyError) {
+ pkixTempErrorReceived = PKIX_TRUE;
+ pkixErrorClass = verifyError->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ goto fatal;
+ }
+ }
+
+ if (PKIX_ERROR_RECEIVED) {
+ if (state->verifyNode != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, verifyError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ if (state->certLoopingDetected) {
+ PKIX_ERROR
+ (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
+ }
+ state->status = BUILD_GETNEXTCERT;
+ } else {
+ state->status = BUILD_DATEPREP;
+ }
+ }
+
+ if (state->status == BUILD_DATEPREP) {
+ /* Keep track of whether this chain can be cached */
+ PKIX_CHECK(pkix_Build_UpdateDate(state, plContext),
+ PKIX_BUILDUPDATEDATEFAILED);
+
+ canBeCached = state->canBeCached;
+ PKIX_DECREF(validityDate);
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ if (trusted == PKIX_TRUE) {
+ state->status = BUILD_CHECKTRUSTED;
+ } else {
+ state->status = BUILD_ADDTOCHAIN;
+ }
+ }
+
+ if (state->status == BUILD_CHECKTRUSTED) {
+
+ /*
+ * If this cert is trusted, try to validate the entire
+ * chain using this certificate as trust anchor.
+ */
+ PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert
+ (state->candidateCert,
+ &trustAnchor,
+ plContext),
+ PKIX_TRUSTANCHORCREATEWITHCERTFAILED);
+
+ PKIX_CHECK(pkix_Build_ValidationCheckers
+ (state,
+ state->trustChain,
+ trustAnchor,
+ PKIX_FALSE, /* do not add eku checker
+ * since eku was already
+ * checked */
+ plContext),
+ PKIX_BUILDVALIDATIONCHECKERSFAILED);
+
+ state->status = BUILD_CHECKTRUSTED2;
+ }
+
+ if (state->status == BUILD_CHECKTRUSTED2) {
+ verifyError =
+ pkix_Build_ValidateEntireChain(state,
+ trustAnchor,
+ &nbio, &valResult,
+ verifyNode,
+ plContext);
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ goto cleanup;
+ } else {
+ /* checking the error for fatal status */
+ if (verifyError) {
+ pkixTempErrorReceived = PKIX_TRUE;
+ pkixErrorClass = verifyError->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ goto fatal;
+ }
+ }
+ if (state->verifyNode != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ if (!PKIX_ERROR_RECEIVED) {
+ *pValResult = valResult;
+ valResult = NULL;
+ /* Change state so IsIOPending is FALSE */
+ state->status = BUILD_CHECKTRUSTED;
+ goto cleanup;
+ }
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ /* Reset temp error that was set by
+ * PKIX_CHECK_ONLY_FATAL and continue */
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(trustAnchor);
+ }
+
+ /*
+ * If chain doesn't validate with a trusted Cert,
+ * adding more Certs to it can't help.
+ */
+ if (state->certLoopingDetected) {
+ PKIX_DECREF(verifyError);
+ PKIX_ERROR_CREATE(BUILD,
+ PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(verifyError);
+ }
+ state->status = BUILD_GETNEXTCERT;
+ }
+
+ /*
+ * This Cert was not trusted. Add it to our chain, and
+ * continue building. If we don't reach a trust anchor,
+ * we'll take it off later and continue without it.
+ */
+ if (state->status == BUILD_ADDTOCHAIN) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->trustChain,
+ (PKIX_PL_Object *)state->candidateCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ state->status = BUILD_EXTENDCHAIN;
+ }
+
+ if (state->status == BUILD_EXTENDCHAIN) {
+
+ /* Check whether we are allowed to extend the chain */
+ if ((state->buildConstants.maxDepth != 0) &&
+ (state->numDepth <= 1)) {
+
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, verifyError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode, verifyNode, plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if error logged, still need to abort */
+ PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS);
+ }
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (state->candidateCert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)state->traversedSubjNames,
+ (PKIX_PL_Object **)&childTraversedSubjNames,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (isSelfIssued) {
+ childTraversedCACerts = state->traversedCACerts;
+ } else {
+ childTraversedCACerts = state->traversedCACerts + 1;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (state->candidateCert,
+ &subjectNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+
+ if (subjectNames) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (subjectNames,
+ &numSubjectNames,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ } else {
+ numSubjectNames = 0;
+ }
+
+ for (i = 0; i < numSubjectNames; i++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (subjectNames,
+ i,
+ &subjectName,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_NULLCHECK_ONE
+ (state->traversedSubjNames);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->traversedSubjNames,
+ subjectName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(subjectName);
+ }
+ PKIX_DECREF(subjectNames);
+ }
+
+ PKIX_CHECK(pkix_ForwardBuilderState_Create
+ (childTraversedCACerts,
+ state->buildConstants.maxFanout,
+ state->numDepth - 1,
+ canBeCached,
+ validityDate,
+ state->candidateCert,
+ childTraversedSubjNames,
+ state->trustChain,
+ state,
+ &childState,
+ plContext),
+ PKIX_FORWARDBUILDSTATECREATEFAILED);
+
+ PKIX_DECREF(childTraversedSubjNames);
+ PKIX_DECREF(certSelParams);
+ childState->verifyNode = verifyNode;
+ verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = childState; /* state->status == BUILD_INITIAL */
+ childState = NULL;
+ continue; /* with while (!outOfOptions) */
+ }
+
+ if (state->status == BUILD_GETNEXTCERT) {
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(state->candidateCert);
+
+ /*
+ * If we were using a Cert from the callier-supplied partial
+ * chain, delete it and go to the certStores.
+ */
+ if (state->usingHintCerts == PKIX_TRUE) {
+ PKIX_DECREF(state->candidateCerts);
+ PKIX_CHECK(PKIX_List_Create
+ (&state->candidateCerts, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ state->numCerts = 0;
+ state->usingHintCerts = PKIX_FALSE;
+ state->status = BUILD_TRYAIA;
+ continue;
+ } else if (++(state->certIndex) < (state->numCerts)) {
+ if ((state->buildConstants.maxFanout != 0) &&
+ (--(state->numFanout) == 0)) {
+
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_FANOUTEXCEEDSRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL
+ (pkix_VerifyNode_SetError
+ (state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if error logged, still need to abort */
+ PKIX_ERROR
+ (PKIX_FANOUTEXCEEDSRESOURCELIMITS);
+ }
+ state->status = BUILD_CERTVALIDATING;
+ continue;
+ }
+ }
+
+ /*
+ * Adding the current cert to the chain didn't help. If our search
+ * has been restricted to local certStores, try opening up the
+ * search and see whether that helps. Otherwise, back up to the
+ * parent cert, and see if there are any more to try.
+ */
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ pkix_PrepareForwardBuilderStateForAIA(state);
+ } else do {
+ if (state->parentState == NULL) {
+ /* We are at the top level, and can't back up! */
+ outOfOptions = PKIX_TRUE;
+ } else {
+ /*
+ * Try the next cert, if any, for this parent.
+ * Otherwise keep backing up until we reach a
+ * parent with more certs to try.
+ */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->trustChain, &numChained, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (state->trustChain, numChained - 1, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+
+ /* local and aia fetching returned no good certs.
+ * Creating a verify node in the parent that tells
+ * us this. */
+ if (!state->verifyNode) {
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_Create(state->prevCert,
+ 0, NULL,
+ &state->verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ }
+ /* Updating the log with the error. */
+ PKIX_DECREF(verifyError);
+ PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(verifyError);
+
+ PKIX_INCREF(state->parentState);
+ parentState = state->parentState;
+ PKIX_DECREF(verifyNode);
+ verifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = parentState;
+ parentState = NULL;
+ if (state->verifyNode != NULL && verifyNode) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ PKIX_DECREF(validityDate);
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ canBeCached = state->canBeCached;
+
+ /* Are there any more Certs to try? */
+ if (++(state->certIndex) < (state->numCerts)) {
+ state->status = BUILD_CERTVALIDATING;
+ PKIX_DECREF(state->candidateCert);
+ break;
+ }
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ /* Clean up and go for AIA round. */
+ pkix_PrepareForwardBuilderStateForAIA(state);
+ break;
+ }
+ }
+ PKIX_DECREF(state->candidateCert);
+ } while (outOfOptions == PKIX_FALSE);
+
+ } /* while (outOfOptions == PKIX_FALSE) */
+
+cleanup:
+
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto fatal;
+ }
+
+ /* verifyNode should be equal to NULL at this point. Assert it.
+ * Temporarelly use verifyError to store an error ref to which we
+ * have in pkixErrorResult. This is done to prevent error cloberring
+ * while using macros below. */
+ PORT_Assert(verifyError == NULL);
+ verifyError = pkixErrorResult;
+
+ /*
+ * We were called with an initialState that had no parent. If we are
+ * returning with an error or with a result, we must destroy any state
+ * that we created (any state with a parent).
+ */
+
+ PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending
+ (state, &ioPending, plContext),
+ PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED);
+
+ if (ioPending == PKIX_FALSE) {
+ while (state->parentState) {
+ PKIX_INCREF(state->parentState);
+ parentState = state->parentState;
+ PKIX_DECREF(verifyNode);
+ verifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = parentState;
+ parentState = NULL;
+ if (state->verifyNode != NULL && verifyNode) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ }
+ state->canBeCached = canBeCached;
+ PKIX_DECREF(state->validityDate);
+ state->validityDate = validityDate;
+ validityDate = NULL;
+ }
+ if (!*pValResult && !verifyError) {
+ if (!finalError) {
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_FindError(state->verifyNode,
+ &finalError,
+ plContext),
+ PKIX_VERIFYNODEFINDERRORFAILED);
+ }
+ if (finalError) {
+ pkixErrorResult = finalError;
+ pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED;
+ finalError = NULL;
+ goto fatal;
+ }
+ pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER;
+ pkixErrorReceived = PKIX_TRUE;
+ PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode, verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ } else {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ }
+
+fatal:
+ if (state->parentState) {
+ /* parentState in "state" object should be NULL at this point.
+ * If itn't, that means that we got fatal error(we have jumped to
+ * "fatal" label) and we should destroy all state except the top one. */
+ while (state->parentState) {
+ PKIX_Error *error = NULL;
+ PKIX_ForwardBuilderState *prntState = state->parentState;
+ /* Dumb: need to increment parentState to avoid destruction
+ * of "build constants"(they get destroyed when parentState is
+ * set to NULL. */
+ PKIX_INCREF(prntState);
+ error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext);
+ if (error) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
+ }
+ /* No need to decref the parent state. It was already done by
+ * pkix_ForwardBuilderState_Destroy function. */
+ state = prntState;
+ }
+ }
+ PKIX_DECREF(parentState);
+ PKIX_DECREF(childState);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(verifyError);
+ PKIX_DECREF(finalError);
+ PKIX_DECREF(verifyNode);
+ PKIX_DECREF(childTraversedSubjNames);
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(subjectNames);
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(trustAnchor);
+ PKIX_DECREF(validityDate);
+ PKIX_DECREF(revCheckerState);
+ PKIX_DECREF(currTime);
+ PKIX_DECREF(filteredCerts);
+ PKIX_DECREF(unfilteredCerts);
+ PKIX_DECREF(trustedCert);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_CheckInCache
+ * DESCRIPTION:
+ *
+ * The function tries to locate a chain for a cert in the cert chain cache.
+ * If found, the chain goes through revocation chacking and returned back to
+ * caller. Chains that fail revocation check get removed from cache.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. 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 Build 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_Build_CheckInCache(
+ PKIX_ForwardBuilderState *state,
+ PKIX_BuildResult **pBuildResult,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_Error *buildError = NULL;
+ PKIX_TrustAnchor *matchingAnchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_Boolean cacheHit = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_Boolean stillValid = PKIX_FALSE;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_CheckInCache");
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ targetCert = state->buildConstants.targetCert;
+ anchors = state->buildConstants.anchors;
+ testDate = state->buildConstants.testDate;
+
+ /* Check whether this cert verification has been cached. */
+ PKIX_CHECK(pkix_CacheCertChain_Lookup
+ (targetCert,
+ anchors,
+ testDate,
+ &cacheHit,
+ &buildResult,
+ plContext),
+ PKIX_CACHECERTCHAINLOOKUPFAILED);
+
+ if (!cacheHit) {
+ goto cleanup;
+ }
+
+ /*
+ * We found something in cache. Verify that the anchor
+ * cert is still trusted,
+ */
+ PKIX_CHECK(PKIX_BuildResult_GetValidateResult
+ (buildResult, &valResult, plContext),
+ PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
+
+ PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor
+ (valResult, &matchingAnchor, plContext),
+ PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
+
+ PKIX_DECREF(valResult);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (matchingAnchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ if (anchors && state->buildConstants.numAnchors) {
+ /* Check if it is one of the trust anchors */
+ PKIX_CHECK(
+ pkix_List_Contains(anchors,
+ (PKIX_PL_Object *)matchingAnchor,
+ &trusted,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+
+ if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) ||
+ !state->buildConstants.numAnchors) {
+ /* If it is not one of the trust anchors and the trust anchors
+ * are supplemental, or if there are no trust anchors, then check
+ * if the cert is trusted directly.
+ */
+ PKIX_CHECK(
+ PKIX_PL_Cert_IsCertTrusted(trustedCert,
+ PKIX_PL_TrustAnchorMode_Ignore,
+ &trusted, plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+ if (!trusted) {
+ goto cleanup;
+ }
+ /*
+ * Since the key usage may vary for different
+ * applications, we need to verify the chain again.
+ * Reverification will be improved with a fix for 397805.
+ */
+ PKIX_CHECK(PKIX_BuildResult_GetCertChain
+ (buildResult, &certList, plContext),
+ PKIX_BUILDRESULTGETCERTCHAINFAILED);
+
+ PKIX_CHECK(pkix_Build_ValidationCheckers
+ (state,
+ certList,
+ matchingAnchor,
+ PKIX_TRUE, /* Chain revalidation stage. */
+ plContext),
+ PKIX_BUILDVALIDATIONCHECKERSFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_Build_ValidateEntireChain(state, matchingAnchor,
+ &nbioContext, &valResult,
+ state->verifyNode, plContext),
+ PKIX_BUILDVALIDATEENTIRECHAINFAILED);
+
+ if (nbioContext != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (!PKIX_ERROR_RECEIVED) {
+ /* The result from cache is still valid. But we replace an old*/
+ *pBuildResult = buildResult;
+ buildResult = NULL;
+ stillValid = PKIX_TRUE;
+ }
+
+cleanup:
+
+ if (!nbioContext && cacheHit && !(trusted && stillValid)) {
+ /* The anchor of this chain is no longer trusted or
+ * chain cert(s) has been revoked.
+ * Invalidate this result in the cache */
+ buildError = pkixErrorResult;
+ PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove
+ (targetCert,
+ anchors,
+ plContext),
+ PKIX_CACHECERTCHAINREMOVEFAILED);
+ pkixErrorResult = buildError;
+ buildError = NULL;
+ }
+
+fatal:
+ PKIX_DECREF(buildResult);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(buildError);
+ PKIX_DECREF(certList);
+ PKIX_DECREF(matchingAnchor);
+ PKIX_DECREF(trustedCert);
+
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_InitiateBuildChain
+ * DESCRIPTION:
+ *
+ * This function initiates the search for a BuildChain, using the parameters
+ * provided in "procParams" and, if continuing a search that was suspended
+ * for I/O, using the ForwardBuilderState pointed to by "pState".
+ *
+ * If a successful chain is built, this function stores the BuildResult at
+ * "pBuildResult". Alternatively, if an operation using non-blocking I/O
+ * is in progress and the operation has not been completed, this function
+ * stores the platform-dependent non-blocking I/O context (nbioContext) at
+ * "pNBIOContext", the FowardBuilderState at "pState", and NULL at
+ * "pBuildResult". Finally, if chain building was unsuccessful, this function
+ * stores NULL at both "pState" and at "pBuildResult".
+ *
+ * Note: This function is re-entered only for the case of non-blocking I/O
+ * in the "short-cut" attempt to build a chain using the target Certificate
+ * directly with one of the trustAnchors. For all other cases, resumption
+ * after non-blocking I/O is via pkix_Build_ResumeBuildChain.
+ *
+ * PARAMETERS:
+ * "procParams"
+ * Address of the ProcessingParams for the search. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pState"
+ * Address at which the ForwardBuilderState is stored, if the chain
+ * building is suspended for waiting I/O; also, the address at which the
+ * ForwardBuilderState is provided for resumption of the chain building
+ * attempt. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * Must be non-NULL.
+ * "pVerifyNode"
+ * Address at which a VerifyNode chain is returned, if 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 Build 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_Build_InitiateBuildChain(
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numAnchors = 0;
+ PKIX_UInt32 numCertStores = 0;
+ PKIX_UInt32 numHintCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean isDuplicate = PKIX_FALSE;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_CertSelector *targetConstraints = NULL;
+ PKIX_ComCertSelParams *targetParams = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *targetSubjNames = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_PL_Object *firstHintCert = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_PL_PublicKey *targetPubKey = NULL;
+ void *nbioContext = NULL;
+ BuildConstants buildConstants;
+
+ PKIX_List *tentativeChain = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_CertSelector_MatchCallback selectorCallback = NULL;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain");
+ PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ state = *pState;
+ *pState = NULL; /* no net change in reference count */
+
+ if (state == NULL) {
+ PKIX_CHECK(PKIX_ProcessingParams_GetDate
+ (procParams, &testDate, plContext),
+ PKIX_PROCESSINGPARAMSGETDATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
+ (procParams, &anchors, plContext),
+ PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* retrieve stuff from targetCertConstraints */
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &targetConstraints, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (targetConstraints, &targetParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
+ (targetParams, &targetCert, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetLeafCertFlag(targetParams,
+ PKIX_TRUE, plContext),
+ PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts
+ (procParams, &hintCerts, plContext),
+ PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED);
+
+ if (hintCerts != NULL) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (hintCerts, &numHintCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /*
+ * Caller must provide either a target Cert
+ * (in ComCertSelParams->Certificate) or a partial Cert
+ * chain (in ProcParams->HintCerts).
+ */
+
+ if (targetCert == NULL) {
+
+ /* Use first cert of hintCerts as the targetCert */
+ if (numHintCerts == 0) {
+ PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (hintCerts,
+ 0,
+ (PKIX_PL_Object **)&targetCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext),
+ PKIX_LISTGETITEMFAILED);
+ } else {
+
+ /*
+ * If the first hintCert is the same as the targetCert,
+ * delete it from hintCerts.
+ */
+ if (numHintCerts != 0) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (hintCerts, 0, &firstHintCert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)targetCert,
+ firstHintCert,
+ &isDuplicate,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (isDuplicate) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (hintCerts, 0, plContext),
+ PKIX_LISTGETITEMFAILED);
+ }
+ PKIX_DECREF(firstHintCert);
+ }
+
+ }
+
+ if (targetCert == NULL) {
+ PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted
+ (targetCert,
+ &trusted,
+ plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (targetCert,
+ &targetSubjNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (targetCert, &targetPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (tentativeChain, (PKIX_PL_Object *)targetCert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (procParams->qualifyTargetCert) {
+ /* EE cert validation */
+ /* Sync up the time on the target selector parameter struct. */
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetCertificateValid(targetParams,
+ testDate,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (targetConstraints, &selectorCallback, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ pkixErrorResult =
+ (*selectorCallback)(targetConstraints, targetCert,
+ plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = pkixErrorResult->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto cleanup;
+ }
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0,
+ pkixErrorResult,
+ pVerifyNode,
+ plContext);
+ if (tempResult) {
+ PKIX_DECREF(pkixErrorResult);
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+ pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED;
+ goto cleanup;
+ }
+ }
+
+ /* If the EE cert is trusted, force success. We only want to do
+ * this if we aren't validating against a policy (like EV). */
+ if (trusted && procParams->initialPolicies == NULL) {
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0, NULL,
+ pVerifyNode,
+ plContext);
+ if (tempResult) {
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (targetPubKey, NULL /* anchor */,
+ NULL /* policyTree */, &valResult, plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, tentativeChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ /* Note that *pState is NULL. The only side effect is that
+ * the cert chain won't be cached in PKIX_BuildChain, which
+ * is fine. */
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (certStores, &numCertStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Reorder CertStores so trusted are at front of the List */
+ if (numCertStores > 1) {
+ for (i = numCertStores - 1; i > 0; i--) {
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
+ (certStores,
+ i,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback
+ (certStore, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ if (trustCallback != NULL) {
+ /* Is a trusted Cert, move CertStore to front */
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (certStores, i, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ PKIX_CHECK(PKIX_List_InsertItem
+ (certStores,
+ 0,
+ (PKIX_PL_Object *)certStore,
+ plContext),
+ PKIX_LISTINSERTITEMFAILED);
+
+ }
+
+ PKIX_DECREF(certStore);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+ /* Do not initialize AIA manager if we are not going to fetch
+ * cert using aia url. */
+ if (procParams->useAIAForCertFetching) {
+ PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext),
+ PKIX_AIAMGRCREATEFAILED);
+ }
+
+ /*
+ * We initialize all the fields of buildConstants here, in one place,
+ * just to help keep track and ensure that we got everything.
+ */
+
+ buildConstants.numAnchors = numAnchors;
+ buildConstants.numCertStores = numCertStores;
+ buildConstants.numHintCerts = numHintCerts;
+ buildConstants.procParams = procParams;
+ buildConstants.testDate = testDate;
+ buildConstants.timeLimit = NULL;
+ buildConstants.targetCert = targetCert;
+ buildConstants.targetPubKey = targetPubKey;
+ buildConstants.certStores = certStores;
+ buildConstants.anchors = anchors;
+ buildConstants.userCheckers = userCheckers;
+ buildConstants.hintCerts = hintCerts;
+ buildConstants.revChecker = revChecker;
+ buildConstants.aiaMgr = aiaMgr;
+ buildConstants.trustOnlyUserAnchors =
+ procParams->useOnlyTrustAnchors;
+
+ PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext),
+ PKIX_BUILDGETRESOURCELIMITSFAILED);
+
+ PKIX_CHECK(pkix_ForwardBuilderState_Create
+ (0, /* PKIX_UInt32 traversedCACerts */
+ buildConstants.maxFanout,
+ buildConstants.maxDepth,
+ PKIX_TRUE, /* PKIX_Boolean canBeCached */
+ NULL, /* PKIX_Date *validityDate */
+ targetCert, /* PKIX_PL_Cert *prevCert */
+ targetSubjNames, /* PKIX_List *traversedSubjNames */
+ tentativeChain, /* PKIX_List *trustChain */
+ NULL, /* PKIX_ForwardBuilderState *parent */
+ &state, /* PKIX_ForwardBuilderState **pState */
+ plContext),
+ PKIX_BUILDSTATECREATEFAILED);
+
+ state->buildConstants.numAnchors = buildConstants.numAnchors;
+ state->buildConstants.numCertStores = buildConstants.numCertStores;
+ state->buildConstants.numHintCerts = buildConstants.numHintCerts;
+ state->buildConstants.maxFanout = buildConstants.maxFanout;
+ state->buildConstants.maxDepth = buildConstants.maxDepth;
+ state->buildConstants.maxTime = buildConstants.maxTime;
+ state->buildConstants.procParams = buildConstants.procParams;
+ PKIX_INCREF(buildConstants.testDate);
+ state->buildConstants.testDate = buildConstants.testDate;
+ state->buildConstants.timeLimit = buildConstants.timeLimit;
+ PKIX_INCREF(buildConstants.targetCert);
+ state->buildConstants.targetCert = buildConstants.targetCert;
+ PKIX_INCREF(buildConstants.targetPubKey);
+ state->buildConstants.targetPubKey =
+ buildConstants.targetPubKey;
+ PKIX_INCREF(buildConstants.certStores);
+ state->buildConstants.certStores = buildConstants.certStores;
+ PKIX_INCREF(buildConstants.anchors);
+ state->buildConstants.anchors = buildConstants.anchors;
+ PKIX_INCREF(buildConstants.userCheckers);
+ state->buildConstants.userCheckers =
+ buildConstants.userCheckers;
+ PKIX_INCREF(buildConstants.hintCerts);
+ state->buildConstants.hintCerts = buildConstants.hintCerts;
+ PKIX_INCREF(buildConstants.revChecker);
+ state->buildConstants.revChecker = buildConstants.revChecker;
+ state->buildConstants.aiaMgr = buildConstants.aiaMgr;
+ aiaMgr = NULL;
+ state->buildConstants.trustOnlyUserAnchors =
+ buildConstants.trustOnlyUserAnchors;
+
+ if (buildConstants.maxTime != 0) {
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (buildConstants.maxTime,
+ &state->buildConstants.timeLimit,
+ plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+ }
+
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0, NULL,
+ &(state->verifyNode),
+ plContext);
+ if (tempResult) {
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_Build_CheckInCache(state, &buildResult,
+ &nbioContext, plContext),
+ PKIX_UNABLETOBUILDCHAIN);
+ if (nbioContext) {
+ *pNBIOContext = nbioContext;
+ *pState = state;
+ state = NULL;
+ goto cleanup;
+ }
+ if (buildResult) {
+ *pBuildResult = buildResult;
+ if (pVerifyNode != NULL) {
+ *pVerifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ }
+ goto cleanup;
+ }
+ }
+
+ /* If we're resuming after non-blocking I/O we need to get SubjNames */
+ if (targetSubjNames == NULL) {
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (state->buildConstants.targetCert,
+ &targetSubjNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+ }
+
+ state->status = BUILD_INITIAL;
+
+ pkixErrorResult =
+ pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
+ &valResult, plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (pkixErrorResult == NULL && nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pBuildResult = NULL;
+
+ /* no valResult means the build has failed */
+ } else {
+ if (pVerifyNode != NULL) {
+ PKIX_INCREF(state->verifyNode);
+ *pVerifyNode = state->verifyNode;
+ }
+
+ if (valResult == NULL || pkixErrorResult)
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, state->trustChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ }
+
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(targetConstraints);
+ PKIX_DECREF(targetParams);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(targetSubjNames);
+ PKIX_DECREF(targetCert);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(hintCerts);
+ PKIX_DECREF(firstHintCert);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(targetPubKey);
+ PKIX_DECREF(tentativeChain);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(certList);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(state);
+ PKIX_DECREF(aiaMgr);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ResumeBuildChain
+ * DESCRIPTION:
+ *
+ * This function continues the search for a BuildChain, using the parameters
+ * provided in "procParams" and the ForwardBuilderState pointed to by "state".
+ *
+ * If a successful chain is built, this function stores the BuildResult at
+ * "pBuildResult". Alternatively, if an operation using non-blocking I/O
+ * is in progress and the operation has not been completed, this function
+ * stores the FowardBuilderState at "pState" and NULL at "pBuildResult".
+ * Finally, if chain building was unsuccessful, this function stores NULL
+ * at both "pState" and at "pBuildResult".
+ *
+ * PARAMETERS:
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pState"
+ * Address at which the ForwardBuilderState is provided for resumption of
+ * the chain building attempt; also, the address at which the
+ * ForwardBuilderStateis stored, if the chain building is suspended for
+ * waiting I/O. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * 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 Build 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_Build_ResumeBuildChain(
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState *state,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain");
+ PKIX_NULLCHECK_TWO(state, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ pkixErrorResult =
+ pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
+ &valResult, plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (pkixErrorResult == NULL && nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pBuildResult = NULL;
+
+ /* no valResult means the build has failed */
+ } else {
+ if (pVerifyNode != NULL) {
+ PKIX_INCREF(state->verifyNode);
+ *pVerifyNode = state->verifyNode;
+ }
+
+ if (valResult == NULL || pkixErrorResult)
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, state->trustChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ }
+
+cleanup:
+
+ PKIX_DECREF(valResult);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_BuildChain (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_BuildChain(
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "PKIX_BuildChain");
+ PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ if (*pState == NULL) {
+ PKIX_CHECK(pkix_Build_InitiateBuildChain
+ (procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ } else {
+ state = (PKIX_ForwardBuilderState *)(*pState);
+ *pState = NULL; /* no net change in reference count */
+ if (state->status == BUILD_SHORTCUTPENDING) {
+ PKIX_CHECK(pkix_Build_InitiateBuildChain
+ (procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ } else {
+ PKIX_CHECK(pkix_Build_ResumeBuildChain
+ (&nbioContext,
+ state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ }
+ }
+
+ /* non-null nbioContext means the build would block */
+ if (nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pState = state;
+ state = NULL;
+ *pBuildResult = NULL;
+
+ /* no buildResult means the build has failed */
+ } else if (buildResult == NULL) {
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+ } else {
+ /*
+ * If we made a successful chain by combining the target Cert
+ * with one of the Trust Anchors, we may have never created a
+ * validityDate. We treat this situation as
+ * canBeCached = PKIX_FALSE.
+ */
+ if ((state != NULL) &&
+ ((state->validityDate) != NULL) &&
+ (state->canBeCached)) {
+ PKIX_CHECK(pkix_CacheCertChain_Add
+ (state->buildConstants.targetCert,
+ state->buildConstants.anchors,
+ state->validityDate,
+ buildResult,
+ plContext),
+ PKIX_CACHECERTCHAINADDFAILED);
+ }
+
+ *pState = NULL;
+ *pBuildResult = buildResult;
+ buildResult = NULL;
+ }
+
+cleanup:
+ PKIX_DECREF(buildResult);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(BUILD);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.h b/security/nss/lib/libpkix/pkix/top/pkix_build.h
new file mode 100644
index 0000000000..eeba9239d8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_build.h
@@ -0,0 +1,120 @@
+/* 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_build.h
+ *
+ * Header file for buildChain function
+ *
+ */
+
+#ifndef _PKIX_BUILD_H
+#define _PKIX_BUILD_H
+#include "pkix_tools.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapt.h"
+#endif
+#include "pkix_ekuchecker.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ BUILD_SHORTCUTPENDING,
+ BUILD_INITIAL,
+ BUILD_TRYAIA,
+ BUILD_AIAPENDING,
+ BUILD_COLLECTINGCERTS,
+ BUILD_GATHERPENDING,
+ BUILD_CERTVALIDATING,
+ BUILD_ABANDONNODE,
+ BUILD_DATEPREP,
+ BUILD_CHECKTRUSTED,
+ BUILD_CHECKTRUSTED2,
+ BUILD_ADDTOCHAIN,
+ BUILD_VALCHAIN,
+ BUILD_VALCHAIN2,
+ BUILD_EXTENDCHAIN,
+ BUILD_GETNEXTCERT
+} BuildStatus;
+
+typedef struct BuildConstantsStruct BuildConstants;
+
+/*
+ * These fields (the ones that are objects) are not reference-counted
+ * in *each* state, but only in the root, the state that has no parent.
+ * That saves time in creation and destruction of child states, but is
+ * safe enough since they are constants.
+ */
+struct BuildConstantsStruct {
+ PKIX_UInt32 numAnchors;
+ PKIX_UInt32 numCertStores;
+ PKIX_UInt32 numHintCerts;
+ PKIX_UInt32 maxDepth;
+ PKIX_UInt32 maxFanout;
+ PKIX_UInt32 maxTime;
+ PKIX_ProcessingParams *procParams;
+ PKIX_PL_Date *testDate;
+ PKIX_PL_Date *timeLimit;
+ PKIX_PL_Cert *targetCert;
+ PKIX_PL_PublicKey *targetPubKey;
+ PKIX_List *certStores;
+ PKIX_List *anchors;
+ PKIX_List *userCheckers;
+ PKIX_List *hintCerts;
+ PKIX_RevocationChecker *revChecker;
+ PKIX_PL_AIAMgr *aiaMgr;
+ PKIX_Boolean useAIAForCertFetching;
+ PKIX_Boolean trustOnlyUserAnchors;
+};
+
+struct PKIX_ForwardBuilderStateStruct{
+ BuildStatus status;
+ PKIX_Int32 traversedCACerts;
+ PKIX_UInt32 certStoreIndex;
+ PKIX_UInt32 numCerts;
+ PKIX_UInt32 numAias;
+ PKIX_UInt32 certIndex;
+ PKIX_UInt32 aiaIndex;
+ PKIX_UInt32 certCheckedIndex;
+ PKIX_UInt32 checkerIndex;
+ PKIX_UInt32 hintCertIndex;
+ PKIX_UInt32 numFanout;
+ PKIX_UInt32 numDepth;
+ PKIX_UInt32 reasonCode;
+ PKIX_Boolean canBeCached;
+ PKIX_Boolean useOnlyLocal;
+ PKIX_Boolean revChecking;
+ PKIX_Boolean usingHintCerts;
+ PKIX_Boolean certLoopingDetected;
+ PKIX_PL_Date *validityDate;
+ PKIX_PL_Cert *prevCert;
+ PKIX_PL_Cert *candidateCert;
+ PKIX_List *traversedSubjNames;
+ PKIX_List *trustChain;
+ PKIX_List *aia;
+ PKIX_List *candidateCerts;
+ PKIX_List *reversedCertChain;
+ PKIX_List *checkedCritExtOIDs;
+ PKIX_List *checkerChain;
+ PKIX_CertSelector *certSel;
+ PKIX_VerifyNode *verifyNode;
+ void *client; /* messageHandler, such as LDAPClient */
+ PKIX_ForwardBuilderState *parentState;
+ BuildConstants buildConstants;
+};
+
+/* --Private-Functions-------------------------------------------- */
+
+PKIX_Error *
+pkix_ForwardBuilderState_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_Build_GetNBIOContext(void *state, void **pNBIOContext, void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BUILD_H */
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
new file mode 100644
index 0000000000..aad0e1aaf3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
@@ -0,0 +1,210 @@
+/* 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_lifecycle.c
+ *
+ * Top level initialize and shutdown functions
+ *
+ */
+
+#include "pkix_lifecycle.h"
+
+static PKIX_Boolean pkixIsInitialized;
+
+/* Lock used by Logger - is reentrant by the same thread */
+extern PKIX_PL_MonitorLock *pkixLoggerLock;
+
+/*
+ * Following pkix_* variables are for debugging purpose. They should be taken
+ * out eventually. The purpose is to verify cache tables usage (via debugger).
+ */
+int pkix_ccAddCount = 0;
+int pkix_ccLookupCount = 0;
+int pkix_ccRemoveCount = 0;
+int pkix_cAddCount = 0;
+int pkix_cLookupCount = 0;
+int pkix_cRemoveCount = 0;
+int pkix_ceAddCount = 0;
+int pkix_ceLookupCount = 0;
+
+PKIX_PL_HashTable *cachedCrlSigTable = NULL;
+PKIX_PL_HashTable *cachedCertSigTable = NULL;
+PKIX_PL_HashTable *cachedCertChainTable = NULL;
+PKIX_PL_HashTable *cachedCertTable = NULL;
+PKIX_PL_HashTable *cachedCrlEntryTable = NULL;
+PKIX_PL_HashTable *aiaConnectionCache = NULL;
+PKIX_PL_HashTable *httpSocketCache = NULL;
+
+extern PKIX_List *pkixLoggers;
+extern PKIX_List *pkixLoggersErrors;
+extern PKIX_List *pkixLoggersDebugTrace;
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Initialize (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_UInt32 desiredMajorVersion,
+ PKIX_UInt32 minDesiredMinorVersion,
+ PKIX_UInt32 maxDesiredMinorVersion,
+ PKIX_UInt32 *pActualMinorVersion,
+ void **pPlContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(LIFECYCLE, "PKIX_Initialize");
+ PKIX_NULLCHECK_ONE(pPlContext);
+
+ /*
+ * If we are called a second time other than in the situation handled
+ * above, we return a positive status.
+ */
+ if (pkixIsInitialized){
+ /* Already initialized */
+ PKIX_RETURN(LIFECYCLE);
+ }
+
+ PKIX_CHECK(PKIX_PL_Initialize
+ (platformInitNeeded, PKIX_FALSE, &plContext),
+ PKIX_INITIALIZEFAILED);
+
+ *pPlContext = plContext;
+
+ if (desiredMajorVersion != PKIX_MAJOR_VERSION){
+ PKIX_ERROR(PKIX_MAJORVERSIONSDONTMATCH);
+ }
+
+ if ((minDesiredMinorVersion > PKIX_MINOR_VERSION) ||
+ (maxDesiredMinorVersion < PKIX_MINOR_VERSION)){
+ PKIX_ERROR(PKIX_MINORVERSIONNOTBETWEENDESIREDMINANDMAX);
+ }
+
+ *pActualMinorVersion = PKIX_MINOR_VERSION;
+
+ /* Create Cache Tables
+ * Do not initialize hash tables for object leak test */
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 0, &cachedCertSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 0, &cachedCrlSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCertChainTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCertTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCrlEntryTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (5, 5, &aiaConnectionCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+#ifdef PKIX_SOCKETCACHE
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (5, 5, &httpSocketCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+#endif
+ if (pkixLoggerLock == NULL) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Create
+ (&pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKCREATEFAILED);
+ }
+#else
+ fnInvTable = PL_NewHashTable(0, pkix_ErrorGen_Hash,
+ PL_CompareValues,
+ PL_CompareValues, NULL, NULL);
+ if (!fnInvTable) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackNameArr = PORT_ZNewArray(char*, MAX_STACK_DEPTH);
+ if (!fnStackNameArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackInvCountArr = PORT_ZNewArray(PKIX_UInt32, MAX_STACK_DEPTH);
+ if (!fnStackInvCountArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ pkixIsInitialized = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LIFECYCLE);
+}
+
+/*
+ * FUNCTION: PKIX_Shutdown (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_Shutdown(void *plContext)
+{
+ PKIX_List *savedPkixLoggers = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+
+ PKIX_ENTER(LIFECYCLE, "PKIX_Shutdown");
+
+ if (!pkixIsInitialized){
+ /* The library was not initialized */
+ PKIX_RETURN(LIFECYCLE);
+ }
+
+ pkixIsInitialized = PKIX_FALSE;
+
+ if (pkixLoggers) {
+ savedPkixLoggers = pkixLoggers;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggers = NULL;
+ pkixLoggersErrors = NULL;
+ pkixLoggersDebugTrace = NULL;
+ PKIX_DECREF(savedPkixLoggers);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+ }
+ PKIX_DECREF(pkixLoggerLock);
+
+ /* Destroy Cache Tables */
+ PKIX_DECREF(cachedCertSigTable);
+ PKIX_DECREF(cachedCrlSigTable);
+ PKIX_DECREF(cachedCertChainTable);
+ PKIX_DECREF(cachedCertTable);
+ PKIX_DECREF(cachedCrlEntryTable);
+ PKIX_DECREF(aiaConnectionCache);
+ PKIX_DECREF(httpSocketCache);
+
+ /* Clean up any temporary errors that happened during shutdown */
+ if (pkixErrorList) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext);
+ pkixErrorList = NULL;
+ }
+
+ PKIX_CHECK(PKIX_PL_Shutdown(plContext),
+ PKIX_SHUTDOWNFAILED);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Free(fnStackInvCountArr);
+ PORT_Free(fnStackNameArr);
+ PL_HashTableDestroy(fnInvTable);
+#endif
+
+cleanup:
+
+ PKIX_RETURN(LIFECYCLE);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h
new file mode 100644
index 0000000000..02631229cb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h
@@ -0,0 +1,23 @@
+/* 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_lifecycle.h
+ *
+ * Header file for initialize and shutdown functions.
+ *
+ */
+
+#ifndef _PKIX_LIFECYCLE_H
+#define _PKIX_LIFECYCLE_H
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LIFECYCLE_H */
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.c b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
new file mode 100644
index 0000000000..1e5dec795a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
@@ -0,0 +1,1451 @@
+/* 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_validate.c
+ *
+ * Top level validateChain function
+ *
+ */
+
+#include "pkix_validate.h"
+#include "pkix_pl_common.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_AddToVerifyLog
+ * DESCRIPTION:
+ *
+ * This function returns immediately if the address for the VerifyNode tree
+ * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
+ * from the Cert pointed to by "cert" and the Error pointed to by "error",
+ * and inserts it at the depth in the VerifyNode tree determined by "depth". A
+ * depth of zero means that this function creates the root node of a new tree.
+ *
+ * Note: this function does not include the means of choosing among branches
+ * of a tree. It is intended for non-branching trees, that is, where each
+ * parent node has only a single child node.
+ *
+ * PARAMETERS:
+ * "cert"
+ * The address of the Cert to be included in the new VerifyNode. Must be
+ * non-NULL.
+ * "depth"
+ * The UInt32 value of the depth.
+ * "error"
+ * The address of the Error to be included in the new VerifyNode.
+ * "pVerifyTree"
+ * The address of the VerifyNode tree into which the created VerifyNode
+ * is to be inserted. The node is not created if VerifyTree is 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 Validate 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_AddToVerifyLog(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+
+ PKIX_VerifyNode *verifyNode = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
+ PKIX_NULLCHECK_ONE(cert);
+
+ if (pVerifyTree) { /* nothing to do if no address given for log */
+
+ PKIX_CHECK(pkix_VerifyNode_Create
+ (cert, depth, error, &verifyNode, plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+
+ if (depth == 0) {
+ /* We just created the root node */
+ *pVerifyTree = verifyNode;
+ } else {
+ PKIX_CHECK(pkix_VerifyNode_AddToChain
+ (*pVerifyTree, verifyNode, plContext),
+ PKIX_VERIFYNODEADDTOCHAINFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_CheckCert
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" successfully validates
+ * using the List of CertChainCheckers pointed to by "checkers". If the
+ * certificate does not validate, an Error pointer is returned.
+ *
+ * This function should be called initially with the UInt32 pointed to by
+ * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
+ * containing NULL. If a checker does non-blocking I/O, this function will
+ * return with the index of that checker stored at "pCheckerIndex" and a
+ * platform-dependent non-blocking I/O context stored at "pNBIOContext".
+ * A subsequent call to this function with those values intact will allow the
+ * checking to resume where it left off. This should be repeated until the
+ * function returns with NULL stored at "pNBIOContext".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert to validate. Must be non-NULL.
+ * "checkers"
+ * List of CertChainCheckers which must each validate the certificate.
+ * Must be non-NULL.
+ * "checkedExtOIDs"
+ * List of PKIX_PL_OID that has been processed. If called from building
+ * chain, it is the list of critical extension OIDs that has been
+ * processed prior to validation. May be NULL.
+ * "pCheckerIndex"
+ * Address at which is stored the the index, within the List "checkers",
+ * of a checker whose processing was interrupted by non-blocking I/O.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which is stored platform-specific non-blocking I/O context.
+ * 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 Validate 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_CheckCert(
+ PKIX_PL_Cert *cert,
+ PKIX_List *checkers,
+ PKIX_List *checkedExtOIDsList,
+ PKIX_UInt32 *pCheckerIndex,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_List *unresCritExtOIDs = NULL;
+ PKIX_UInt32 numCheckers;
+ PKIX_UInt32 numUnresCritExtOIDs = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_CheckCert");
+ PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL; /* prepare for case of error exit */
+
+ PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
+ (cert, &unresCritExtOIDs, plContext),
+ PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (checkerIndex = *pCheckerIndex;
+ checkerIndex < numCheckers;
+ checkerIndex++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (checkers,
+ checkerIndex,
+ (PKIX_PL_Object **)&checker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
+ (checker, &checkerCheck, plContext),
+ PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
+
+ PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
+ &nbioContext, plContext),
+ PKIX_CERTCHAINCHECKERCHECKFAILED);
+
+ if (nbioContext != NULL) {
+ *pCheckerIndex = checkerIndex;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_DECREF(checker);
+ }
+
+ if (unresCritExtOIDs){
+
+#ifdef PKIX_VALIDATEDEBUG
+ {
+ PKIX_PL_String *oidString = NULL;
+ PKIX_UInt32 length;
+ char *oidAscii = NULL;
+ PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (oidString,
+ PKIX_ESCASCII,
+ (void **) &oidAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_VALIDATE_DEBUG_ARG
+ ("unrecognized critical extension OIDs:"
+ " %s\n", oidAscii);
+ PKIX_DECREF(oidString);
+ PKIX_PL_Free(oidAscii, plContext);
+ }
+#endif
+
+ if (checkedExtOIDsList != NULL) {
+ /* Take out OID's that had been processed, if any */
+ PKIX_CHECK(pkix_List_RemoveItems
+ (unresCritExtOIDs,
+ checkedExtOIDsList,
+ plContext),
+ PKIX_LISTREMOVEITEMSFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numUnresCritExtOIDs != 0){
+ PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(unresCritExtOIDs);
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_InitializeCheckers
+ * DESCRIPTION:
+ *
+ * Creates several checkers and initializes them with values derived from the
+ * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
+ * "procParams", and the number of Certs in the Chain, represented by
+ * "numCerts". The List of checkers is stored at "pCheckers".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor used to initialize the SignatureChecker and
+ * NameChainingChecker. Must be non-NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the ExpirationChecker
+ * and TargetCertChecker. Must be non-NULL.
+ * "numCerts"
+ * Number of certificates in the CertChain.
+ * "pCheckers"
+ * 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 Validate 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_InitializeCheckers(
+ PKIX_TrustAnchor *anchor,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 numCerts,
+ PKIX_List **pCheckers,
+ void *plContext)
+{
+ PKIX_CertChainChecker *targetCertChecker = NULL;
+ PKIX_CertChainChecker *expirationChecker = NULL;
+ PKIX_CertChainChecker *nameChainingChecker = NULL;
+ PKIX_CertChainChecker *nameConstraintsChecker = NULL;
+ PKIX_CertChainChecker *basicConstraintsChecker = NULL;
+ PKIX_CertChainChecker *policyChecker = NULL;
+ PKIX_CertChainChecker *sigChecker = NULL;
+ PKIX_CertChainChecker *defaultCrlChecker = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_PL_X500Name *trustedCAName = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_CertNameConstraints *trustedNC = NULL;
+ PKIX_List *initialPolicies = NULL;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_List *userCheckersList = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_UInt32 numCertCheckers = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
+ PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
+ PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * The TrustAnchor may have been created using CreateWithCert
+ * (in which case GetCAPublicKey and GetCAName will return NULL)
+ * or may have been created using CreateWithNameKeyPair (in which
+ * case GetTrustedCert will return NULL. So we call GetTrustedCert
+ * and populate trustedPubKey and trustedCAName accordingly.
+ */
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ if (trustedCert){
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (trustedCert, &trustedCAName, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+ } else {
+ PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
+ (anchor, &trustedPubKey, plContext),
+ PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetCAName
+ (anchor, &trustedCAName, plContext),
+ PKIX_TRUSTANCHORGETCANAMEFAILED);
+ }
+
+ PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
+ (anchor, &trustedNC, plContext),
+ PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetDate
+ (procParams, &testDate, plContext),
+ PKIX_PROCESSINGPARAMSGETDATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
+ (procParams, &initialPolicies, plContext),
+ PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ (procParams, &policyQualifiersRejected, plContext),
+ PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
+ (procParams, &initialPolicyMappingInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
+ (procParams, &initialAnyPolicyInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
+ (procParams, &initialExplicitPolicy, plContext),
+ PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckersList, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ /* now, initialize all the checkers */
+ PKIX_CHECK(pkix_TargetCertChecker_Initialize
+ (certSelector, numCerts, &targetCertChecker, plContext),
+ PKIX_TARGETCERTCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_ExpirationChecker_Initialize
+ (testDate, &expirationChecker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_NameChainingChecker_Initialize
+ (trustedCAName, &nameChainingChecker, plContext),
+ PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
+ (trustedNC, numCerts, &nameConstraintsChecker, plContext),
+ PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
+ (numCerts, &basicConstraintsChecker, plContext),
+ PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Initialize
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numCerts,
+ &policyChecker,
+ plContext),
+ PKIX_POLICYCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_SignatureChecker_Initialize
+ (trustedPubKey, numCerts, &sigChecker, plContext),
+ PKIX_SIGNATURECHECKERINITIALIZEFAILED);
+
+ if (userCheckersList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckersList, &numCertCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numCertCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckersList,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)userChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)policyChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)sigChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ *pCheckers = checkers;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(checkers);
+ }
+
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(initialPolicies);
+ PKIX_DECREF(targetCertChecker);
+ PKIX_DECREF(expirationChecker);
+ PKIX_DECREF(nameChainingChecker);
+ PKIX_DECREF(nameConstraintsChecker);
+ PKIX_DECREF(basicConstraintsChecker);
+ PKIX_DECREF(policyChecker);
+ PKIX_DECREF(sigChecker);
+ PKIX_DECREF(trustedCAName);
+ PKIX_DECREF(trustedPubKey);
+ PKIX_DECREF(trustedNC);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(defaultCrlChecker);
+ PKIX_DECREF(userCheckersList);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_RetrieveOutputs
+ * DESCRIPTION:
+ *
+ * This function queries the respective states of the List of checkers in
+ * "checkers" to to obtain the final public key from the SignatureChecker
+ * and the policy tree from the PolicyChecker, storing those values at
+ * "pFinalSubjPubKey" and "pPolicyTree", respectively.
+ *
+ * PARAMETERS:
+ * "checkers"
+ * Address of List of checkers to be queried. Must be non-NULL.
+ * "pFinalSubjPubKey"
+ * Address where final public key will be stored. Must be non-NULL.
+ * "pPolicyTree"
+ * Address where policy tree 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 Validate 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_RetrieveOutputs(
+ PKIX_List *checkers,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *finalSubjPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_PL_Object *state = NULL;
+ PKIX_UInt32 numCheckers = 0;
+ PKIX_UInt32 type;
+ PKIX_Int32 j;
+
+ PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");
+
+ PKIX_NULLCHECK_TWO(checkers, pPolicyTree);
+
+ /*
+ * To optimize the search, we guess that the sigChecker is
+ * last in the tree and is preceded by the policyChecker. We
+ * search toward the front of the chain. Remember that List
+ * items are indexed 0..(numItems - 1).
+ */
+
+ PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (j = numCheckers - 1; j >= 0; j--){
+ PKIX_CHECK(PKIX_List_GetItem
+ (checkers, j, (PKIX_PL_Object **)&checker, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, &state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ /* user defined checker may have no state */
+ if (state != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
+ PKIX_OBJECTGETTYPEFAILED);
+
+ if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
+ /* final pubKey will include any inherited DSA params */
+ finalSubjPubKey =
+ ((pkix_SignatureCheckerState *)state)->
+ prevPublicKey;
+ PKIX_INCREF(finalSubjPubKey);
+ *pFinalSubjPubKey = finalSubjPubKey;
+ }
+
+ if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
+ validPolicyTree =
+ ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
+ break;
+ }
+ }
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(state);
+ }
+
+ PKIX_INCREF(validPolicyTree);
+ *pPolicyTree = validPolicyTree;
+
+cleanup:
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_CheckChain
+ * DESCRIPTION:
+ *
+ * Checks whether the List of Certs pointed to by "certs", containing
+ * "numCerts" entries, successfully validates using each CertChainChecker in
+ * the List pointed to by "checkers" and has not been revoked, according to any
+ * of the Revocation Checkers in the List pointed to by "revChecker". Checkers
+ * are expected to remove from "removeCheckedExtOIDs" and extensions that they
+ * process. Indices to the certChain and the checkerChain are obtained and
+ * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
+ * should be set to zero prior to the initial call, but may be changed (and
+ * must be supplied on subsequent calls) if processing is suspended for non-
+ * blocking I/O. Each time a Cert passes from being validated by one of the
+ * CertChainCheckers to being checked by a Revocation Checker, the Boolean
+ * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
+ * rejected by a Revocation Checker, its reason code is returned at
+ * "pReasonCode. If the List of Certs successfully validates, the public key i
+ * the final certificate is obtained and stored at "pFinalSubjPubKey" and the
+ * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
+ * of Certs fails to validate, an Error pointer is returned.
+ *
+ * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
+ * tracks the results of the validation. That is, either each node in the
+ * chain has a NULL Error component, or the last node contains an Error
+ * which indicates why the validation failed.
+ *
+ * The number of Certs in the List, represented by "numCerts", is used to
+ * determine which Cert is the final Cert.
+ *
+ * PARAMETERS:
+ * "certs"
+ * Address of List of Certs to validate. Must be non-NULL.
+ * "numCerts"
+ * Number of certificates in the List of certificates.
+ * "checkers"
+ * List of CertChainCheckers which must each validate the List of
+ * certificates. Must be non-NULL.
+ * "revChecker"
+ * List of RevocationCheckers which must each not reject the List of
+ * certificates. May be empty, but must be non-NULL.
+ * "removeCheckedExtOIDs"
+ * List of PKIX_PL_OID that has been processed. If called from building
+ * chain, it is the list of critical extension OIDs that has been
+ * processed prior to validation. Extension OIDs that may be processed by
+ * user defined checker processes are also in the list. May be NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize various checkers. Must
+ * be non-NULL.
+ * "pCertCheckedIndex"
+ * Address where Int32 index to the Cert chain is obtained and
+ * returned. Must be non-NULL.
+ * "pCheckerIndex"
+ * Address where Int32 index to the CheckerChain is obtained and
+ * returned. Must be non-NULL.
+ * "pRevChecking"
+ * Address where Boolean is obtained and returned, indicating, if FALSE,
+ * that CertChainCheckers are being called; or, if TRUE, that RevChecker
+ * are being called. Must be non-NULL.
+ * "pReasonCode"
+ * Address where UInt32 results of revocation checking are stored. Must be
+ * non-NULL.
+ * "pNBIOContext"
+ * Address where platform-dependent context is stored if checking is
+ * suspended for non-blocking I/O. Must be non-NULL.
+ * "pFinalSubjPubKey"
+ * Address where the final public key will be stored. Must be non-NULL.
+ * "pPolicyTree"
+ * Address where the final validPolicyTree is stored. Must be non-NULL.
+ * "pVerifyTree"
+ * Address where a VerifyTree is stored, if 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 Validate 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_CheckChain(
+ PKIX_List *certs,
+ PKIX_UInt32 numCerts,
+ PKIX_TrustAnchor *anchor,
+ PKIX_List *checkers,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_List *removeCheckedExtOIDs,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 *pCertCheckedIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_UInt32 *pReasonCode,
+ void **pNBIOContext,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_Error *checkCertError = NULL;
+ void *nbioContext = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *issuer = NULL;
+ PKIX_PL_NssContext *nssContext = NULL;
+ CERTCertList *certList = NULL;
+ const CERTChainVerifyCallback *chainVerifyCallback = NULL;
+ CERTCertificate *nssCert = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_CheckChain");
+ PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
+ PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
+ PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+ revChecking = *pRevChecking;
+ nssContext = (PKIX_PL_NssContext *)plContext;
+ chainVerifyCallback = &nssContext->chainVerifyCallback;
+
+ if (chainVerifyCallback->isChainValid != NULL) {
+ PRBool chainOK = PR_FALSE; /*assume failure*/
+ SECStatus rv;
+
+ certList = CERT_NewCertList();
+ if (certList == NULL) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ /* Add the trust anchor to the list */
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &cert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
+ PKIX_CERTGETCERTCERTIFICATEFAILED);
+
+ rv = CERT_AddCertToListHead(certList, nssCert);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ /* the certList takes ownership of nssCert on success */
+ nssCert = NULL;
+ PKIX_DECREF(cert);
+
+ /* Add the rest of the chain to the list */
+ for (j = *pCertCheckedIndex; j < numCerts; j++) {
+ PKIX_CHECK(PKIX_List_GetItem(
+ certs, j, (PKIX_PL_Object **)&cert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
+ PKIX_CERTGETCERTCERTIFICATEFAILED);
+
+ rv = CERT_AddCertToListHead(certList, nssCert);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ /* the certList takes ownership of nssCert on success */
+ nssCert = NULL;
+ PKIX_DECREF(cert);
+ }
+
+ rv = (*chainVerifyCallback->isChainValid)
+ (chainVerifyCallback->isChainValidArg, certList, &chainOK);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED);
+ }
+
+ if (!chainOK) {
+ PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED);
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &cert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ for (j = *pCertCheckedIndex; j < numCerts; j++) {
+
+ PORT_Assert(cert);
+ PKIX_DECREF(issuer);
+ issuer = cert;
+ cert = NULL;
+
+ PKIX_CHECK(PKIX_List_GetItem(
+ certs, j, (PKIX_PL_Object **)&cert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* check if cert pointer is valid */
+ PORT_Assert(cert);
+ if (cert == NULL) {
+ continue;
+ }
+
+ if (revChecking == PKIX_FALSE) {
+
+ PKIX_CHECK(pkix_CheckCert
+ (cert,
+ checkers,
+ removeCheckedExtOIDs,
+ pCheckerIndex,
+ &nbioContext,
+ plContext),
+ PKIX_CHECKCERTFAILED);
+
+ if (nbioContext != NULL) {
+ *pCertCheckedIndex = j;
+ *pRevChecking = revChecking;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ revChecking = PKIX_TRUE;
+ *pCheckerIndex = 0;
+ }
+
+ if (revChecking == PKIX_TRUE) {
+ PKIX_RevocationStatus revStatus;
+ pkixErrorResult =
+ PKIX_RevocationChecker_Check(
+ cert, issuer, revChecker,
+ procParams, PKIX_TRUE,
+ (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
+ &revStatus, pReasonCode,
+ &nbioContext, plContext);
+ if (nbioContext != NULL) {
+ *pCertCheckedIndex = j;
+ *pRevChecking = revChecking;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (revStatus == PKIX_RevStatus_Revoked ||
+ pkixErrorResult) {
+ if (!pkixErrorResult) {
+ /* if pkixErrorResult is returned then
+ * use it as it has a detailed revocation
+ * error code. Otherwise create a new error */
+ PKIX_ERROR_CREATE(VALIDATE,
+ PKIX_CERTIFICATEREVOKED,
+ pkixErrorResult);
+ }
+ goto cleanup;
+ }
+ revChecking = PKIX_FALSE;
+ *pCheckerIndex = 0;
+ }
+
+ PKIX_CHECK(pkix_AddToVerifyLog
+ (cert, j, NULL, pVerifyTree, plContext),
+ PKIX_ADDTOVERIFYLOGFAILED);
+ }
+
+ PKIX_CHECK(pkix_RetrieveOutputs
+ (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
+ PKIX_RETRIEVEOUTPUTSFAILED);
+
+ *pNBIOContext = NULL;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && cert) {
+ checkCertError = pkixErrorResult;
+
+ PKIX_CHECK_FATAL(
+ pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
+ plContext),
+ PKIX_ADDTOVERIFYLOGFAILED);
+ pkixErrorResult = checkCertError;
+ pkixErrorCode = pkixErrorResult->errCode;
+ checkCertError = NULL;
+ }
+
+fatal:
+ if (nssCert) {
+ CERT_DestroyCertificate(nssCert);
+ }
+
+ if (certList) {
+ CERT_DestroyCertList(certList);
+ }
+
+ PKIX_DECREF(checkCertError);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(issuer);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_ExtractParameters
+ * DESCRIPTION:
+ *
+ * Extracts several parameters from the ValidateParams object pointed to by
+ * "valParams" and stores the CertChain at "pChain", the List of Certs at
+ * "pCerts", the number of Certs in the chain at "pNumCerts", the
+ * ProcessingParams object at "pProcParams", the List of TrustAnchors at
+ * "pAnchors", and the number of TrustAnchors at "pNumAnchors".
+ *
+ * PARAMETERS:
+ * "valParams"
+ * Address of ValidateParams from which the parameters are extracted.
+ * Must be non-NULL.
+ * "pCerts"
+ * Address where object pointer for List of Certs will be stored.
+ * Must be non-NULL.
+ * "pNumCerts"
+ * Address where number of Certs will be stored. Must be non-NULL.
+ * "pProcParams"
+ * Address where object pointer for ProcessingParams will be stored.
+ * Must be non-NULL.
+ * "pAnchors"
+ * Address where object pointer for List of Anchors will be stored.
+ * Must be non-NULL.
+ * "pNumAnchors"
+ * Address where number of Anchors 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 Validate 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_ExtractParameters(
+ PKIX_ValidateParams *valParams,
+ PKIX_List **pCerts,
+ PKIX_UInt32 *pNumCerts,
+ PKIX_ProcessingParams **pProcParams,
+ PKIX_List **pAnchors,
+ PKIX_UInt32 *pNumAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
+ PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
+ PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);
+
+ /* extract relevant parameters from chain */
+ PKIX_CHECK(PKIX_ValidateParams_GetCertChain
+ (valParams, pCerts, plContext),
+ PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* extract relevant parameters from procParams */
+ PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
+ (valParams, pProcParams, plContext),
+ PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
+ (*pProcParams, pAnchors, plContext),
+ PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_ValidateChain(
+ PKIX_ValidateParams *valParams,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_Error *chainFailed = NULL;
+
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_List *validateCheckedCritExtOIDsList = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_PublicKey *finalPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_Boolean supportForwarding = PKIX_FALSE;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_UInt32 i, numCerts, numAnchors;
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 certCheckedIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_UInt32 reasonCode = 0;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
+ PKIX_NULLCHECK_TWO(valParams, pResult);
+
+ /* extract various parameters from valParams */
+ PKIX_CHECK(pkix_ExtractParameters
+ (valParams,
+ &certs,
+ &numCerts,
+ &procParams,
+ &anchors,
+ &numAnchors,
+ plContext),
+ PKIX_EXTRACTPARAMETERSFAILED);
+
+ /*
+ * setup an extension OID list that user had defined for his checker
+ * processing. User checker is not responsible for taking out OIDs
+ * from unresolved critical extension list as the libpkix checker
+ * is doing. Here we add those user checkers' OIDs to the removal
+ * list to be taken out by CheckChain
+ */
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ if (userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&validateCheckedCritExtOIDsList,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwarding, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwarding == PKIX_FALSE) {
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (validateCheckedCritExtOIDsList,
+ userCheckerExtOIDs,
+ plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+
+ /* try to validate the chain with each anchor */
+ for (i = 0; i < numAnchors; i++){
+
+ /* get trust anchor */
+ PKIX_CHECK(PKIX_List_GetItem
+ (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* initialize checkers using information from trust anchor */
+ PKIX_CHECK(pkix_InitializeCheckers
+ (anchor, procParams, numCerts, &checkers, plContext),
+ PKIX_INITIALIZECHECKERSFAILED);
+
+ /*
+ * Validate the chain using this trust anchor and these
+ * checkers. (WARNING: checkers that use non-blocking I/O
+ * are not currently supported.)
+ */
+ certCheckedIndex = 0;
+ checkerIndex = 0;
+ revChecking = PKIX_FALSE;
+ chainFailed = pkix_CheckChain
+ (certs,
+ numCerts,
+ anchor,
+ checkers,
+ revChecker,
+ validateCheckedCritExtOIDsList,
+ procParams,
+ &certCheckedIndex,
+ &checkerIndex,
+ &revChecking,
+ &reasonCode,
+ &nbioContext,
+ &finalPubKey,
+ &validPolicyTree,
+ pVerifyTree,
+ plContext);
+
+ if (chainFailed) {
+
+ /* cert chain failed to validate */
+
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(validPolicyTree);
+
+ /* if last anchor, we fail; else, we try next anchor */
+ if (i == (numAnchors - 1)) { /* last anchor */
+ PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
+ }
+
+ } else {
+
+ /* XXX Remove this assertion after 2014-12-31.
+ * See bug 946984. */
+ PORT_Assert(reasonCode == 0);
+
+ /* cert chain successfully validated! */
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (finalPubKey,
+ anchor,
+ validPolicyTree,
+ &valResult,
+ plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pResult = valResult;
+
+ /* no need to try any more anchors in the loop */
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(finalPubKey);
+ PKIX_DECREF(certs);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(validPolicyTree);
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(procParams);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(validateCheckedCritExtOIDsList);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_Validate_BuildUserOIDs
+ * DESCRIPTION:
+ *
+ * This function creates a List of the OIDs that are processed by the user
+ * checkers in the List pointed to by "userCheckers", storing the resulting
+ * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
+ * List will be NULL. Otherwise the output List will be non-NULL, but may be
+ * empty.
+ *
+ * PARAMETERS:
+ * "userCheckers"
+ * The address of the List of userCheckers.
+ * "pUserCritOIDs"
+ * The address at which the List is 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 VALIDATE 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_Validate_BuildUserOIDs(
+ PKIX_List *userCheckers,
+ PKIX_List **pUserCritOIDs,
+ void *plContext)
+{
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *userCritOIDs = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_Boolean supportForwarding = PKIX_FALSE;
+ PKIX_CertChainChecker *userChecker = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
+ PKIX_NULLCHECK_ONE(pUserCritOIDs);
+
+ if (userCheckers != NULL) {
+ PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwarding, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwarding == PKIX_FALSE) {
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (userCritOIDs, userCheckerExtOIDs, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ *pUserCritOIDs = userCritOIDs;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(userCritOIDs);
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_ValidateChain_NB(
+ PKIX_ValidateParams *valParams,
+ PKIX_UInt32 *pCertIndex,
+ PKIX_UInt32 *pAnchorIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_List **pCheckers,
+ void **pNBIOContext,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 numAnchors = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 certIndex = 0;
+ PKIX_UInt32 anchorIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_UInt32 reasonCode = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_List *certs = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *validateCheckedCritExtOIDsList = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_PublicKey *finalPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_Error *chainFailed = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
+ PKIX_NULLCHECK_FOUR
+ (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
+ PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ /* extract various parameters from valParams */
+ PKIX_CHECK(pkix_ExtractParameters
+ (valParams,
+ &certs,
+ &numCerts,
+ &procParams,
+ &anchors,
+ &numAnchors,
+ plContext),
+ PKIX_EXTRACTPARAMETERSFAILED);
+
+ /*
+ * Create a List of the OIDs that will be processed by the user
+ * checkers. User checkers are not responsible for removing OIDs from
+ * the List of unresolved critical extensions, as libpkix checkers are.
+ * So we add those user checkers' OIDs to the removal list to be taken
+ * out by CheckChain.
+ */
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ PKIX_CHECK(pkix_Validate_BuildUserOIDs
+ (userCheckers, &validateCheckedCritExtOIDsList, plContext),
+ PKIX_VALIDATEBUILDUSEROIDSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+
+ /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
+ if (nbioContext != NULL) {
+ /* Resuming */
+ certIndex = *pCertIndex;
+ anchorIndex = *pAnchorIndex;
+ checkerIndex = *pCheckerIndex;
+ revChecking = *pRevChecking;
+ checkers = *pCheckers;
+ *pCheckers = NULL;
+ }
+
+ /* try to validate the chain with each anchor */
+ for (i = anchorIndex; i < numAnchors; i++) {
+
+ /* get trust anchor */
+ PKIX_CHECK(PKIX_List_GetItem
+ (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* initialize checkers using information from trust anchor */
+ if (nbioContext == NULL) {
+ PKIX_CHECK(pkix_InitializeCheckers
+ (anchor,
+ procParams,
+ numCerts,
+ &checkers,
+ plContext),
+ PKIX_INITIALIZECHECKERSFAILED);
+ }
+
+ /*
+ * Validate the chain using this trust anchor and these
+ * checkers.
+ */
+ chainFailed = pkix_CheckChain
+ (certs,
+ numCerts,
+ anchor,
+ checkers,
+ revChecker,
+ validateCheckedCritExtOIDsList,
+ procParams,
+ &certIndex,
+ &checkerIndex,
+ &revChecking,
+ &reasonCode,
+ &nbioContext,
+ &finalPubKey,
+ &validPolicyTree,
+ pVerifyTree,
+ plContext);
+
+ if (nbioContext != NULL) {
+ *pCertIndex = certIndex;
+ *pAnchorIndex = anchorIndex;
+ *pCheckerIndex = checkerIndex;
+ *pRevChecking = revChecking;
+ PKIX_INCREF(checkers);
+ *pCheckers = checkers;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ if (chainFailed) {
+
+ /* cert chain failed to validate */
+
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(validPolicyTree);
+
+ /* if last anchor, we fail; else, we try next anchor */
+ if (i == (numAnchors - 1)) { /* last anchor */
+ PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
+ }
+
+ } else {
+
+ /* XXX Remove this assertion after 2014-12-31.
+ * See bug 946984. */
+ PORT_Assert(reasonCode == 0);
+
+ /* cert chain successfully validated! */
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (finalPubKey,
+ anchor,
+ validPolicyTree,
+ &valResult,
+ plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pResult = valResult;
+
+ /* no need to try any more anchors in the loop */
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(finalPubKey);
+ PKIX_DECREF(certs);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(validPolicyTree);
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(procParams);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(validateCheckedCritExtOIDsList);
+
+ PKIX_RETURN(VALIDATE);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.h b/security/nss/lib/libpkix/pkix/top/pkix_validate.h
new file mode 100644
index 0000000000..7692e3babf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.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_validate.h
+ *
+ * Header file for validateChain function
+ *
+ */
+
+#ifndef _PKIX_VALIDATE_H
+#define _PKIX_VALIDATE_H
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_CheckChain(
+ PKIX_List *certs,
+ PKIX_UInt32 numCerts,
+ PKIX_TrustAnchor *anchor,
+ PKIX_List *checkers,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_List *buildCheckedExtOIDs,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 *pCertCheckedIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_UInt32 *pReasonCode,
+ void **pNBIOContext,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATE_H */
diff --git a/security/nss/lib/libpkix/pkix/top/top.gyp b/security/nss/lib/libpkix/pkix/top/top.gyp
new file mode 100644
index 0000000000..fb1b08ecbd
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/top.gyp
@@ -0,0 +1,25 @@
+# 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': 'pkixtop',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_build.c',
+ 'pkix_lifecycle.c',
+ 'pkix_validate.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/util/Makefile b/security/nss/lib/libpkix/pkix/util/Makefile
new file mode 100644
index 0000000000..2b5492506c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/Makefile
@@ -0,0 +1,44 @@
+#! 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/util/exports.gyp b/security/nss/lib/libpkix/pkix/util/exports.gyp
new file mode 100644
index 0000000000..8318c6c347
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/exports.gyp
@@ -0,0 +1,28 @@
+# 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_util_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_error.h',
+ 'pkix_list.h',
+ 'pkix_logger.h',
+ 'pkix_tools.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/util/manifest.mn b/security/nss/lib/libpkix/pkix/util/manifest.mn
new file mode 100644
index 0000000000..e7d9f973c7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/manifest.mn
@@ -0,0 +1,25 @@
+#
+# 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_tools.h \
+ pkix_error.h \
+ pkix_logger.h \
+ pkix_list.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_tools.c \
+ pkix_error.c \
+ pkix_logger.c \
+ pkix_list.c \
+ pkix_errpaths.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixutil
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.c b/security/nss/lib/libpkix/pkix/util/pkix_error.c
new file mode 100644
index 0000000000..9d730ca161
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c
@@ -0,0 +1,565 @@
+/* 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_error.c
+ *
+ * Error Object Functions
+ *
+ */
+
+#include "pkix_error.h"
+
+#undef PKIX_ERRORENTRY
+
+#define PKIX_ERRORENTRY(name,desc,nsserr) #desc
+
+#if defined PKIX_ERROR_DESCRIPTION
+
+const char * const PKIX_ErrorText[] =
+{
+#include "pkix_errorstrings.h"
+};
+
+#else
+
+#include "prprf.h"
+
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+extern const PKIX_Int32 PKIX_PLErrorIndex[];
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Error_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Error *firstError = NULL;
+ PKIX_Error *secondError = NULL;
+ PKIX_Error *firstCause = NULL;
+ PKIX_Error *secondCause = NULL;
+ PKIX_PL_Object *firstInfo = NULL;
+ PKIX_PL_Object *secondInfo = NULL;
+ PKIX_ERRORCLASS firstClass, secondClass;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean boolResult, unequalFlag;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ unequalFlag = PKIX_FALSE;
+
+ /* First just compare pointer values to save time */
+ if (firstObject == secondObject) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ } else {
+ /* Result will only be set to true if all tests pass */
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTANERROROBJECT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_ERRORGETTINGSECONDOBJECTTYPE);
+
+ /* If types differ, then return false. Result is already set */
+ if (secondType != PKIX_ERROR_TYPE) goto cleanup;
+
+ /* It is safe to cast to PKIX_Error */
+ firstError = (PKIX_Error *) firstObject;
+ secondError = (PKIX_Error *) secondObject;
+
+ /* Compare error codes */
+ firstClass = firstError->errClass;
+ secondClass = secondError->errClass;
+
+ /* If codes differ, return false. Result is already set */
+ if (firstClass != secondClass) goto cleanup;
+
+ /* Compare causes */
+ firstCause = firstError->cause;
+ secondCause = secondError->cause;
+
+ /* Ensure that either both or none of the causes are NULL */
+ if (((firstCause != NULL) && (secondCause == NULL))||
+ ((firstCause == NULL) && (secondCause != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstCause != NULL) && (secondCause != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstCause,
+ (PKIX_PL_Object*)secondCause,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the cause errors are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+ /* Compare info fields */
+ firstInfo = firstError->info;
+ secondInfo = secondError->info;
+
+ if (firstInfo != secondInfo) goto cleanup;
+
+ /* Ensure that either both or none of the infos are NULL */
+ if (((firstInfo != NULL) && (secondInfo == NULL))||
+ ((firstInfo == NULL) && (secondInfo != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstInfo != NULL) && (secondInfo != NULL)) {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstInfo,
+ (PKIX_PL_Object*)secondInfo,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the infos are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+
+ /* Compare descs */
+ if (firstError->errCode != secondError->errCode) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ if (firstError->plErr != secondError->plErr) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the unequalFlag was set, return false */
+ if (unequalFlag) goto cleanup;
+
+ /* Errors are equal in all fields at this point */
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ PKIX_DECREF(error->cause);
+
+ PKIX_DECREF(error->info);
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+
+/* XXX This is not thread safe */
+static PKIX_UInt32 pkix_error_cause_depth = 1;
+
+/*
+ * FUNCTION: pkix_Error_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+ PKIX_Error *cause = NULL;
+ PKIX_PL_String *desc = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *causeString = NULL;
+ PKIX_PL_String *optCauseString = NULL;
+ PKIX_PL_String *errorNameString = NULL;
+ char *format = NULL;
+ PKIX_ERRORCLASS errClass;
+
+ PKIX_ENTER(ERROR, "pkix_Error_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ /* Get this error's errClass, description and the string of its cause */
+ errClass = error->errClass;
+
+ /* Get the description string */
+ PKIX_Error_GetDescription(error, &desc, plContext);
+
+ /* Get the cause */
+ cause = error->cause;
+
+ /* Get the causes's description string */
+ if (cause != NULL) {
+ pkix_error_cause_depth++;
+
+ /* Get the cause string */
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)cause, &causeString, plContext),
+ PKIX_ERRORGETTINGCAUSESTRING);
+
+ format = "\n*** Cause (%d): %s";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the optional Cause String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&optCauseString,
+ plContext,
+ formatString,
+ pkix_error_cause_depth,
+ causeString),
+ PKIX_SPRINTFFAILED);
+
+ PKIX_DECREF(formatString);
+
+ pkix_error_cause_depth--;
+ }
+
+ /* Create the Format String */
+ if (optCauseString != NULL) {
+ format = "*** %s Error- %s%s";
+ } else {
+ format = "*** %s Error- %s";
+ }
+
+ /* Ensure that error errClass is known, otherwise default to Object */
+ if (errClass >= PKIX_NUMERRORCLASSES) {
+ errClass = 0;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[errClass],
+ 0,
+ &errorNameString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the output String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ formatString,
+ errorNameString,
+ desc,
+ optCauseString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(desc);
+ PKIX_DECREF(causeString);
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(optCauseString);
+ PKIX_DECREF(errorNameString);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "pkix_Error_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pResult);
+
+ /* XXX Unimplemented */
+ /* XXX Need to make hashcodes equal when two errors are equal */
+ *pResult = (PKIX_UInt32)((char *)object - (char *)NULL);
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Initializers------------------------------------------------- */
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error errClass. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ *
+ * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types.
+ * (More precisely, as a list of invocations of ERRMACRO(type).) The
+ * macro is expanded in pkixt.h to define error numbers, and here to
+ * provide corresponding strings. For example, since the fifth ERRMACRO
+ * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and
+ * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX".
+ */
+#undef ERRMACRO
+#define ERRMACRO(type) #type
+
+const char *
+PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] =
+{
+ PKIX_ERRORCLASSES
+};
+
+/*
+ * FUNCTION: pkix_Error_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_ERROR_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_Error_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf");
+
+ entry.description = "Error";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Error);
+ entry.destructor = pkix_Error_Destroy;
+ entry.equalsFunction = pkix_Error_Equals;
+ entry.hashcodeFunction = pkix_Error_Hashcode;
+ entry.toStringFunction = pkix_Error_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_ERROR_TYPE] = entry;
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_Create(
+ PKIX_ERRORCLASS errClass,
+ PKIX_Error *cause,
+ PKIX_PL_Object *info,
+ PKIX_ERRORCODE errCode,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *tempCause = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "PKIX_Error_Create");
+
+ PKIX_NULLCHECK_ONE(pError);
+
+ /*
+ * when called here, if PKIX_PL_Object_Alloc returns an error,
+ * it must be a PKIX_ALLOC_ERROR
+ */
+ pkixErrorResult = PKIX_PL_Object_Alloc
+ (PKIX_ERROR_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_Error))),
+ (PKIX_PL_Object **)&error,
+ plContext);
+
+ if (pkixErrorResult) return (pkixErrorResult);
+
+ error->errClass = errClass;
+
+ /* Ensure we don't have a loop. Follow causes until NULL */
+ for (tempCause = cause;
+ tempCause != NULL;
+ tempCause = tempCause->cause) {
+ /* If we detect a loop, throw a new error */
+ if (tempCause == error) {
+ PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED);
+ }
+ }
+
+ PKIX_INCREF(cause);
+ error->cause = cause;
+
+ PKIX_INCREF(info);
+ error->info = info;
+
+ error->errCode = errCode;
+
+ error->plErr = PKIX_PLErrorIndex[error->errCode];
+
+ *pError = error;
+ error = NULL;
+
+cleanup:
+ /* PKIX-XXX Fix for leak during error creation */
+ PKIX_DECREF(error);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorClass(
+ PKIX_Error *error,
+ PKIX_ERRORCLASS *pClass,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass");
+ PKIX_NULLCHECK_TWO(error, pClass);
+
+ *pClass = error->errClass;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorCode(
+ PKIX_Error *error,
+ PKIX_ERRORCODE *pCode,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode");
+ PKIX_NULLCHECK_TWO(error, pCode);
+
+ *pCode = error->errCode;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetCause(
+ PKIX_Error *error,
+ PKIX_Error **pCause,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetCause");
+ PKIX_NULLCHECK_TWO(error, pCause);
+
+ if (error->cause != PKIX_ALLOC_ERROR()){
+ PKIX_INCREF(error->cause);
+ }
+
+ *pCause = error->cause;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetSupplementaryInfo(
+ PKIX_Error *error,
+ PKIX_PL_Object **pInfo,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo");
+ PKIX_NULLCHECK_TWO(error, pInfo);
+
+ PKIX_INCREF(error->info);
+
+ *pInfo = error->info;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetDescription(
+ PKIX_Error *error,
+ PKIX_PL_String **pDesc,
+ void *plContext)
+{
+ PKIX_PL_String *descString = NULL;
+#ifndef PKIX_ERROR_DESCRIPTION
+ char errorStr[32];
+#endif
+
+ PKIX_ENTER(ERROR, "PKIX_Error_GetDescription");
+ PKIX_NULLCHECK_TWO(error, pDesc);
+
+#ifndef PKIX_ERROR_DESCRIPTION
+ PR_snprintf(errorStr, 32, "Error code: %d", error->errCode);
+#endif
+
+ PKIX_PL_String_Create(PKIX_ESCASCII,
+#if defined PKIX_ERROR_DESCRIPTION
+ (void *)PKIX_ErrorText[error->errCode],
+#else
+ errorStr,
+#endif
+ 0,
+ &descString,
+ plContext);
+
+ *pDesc = descString;
+
+ PKIX_RETURN(ERROR);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.h b/security/nss/lib/libpkix/pkix/util/pkix_error.h
new file mode 100644
index 0000000000..ca4171ab17
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.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_error.h
+ *
+ * Error Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_ERROR_H
+#define _PKIX_ERROR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ErrorStruct {
+ PKIX_ERRORCODE errCode;
+ PKIX_ERRORCLASS errClass; /* was formerly "code" */
+ PKIX_Int32 plErr;
+ PKIX_Error *cause;
+ PKIX_PL_Object *info;
+};
+
+/* see source file for function documentation */
+
+extern PKIX_Error * pkix_Error_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_ERROR_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
new file mode 100644
index 0000000000..a33ccf7ddb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
@@ -0,0 +1,103 @@
+/* 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_errpaths.c
+ *
+ * Error Handling Helper Functions
+ *
+ */
+
+#define PKIX_STDVARS_POINTER
+#include "pkix_error.h"
+
+const PKIX_StdVars zeroStdVars;
+
+PKIX_Error*
+PKIX_DoThrow(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode, PKIX_ERRORCLASS overrideClass,
+ void *plContext)
+{
+ if (!pkixErrorReceived && !pkixErrorResult && pkixErrorList) {
+ pkixTempResult = PKIX_List_GetItem(pkixErrorList, 0,
+ (PKIX_PL_Object**)&pkixReturnResult,
+ plContext);
+ } else {
+ pkixTempResult = (PKIX_Error*)pkix_Throw(errClass, myFuncName, errCode,
+ overrideClass, pkixErrorResult,
+ &pkixReturnResult, plContext);
+ }
+ if (pkixReturnResult) {
+ if (pkixErrorResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ pkixTempResult = pkixReturnResult;
+ } else if (pkixErrorResult) {
+ if (pkixTempResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixTempResult);
+ }
+ pkixTempResult = pkixErrorResult;
+ }
+ if (pkixErrorList) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext);
+ pkixErrorList = NULL;
+ }
+ return pkixTempResult;
+}
+
+PKIX_Error *
+PKIX_DoReturn(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger, void *plContext)
+{
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (pkixErrorReceived || pkixErrorResult || pkixErrorList)
+ return PKIX_DoThrow(stdVars, errClass, pkixErrorCode, pkixErrorClass,
+ plContext);
+ /* PKIX_DEBUG_EXIT(type); */
+ if (doLogger)
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE);
+ return NULL;
+}
+
+/* PKIX_DoAddError - creates the list of received error if it does not exist
+ * yet and adds newly received error into the list. */
+void
+PKIX_DoAddError(PKIX_StdVars *stdVars, PKIX_Error *error, void * plContext)
+{
+ PKIX_List *localList = NULL;
+ PKIX_Error *localError = NULL;
+ PKIX_Boolean listCreated = PKIX_FALSE;
+
+ if (!pkixErrorList) {
+ localError = PKIX_List_Create(&localList, plContext);
+ if (localError)
+ goto cleanup;
+ listCreated = PKIX_TRUE;
+ } else {
+ localList = pkixErrorList;
+ }
+
+ localError = PKIX_List_AppendItem(localList, (PKIX_PL_Object*)error,
+ plContext);
+ PORT_Assert (localError == NULL);
+ if (localError != NULL) {
+ if (listCreated) {
+ /* ignore the error code of DecRef function */
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localList, plContext);
+ localList = NULL;
+ }
+ } else {
+ pkixErrorList = localList;
+ }
+
+cleanup:
+
+ if (localError && localError != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localError, plContext);
+ }
+
+ if (error && error != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
+ }
+}
+
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.c b/security/nss/lib/libpkix/pkix/util/pkix_list.c
new file mode 100644
index 0000000000..d02b66e6d6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.c
@@ -0,0 +1,1701 @@
+/* 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_list.c
+ *
+ * List Object Functions
+ *
+ */
+
+#include "pkix_list.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_List_Create_Internal
+ * DESCRIPTION:
+ *
+ * Creates a new List, using the Boolean value of "isHeader" to determine
+ * whether the new List should be a header, and stores it at "pList". The
+ * List is initially empty and holds no items. To initially add items to
+ * the List, use PKIX_List_AppendItem.
+ *
+ * PARAMETERS:
+ * "isHeader"
+ * Boolean value indicating whether new List should be a header.
+ * "pList"
+ * 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_Create_Internal(
+ PKIX_Boolean isHeader,
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Create_Internal");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LIST_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_List))),
+ (PKIX_PL_Object **)&list, plContext),
+ PKIX_ERRORCREATINGLISTITEM);
+
+ list->item = NULL;
+ list->next = NULL;
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = isHeader;
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *nextItem = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a list */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ /* We have a valid list. DecRef its item and recurse on next */
+ PKIX_DECREF(list->item);
+ while ((nextItem = list->next) != NULL) {
+ list->next = nextItem->next;
+ nextItem->next = NULL;
+ PKIX_DECREF(nextItem);
+ }
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the List pointed
+ * to by "list" and stores its address in the object pointed to by "pString".
+ *
+ * PARAMETERS
+ * "list"
+ * Address of List whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a List 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_List_ToString_Helper(
+ PKIX_List *list,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *itemString = NULL;
+ PKIX_PL_String *nextString = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString_Helper");
+ PKIX_NULLCHECK_TWO(list, pString);
+
+ /* special case when list is the header */
+ if (list->isHeader){
+
+ PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext),
+ PKIX_LISTISEMPTYFAILED);
+
+ if (empty){
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "EMPTY",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_ERRORCREATINGITEMSTRING);
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ } else {
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &itemString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+ }
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString, plContext, format, itemString),
+ PKIX_SPRINTFFAILED);
+ } else {
+ /* Get a string for this list's item */
+ if (list->item == NULL) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "(null)",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)list->item,
+ &itemString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ }
+ if (list->next == NULL) {
+ /* Just return the itemstring */
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ }
+
+ /* Recursive call to get string for this list's next pointer */
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &nextString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s, %s",
+ 0,
+ &format,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ format,
+ itemString,
+ nextString),
+ PKIX_SPRINTFFAILED);
+ }
+
+cleanup:
+
+ PKIX_DECREF(itemString);
+ PKIX_DECREF(nextString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_String *listString = NULL;
+ PKIX_PL_String *format = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(%s)", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(listString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_List *firstList = NULL;
+ PKIX_List *secondList = NULL;
+ PKIX_UInt32 firstLength = 0;
+ PKIX_UInt32 secondLength = 0;
+ PKIX_PL_Object *firstItem = NULL;
+ PKIX_PL_Object *secondItem = NULL;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a List */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLIST);
+
+ /*
+ * Since we know first is a List, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a List, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LIST_TYPE) goto cleanup;
+
+ firstList = (PKIX_List *)first;
+ secondList = (PKIX_List *)second;
+
+ if ((!firstList->isHeader) && (!secondList->isHeader)){
+ PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS);
+ }
+
+ firstLength = firstList->length;
+ secondLength = secondList->length;
+
+ cmpResult = PKIX_FALSE;
+ if (firstLength == secondLength){
+ for (i = 0, cmpResult = PKIX_TRUE;
+ ((i < firstLength) && cmpResult);
+ i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (firstList, i, &firstItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &secondItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if ((!firstItem && secondItem) ||
+ (firstItem && !secondItem)){
+ cmpResult = PKIX_FALSE;
+ } else if (!firstItem && !secondItem){
+ continue;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (firstItem,
+ secondItem,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+ }
+ }
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *element = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ for (i = 0; i < length; i++){
+ PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (!element){
+ tempHash = 100;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ (element, &tempHash, plContext),
+ PKIX_LISTHASHCODEFAILED);
+ }
+
+ hash = 31 * hash + tempHash;
+
+ PKIX_DECREF(element);
+ }
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_DECREF(element);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *listDuplicate = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (list->immutable){
+ PKIX_CHECK(pkix_duplicateImmutable
+ (object, pNewObject, plContext),
+ PKIX_DUPLICATEIMMUTABLEFAILED);
+ } else {
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (list->isHeader, &listDuplicate, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ listDuplicate->length = list->length;
+
+ PKIX_INCREF(list->item);
+ listDuplicate->item = list->item;
+
+ if (list->next == NULL){
+ listDuplicate->next = NULL;
+ } else {
+ /* Recursively Duplicate list */
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *)list->next,
+ (PKIX_PL_Object **)&listDuplicate->next,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+ }
+
+ *pNewObject = (PKIX_PL_Object *)listDuplicate;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(listDuplicate);
+ }
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_GetElement
+ * DESCRIPTION:
+ *
+ * Copies the "list"'s element at "index" into "element". The input List must
+ * be the header of the List (as opposed to being an element of the List). The
+ * index counts from zero and must be less than the List's length. This
+ * function does NOT increment the reference count of the List element since
+ * the returned element's reference will not be stored by the calling
+ * function.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List (must be header) to get element from. Must be non-NULL.
+ * "index"
+ * Index of list to get element from. Must be less than List's length.
+ * "pElement"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_GetElement(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_List **pElement,
+ void *plContext)
+{
+ PKIX_List *iterator = NULL;
+ PKIX_UInt32 length;
+ PKIX_UInt32 position = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_GetElement");
+ PKIX_NULLCHECK_TWO(list, pElement);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (index >= length) {
+ PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS);
+ }
+
+ for (iterator = list; position++ <= index; iterator = iterator->next)
+ ;
+
+ (*pElement) = iterator;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LIST_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_List_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LIST, "pkix_List_RegisterSelf");
+
+ entry.description = "List";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_List);
+ entry.destructor = pkix_List_Destroy;
+ entry.equalsFunction = pkix_List_Equals;
+ entry.hashcodeFunction = pkix_List_Hashcode;
+ entry.toStringFunction = pkix_List_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_List_Duplicate;
+
+ systemClasses[PKIX_LIST_TYPE] = entry;
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Contains
+ * DESCRIPTION:
+ *
+ * Checks a List pointed to by "list", to determine whether it includes
+ * an entry that is equal to the Object pointed to by "object", and stores
+ * the result in "pFound".
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object 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 Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Contains");
+ PKIX_NULLCHECK_THREE(list, object, pFound);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ break;
+ }
+ }
+
+ *pFound = match;
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Remove
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object pointed to by "object". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object to be checked for and deleted, if found; 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 Validate 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_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Remove");
+ PKIX_NULLCHECK_TWO(list, object);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (list, index, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ break;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_RemoveItems
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object in the "deleteList". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * Object in "list" is checked for object in "deleteList" and deleted if
+ * found; may be empty; must be non-NULL
+ * "deleteList"
+ * List of objects to be searched ; may be empty; 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 Validate 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_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_RemoveItems");
+ PKIX_NULLCHECK_TWO(list, deleteList);
+
+ PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (deleteList, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(pkix_List_Remove
+ (list, current, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_MergeLists
+ * DESCRIPTION:
+ *
+ * Creates a new list consisting of the items from "firstList", followed by
+ * the items on "secondList", returns the new list at "pMergedList". If
+ * both input lists are NULL or empty, the result is an empty list. If an error
+ * occurs, the result is NULL.
+ *
+ * PARAMETERS:
+ * "firstList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "secondList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "pMergedList"
+ * Address where returned object is stored.
+ * "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 List 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_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_MergeLists");
+ PKIX_NULLCHECK_ONE(pMergedList);
+
+ *pMergedList = NULL;
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (firstList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ numItems = 0;
+ if (secondList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (secondList,
+ &numItems,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list, item, plContext), PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ *pMergedList = list;
+ list = NULL;
+
+cleanup:
+ PKIX_DECREF(list);
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendList
+ * DESCRIPTION:
+ *
+ * Append items on "fromList" to the "toList". Item reference count on
+ * "toList" is not incremented, but items appended from "fromList" are
+ * incremented.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of list to be appended to. Must be non-NULL.
+ * "fromList"
+ * Address of list to be appended from. May be NULL or empty.
+ * "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 List 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_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_AppendList");
+ PKIX_NULLCHECK_ONE(toList);
+
+ /* if fromList is NULL or is an empty list, no action */
+
+ if (fromList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numItems == 0) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+cleanup:
+
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendUnique
+ * DESCRIPTION:
+ *
+ * Adds each Object in the List pointed to by "fromList" to the List pointed
+ * to by "toList", if it is not already a member of that List. In other words,
+ * "toList" becomes the union of the two sets.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of a List of Objects to be augmented by "fromList". Must be
+ * non-NULL, but may be empty.
+ * "fromList"
+ * Address of a List of Objects to be added, if not already present, to
+ * "toList". Must be non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 listLen = 0;
+ PKIX_UInt32 listIx = 0;
+ PKIX_PL_Object *object = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_List_AppendUnique");
+ PKIX_NULLCHECK_TWO(fromList, toList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (listIx = 0; listIx < listLen; listIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, listIx, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (toList, object, &isContained, plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isContained == PKIX_FALSE) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (toList, object, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(object);
+ }
+
+cleanup:
+
+ PKIX_DECREF(object);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_QuickSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is quick sort (n*logn).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_List *lessList = NULL;
+ PKIX_List *greaterList = NULL;
+ PKIX_List *sortedLessList = NULL;
+ PKIX_List *sortedGreaterList = NULL;
+ PKIX_PL_Object *object = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_List_QuickSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&lessList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&greaterList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, 0, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Pick the first item on the list as the one to be compared.
+ * Separate rest of the itmes into two lists: less-than or greater-
+ * than lists. Sort those two lists recursively. Insert sorted
+ * less-than list before the picked item and append the greater-
+ * than list after the picked item.
+ */
+ for (i = 1; i < size; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+
+ if (cmpResult >= 0) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (lessList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (greaterList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(cmpObj);
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&sortedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (lessList, comparator, &sortedLessList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedLessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, lessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext),
+ PKIX_LISTAPPENDFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (greaterList, comparator, &sortedGreaterList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedGreaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, greaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ *pSortedList = sortedList;
+
+cleanup:
+
+ PKIX_DECREF(cmpObj);
+ PKIX_DECREF(object);
+ PKIX_DECREF(sortedGreaterList);
+ PKIX_DECREF(sortedLessList);
+ PKIX_DECREF(greaterList);
+ PKIX_DECREF(lessList);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_BubbleSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is bubble sort (n*n).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_PL_Object *leastObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i, j;
+
+ PKIX_ENTER(BUILD, "pkix_List_BubbleSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ if (fromList->immutable) {
+ PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST);
+ }
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *) fromList,
+ (PKIX_PL_Object **) &sortedList,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ /*
+ * Move from the first of the item on the list, For each iteration,
+ * compare and swap the least value to the head of the comparisoning
+ * sub-list.
+ */
+ for (i = 0; i < size - 1; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, i, &leastObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ for (j = i + 1; j < size; j++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, j, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(comparator
+ (leastObj, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+ if (cmpResult > 0) {
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, j, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ leastObj = cmpObj;
+ cmpObj = NULL;
+ } else {
+ PKIX_DECREF(cmpObj);
+ }
+ }
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, i, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ }
+
+ }
+
+ *pSortedList = sortedList;
+ sortedList = NULL;
+cleanup:
+
+ PKIX_DECREF(sortedList);
+ PKIX_DECREF(leastObj);
+ PKIX_DECREF(cmpObj);
+
+ PKIX_RETURN(LIST);
+}
+
+/* --Public-List-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_List_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_Create(
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_Create");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetImmutable(
+ PKIX_List *list,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_SetImmutable");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ list->immutable = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsImmutable(
+ PKIX_List *list,
+ PKIX_Boolean *pImmutable,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_IsImmutable");
+ PKIX_NULLCHECK_TWO(list, pImmutable);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pImmutable = list->immutable;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetLength(
+ PKIX_List *list,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_GetLength");
+ PKIX_NULLCHECK_TWO(list, pLength);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pLength = list->length;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsEmpty(
+ PKIX_List *list,
+ PKIX_Boolean *pEmpty,
+ void *plContext)
+{
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(LIST, "PKIX_List_IsEmpty");
+ PKIX_NULLCHECK_TWO(list, pEmpty);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (length == 0){
+ *pEmpty = PKIX_TRUE;
+ } else {
+ *pEmpty = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_AppendItem(
+ PKIX_List *list,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *lastElement = NULL;
+ PKIX_List *newElement = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "PKIX_List_AppendItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* find last element of list and create new element there */
+
+ lastElement = list;
+ for (i = 0; i < length; i++){
+ lastElement = lastElement->next;
+ }
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (PKIX_FALSE, &newElement, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ PKIX_INCREF(item);
+ newElement->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ lastElement->next = newElement;
+ newElement = NULL;
+ list->length += 1;
+
+cleanup:
+
+ PKIX_DECREF(newElement);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_InsertItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *newElem = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_InsertItem");
+ PKIX_NULLCHECK_ONE(list);
+
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ /* Create a new list object */
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ if (list->length) {
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ /* Copy the old element's contents into the new element */
+ newElem->item = element->item;
+ /* Add new item to the list */
+ PKIX_INCREF(item);
+ element->item = item;
+ /* Set the new element's next pointer to the old element's next */
+ newElem->next = element->next;
+ /* Set the old element's next pointer to the new element */
+ element->next = newElem;
+ newElem = NULL;
+ } else {
+ PKIX_INCREF(item);
+ newElem->item = item;
+ newElem->next = NULL;
+ list->next = newElem;
+ newElem = NULL;
+ }
+ list->length++;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+ PKIX_DECREF(newElem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object **pItem,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_GetItem");
+ PKIX_NULLCHECK_TWO(list, pItem);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ PKIX_INCREF(element->item);
+ *pItem = element->item;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element;
+
+ PKIX_ENTER(LIST, "PKIX_List_SetItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ /* Set New Contents */
+ PKIX_INCREF(item);
+ element->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_DeleteItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *prevElement = NULL;
+ PKIX_List *nextElement = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_DeleteItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ nextElement = element->next;
+
+ if (nextElement != NULL) {
+ /* If the next element exists, splice it out. */
+
+ /* Don't need to change ref counts for targets of next */
+ element->item = nextElement->item;
+ nextElement->item = NULL;
+
+ /* Don't need to change ref counts for targets of next */
+ element->next = nextElement->next;
+ nextElement->next = NULL;
+
+ PKIX_DECREF(nextElement);
+
+ } else { /* The element is at the tail of the list */
+ if (index != 0) {
+ PKIX_CHECK(pkix_List_GetElement
+ (list, index-1, &prevElement, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ } else if (index == 0){ /* prevElement must be header */
+ prevElement = list;
+ }
+ prevElement->next = NULL;
+
+ /* Delete the element */
+ PKIX_DECREF(element);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ list->length = list->length - 1;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_ReverseList(
+ PKIX_List *list,
+ PKIX_List **pReversedList,
+ void *plContext)
+{
+ PKIX_List *reversedList = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_PL_Object *duplicateItem = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_ReverseList");
+ PKIX_NULLCHECK_TWO(list, pReversedList);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* Create a new list object */
+ PKIX_CHECK(PKIX_List_Create(&reversedList, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ /*
+ * Starting with the last item and traversing backwards (from
+ * the original list), append each item to the reversed list
+ */
+
+ for (i = 1; i <= length; i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, (length - i), &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ (item, &duplicateItem, plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (reversedList, duplicateItem, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+ }
+
+ *pReversedList = reversedList;
+
+cleanup:
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(reversedList);
+ }
+
+ PKIX_RETURN(LIST);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.h b/security/nss/lib/libpkix/pkix/util/pkix_list.h
new file mode 100644
index 0000000000..13e104f21a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.h
@@ -0,0 +1,95 @@
+/* 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_list.h
+ *
+ * List Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LIST_H
+#define _PKIX_LIST_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PKIX_Error *
+(*PKIX_List_SortComparatorCallback)(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext);
+
+struct PKIX_ListStruct {
+ PKIX_PL_Object *item;
+ PKIX_List *next;
+ PKIX_Boolean immutable;
+ PKIX_UInt32 length;
+ PKIX_Boolean isHeader;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_List_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *target,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LIST_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.c b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
new file mode 100644
index 0000000000..10f537a319
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
@@ -0,0 +1,1088 @@
+/* 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_logger.c
+ *
+ * Logger Object Functions
+ *
+ */
+
+#include "pkix_logger.h"
+#ifndef PKIX_ERROR_DESCRIPTION
+#include "prprf.h"
+#endif
+
+/* Global variable to keep PKIX_Logger List */
+PKIX_List *pkixLoggers = NULL;
+
+/*
+ * Once the Logger has been set, for any logging related operations, we have
+ * to go through the List to find a match, and if found, issue the
+ * corresponding callback. The overhead to check for DEBUG and TRACE in each
+ * PKIX function entering and exiting is very expensive (400X), and redundant
+ * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
+ * pkixLoggers is separated into two lists based on its Loggers' trace level.
+ *
+ * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
+ * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
+ * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
+ * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
+ * pkixLoggersDebugTrace.
+ *
+ * Currently we provide five logging levels and the default setting are by:
+ *
+ * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
+ * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
+ * WARNING is not invoked as default
+ * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
+ * compilation -DPKIX_<component>DEBUG flag to turn on
+ * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
+ * level. TRACE provides duplicate information of DEBUG, but needs no
+ * recompilation and cannot choose component. To allow application
+ * to use DEBUG level, TRACE is put as last.
+ *
+ */
+PKIX_List *pkixLoggersErrors = NULL;
+PKIX_List *pkixLoggersDebugTrace = NULL;
+
+/* To ensure atomic update on pkixLoggers lists */
+PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Logger_CheckErrors
+ * DESCRIPTION:
+ *
+ * This function goes through each PKIX_Logger at "pkixLoggersList" and
+ * checks if "maxLevel" and "logComponent" satisfies what is specified in the
+ * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
+ * passes a PKIX_PL_String that is the concatenation of "message" and
+ * "message2" to the application for processing.
+ * Since this call is inserted into a handful of PKIX macros, no macros are
+ * applied in this function, to avoid infinite recursion.
+ * If an error occurs, this call is aborted.
+ *
+ * PARAMETERS:
+ * "pkixLoggersList"
+ * A list of PKIX_Loggers to be examined for invoking callback. Must be
+ * non-NULL.
+ * "message"
+ * Address of "message" to be logged. Must be non-NULL.
+ * "message2"
+ * Address of "message2" to be concatenated and logged. May be NULL.
+ * "logComponent"
+ * A PKIX_UInt32 that indicates the component the message is from.
+ * "maxLevel"
+ * A PKIX_UInt32 that represents the level of severity of the message.
+ * "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 Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *messageString = NULL;
+ PKIX_PL_String *message2String = NULL;
+ PKIX_PL_String *msgString = NULL;
+ PKIX_Error *error = NULL;
+ PKIX_Boolean needLogging = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ /*
+ * We cannot use any the PKIX_ macros here, since this function is
+ * called from some of these macros. It can create infinite recursion.
+ */
+
+ if ((pkixLoggersList == NULL) || (message == NULL)) {
+ return(NULL);
+ }
+
+ /*
+ * Disable all subsequent loggings to avoid recursion. The result is
+ * if other thread is calling this function at the same time, there
+ * won't be any logging because the pkixLoggersErrors and
+ * pkixLoggersDebugTrace are set to null.
+ * It would be nice if we provide control per thread (e.g. make
+ * plContext threadable) then we can avoid the recursion by setting
+ * flag at plContext. Then other thread's logging won't be affected.
+ *
+ * Also we need to use a reentrant Lock. Although we avoid recursion
+ * for TRACE. When there is an ERROR occurs in subsequent call, this
+ * function will be called.
+ */
+
+ error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* Convert message and message2 to String */
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message, 0, &messageString, plContext);
+ if (error) { goto cleanup; }
+
+ if (message2) {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message2, 0, &message2String, plContext);
+ if (error) { goto cleanup; }
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ } else {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ }
+
+ error = PKIX_PL_Sprintf
+ (&msgString,
+ plContext,
+ formatString,
+ messageString,
+ message2String);
+ if (error) { goto cleanup; }
+
+ /* Go through the Logger list */
+
+ error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
+ if (error) { goto cleanup; }
+
+ for (i = 0; i < length; i++) {
+
+ error = PKIX_List_GetItem
+ (pkixLoggersList,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext);
+ if (error) { goto cleanup; }
+
+ /* Intended logging level less or equal than the max */
+ needLogging = (currentLevel <= logger->maxLevel);
+
+ if (needLogging && (logger->callback)) {
+
+ /*
+ * We separate Logger into two lists based on log level
+ * but log level is not modified. We need to check here to
+ * avoid logging the higher log level (lower value) twice.
+ */
+ if (pkixLoggersList == pkixLoggersErrors) {
+ needLogging = needLogging &&
+ (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
+ } else if (pkixLoggersList == pkixLoggersDebugTrace) {
+ needLogging = needLogging &&
+ (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
+ }
+
+ if (needLogging) {
+ if (logComponent == logger->logComponent) {
+ needLogging = PKIX_TRUE;
+ } else {
+ needLogging = PKIX_FALSE;
+ }
+ }
+
+ if (needLogging) {
+ error = logger->callback
+ (logger,
+ msgString,
+ currentLevel,
+ logComponent,
+ plContext);
+ if (error) { goto cleanup; }
+ }
+ }
+
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ logger = NULL;
+ if (error) { goto cleanup; }
+
+ }
+
+cleanup:
+
+ if (formatString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)formatString, plContext);
+ }
+
+ if (messageString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)messageString, plContext);
+ }
+
+ if (message2String) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)message2String, plContext);
+ }
+
+ if (msgString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)msgString, plContext);
+ }
+
+ if (logger) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ }
+
+ if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ }
+
+ if (pkixLoggersDebugTrace == NULL &&
+ savedPkixLoggersDebugTrace != NULL) {
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ }
+
+ error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ return(NULL);
+}
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ char error[32];
+ char *errorString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
+#if defined PKIX_ERROR_DESCRIPTION
+ errorString = PKIX_ErrorText[errorCode];
+#else
+ PR_snprintf(error, 32, "Error code: %d", errorCode);
+ errorString = error;
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+ pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
+ message2, logComponent,
+ currentLevel, plContext);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ /* We have a valid logger. DecRef its item and recurse on next */
+
+ logger->callback = NULL;
+ PKIX_DECREF(logger->context);
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *contextString = NULL;
+ PKIX_PL_String *componentString = NULL;
+ PKIX_PL_String *loggerString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ asciiFormat =
+ "[\n"
+ "\tLogger: \n"
+ "\tContext: %s\n"
+ "\tMaximum Level: %d\n"
+ "\tComponent Name: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(logger->context, &contextString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
+ 0,
+ &componentString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&loggerString,
+ plContext,
+ formatString,
+ contextString,
+ logger->maxLevel,
+ componentString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = loggerString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(contextString);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_Logger *firstLogger = NULL;
+ PKIX_Logger *secondLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a Logger */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLOGGER);
+
+ /*
+ * Since we know first is a Logger, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a Logger, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
+
+ firstLogger = (PKIX_Logger *)first;
+ secondLogger = (PKIX_Logger *)second;
+
+ cmpResult = PKIX_FALSE;
+
+ if (firstLogger->callback != secondLogger->callback) {
+ goto cleanup;
+ }
+
+ if (firstLogger->logComponent != secondLogger->logComponent) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstLogger->context,
+ secondLogger->context,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ if (firstLogger->maxLevel != secondLogger->maxLevel) {
+ goto cleanup;
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ PKIX_HASHCODE(logger->context, &tempHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) +
+ logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * FUNCTION: pkix_Logger_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *) object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ dupLogger->callback = logger->callback;
+ dupLogger->maxLevel = logger->maxLevel;
+
+ PKIX_DUPLICATE
+ (logger->context,
+ &dupLogger->context,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ dupLogger->logComponent = logger->logComponent;
+
+ *pNewObject = (PKIX_PL_Object *) dupLogger;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(dupLogger);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LOGGER_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_Logger_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
+
+ entry.description = "Logger";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Logger);
+ entry.destructor = pkix_Logger_Destroy;
+ entry.equalsFunction = pkix_Logger_Equals;
+ entry.hashcodeFunction = pkix_Logger_Hashcode;
+ entry.toStringFunction = pkix_Logger_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_Logger_Duplicate;
+
+ systemClasses[PKIX_LOGGER_TYPE] = entry;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/* --Public-Logger-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_Create(
+ PKIX_Logger_LogCallback callback,
+ PKIX_PL_Object *loggerContext,
+ PKIX_Logger **pLogger,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
+ PKIX_NULLCHECK_ONE(pLogger);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&logger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ logger->callback = callback;
+ logger->maxLevel = 0;
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+ PKIX_INCREF(loggerContext);
+ logger->context = loggerContext;
+
+ *pLogger = logger;
+ logger = NULL;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLogCallback(
+ PKIX_Logger *logger,
+ PKIX_Logger_LogCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
+ PKIX_NULLCHECK_TWO(logger, pCallback);
+
+ *pCallback = logger->callback;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggerContext(
+ PKIX_Logger *logger,
+ PKIX_PL_Object **pLoggerContext,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
+ PKIX_NULLCHECK_TWO(logger, pLoggerContext);
+
+ PKIX_INCREF(logger->context);
+ *pLoggerContext = logger->context;
+
+cleanup:
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 *pLevel,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_NULLCHECK_TWO(logger, pLevel);
+
+ *pLevel = logger->maxLevel;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 level,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_NULLCHECK_ONE(logger);
+
+ if (level > PKIX_LOGGER_LEVEL_MAX) {
+ PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
+ } else {
+ logger->maxLevel = level;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS *pComponent,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
+ PKIX_NULLCHECK_TWO(logger, pComponent);
+
+ *pComponent = logger->logComponent;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS component,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
+ PKIX_NULLCHECK_ONE(logger);
+
+ logger->logComponent = component;
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
+ * documented as not thread-safe. However they are thread-safe now. We need
+ * the lock when accessing the logger lists.
+ */
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_GetLoggers(
+ PKIX_List **pLoggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_UInt32 i, length;
+ PKIX_Boolean locked = PKIX_FALSE;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
+ PKIX_NULLCHECK_ONE(pLoggers);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /*
+ * Temporarily disable DEBUG/TRACE Logging to avoid possible
+ * deadlock:
+ * When the Logger List is being accessed, e.g. by PKIX_ENTER or
+ * PKIX_DECREF, pkix_Logger_Check may check whether logging
+ * is requested, creating a deadlock situation.
+ */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ if (pkixLoggers == NULL) {
+ length = 0;
+ } else {
+ PKIX_CHECK(PKIX_List_GetLength
+ (pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /* Create a list and copy the pkixLoggers item to the list */
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+ }
+
+ /* Set the list to be immutable */
+ PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pLoggers = list;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ /* Restore logging capability */
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ pkixLoggersErrors = savedPkixLoggersErrors;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_SetLoggers(
+ PKIX_List *loggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /* Disable tracing, etc. to avoid recursion and deadlock */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* discard any prior loggers */
+ PKIX_DECREF(pkixLoggers);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (loggers != NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (loggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /* Make two lists */
+
+ /* Put in pkixLoggersErrors in any case*/
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+
+ }
+
+ pkixLoggers = list;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(list);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+ pkixLoggers = NULL;
+ }
+
+ PKIX_DECREF(logger);
+
+ /* Reenable logging capability with new lists */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_AddLogger(
+ PKIX_Logger *logger,
+ void *plContext)
+{
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Logger *addLogger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
+ PKIX_NULLCHECK_ONE(logger);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (pkixLoggers == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (pkixLoggers,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &addLogger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+
+ /* Put in pkixLoggersErrors */
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(addLogger);
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(dupLogger);
+ PKIX_DECREF(addLogger);
+
+ /* Restore logging capability */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.h b/security/nss/lib/libpkix/pkix/util/pkix_logger.h
new file mode 100644
index 0000000000..9411aed2e2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.h
@@ -0,0 +1,57 @@
+/* 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_logger.h
+ *
+ * Logger Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LOGGER_H
+#define _PKIX_LOGGER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKIX_List *pkixLoggers;
+extern PKIX_List *pkixLoggersErrors;
+extern PKIX_List *pkixLoggersDebugTrace;
+
+struct PKIX_LoggerStruct {
+ PKIX_Logger_LogCallback callback;
+ PKIX_PL_Object *context;
+ PKIX_UInt32 maxLevel;
+ PKIX_ERRORCLASS logComponent;
+};
+
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_Logger_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LOGGER_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
new file mode 100644
index 0000000000..4c01f8da14
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
@@ -0,0 +1,1525 @@
+/* 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_tools.c
+ *
+ * Private Utility Functions
+ *
+ */
+
+#include "pkix_tools.h"
+
+#define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */
+
+/*
+ * This cahce period is only for CertCache. A Cert from a trusted CertStore
+ * should be checked more frequently for update new arrival, etc.
+ */
+#define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10)
+
+extern PKIX_PL_HashTable *cachedCertChainTable;
+extern PKIX_PL_HashTable *cachedCertTable;
+extern PKIX_PL_HashTable *cachedCrlEntryTable;
+
+/* Following variables are used to checked cache hits - can be taken out */
+extern int pkix_ccAddCount;
+extern int pkix_ccLookupCount;
+extern int pkix_ccRemoveCount;
+extern int pkix_cAddCount;
+extern int pkix_cLookupCount;
+extern int pkix_cRemoveCount;
+extern int pkix_ceAddCount;
+extern int pkix_ceLookupCount;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/* Following variables are used for object leak test */
+char *nonNullValue = "Non Empty Value";
+PKIX_Boolean noErrorState = PKIX_TRUE;
+PKIX_Boolean runningLeakTest;
+PKIX_Boolean errorGenerated;
+PKIX_UInt32 stackPosition;
+PKIX_UInt32 *fnStackInvCountArr;
+char **fnStackNameArr;
+PLHashTable *fnInvTable;
+PKIX_UInt32 testStartFnStackPosition;
+char *errorFnStackString;
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/* --Private-Functions-------------------------------------------- */
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/*
+ * FUNCTION: pkix_ErrorGen_Hash
+ * DESCRIPTION:
+ *
+ * Hash function to be used in object leak test hash table.
+ *
+ */
+PLHashNumber PR_CALLBACK
+pkix_ErrorGen_Hash (const void *key)
+{
+ char *str = NULL;
+ PLHashNumber rv = (*(PRUint8*)key) << 5;
+ PRUint32 i, counter = 0;
+ PRUint8 *rvc = (PRUint8 *)&rv;
+
+ while ((str = fnStackNameArr[counter++]) != NULL) {
+ PRUint32 len = strlen(str);
+ for( i = 0; i < len; i++ ) {
+ rvc[ i % sizeof(rv) ] ^= *str;
+ str++;
+ }
+ }
+
+ return rv;
+}
+
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/*
+ * FUNCTION: pkix_IsCertSelfIssued
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" is self-issued and stores the
+ * Boolean result at "pSelfIssued". A Cert is considered self-issued if the
+ * Cert's issuer matches the Cert's subject. If the subject or issuer is
+ * not specified, a PKIX_FALSE is returned.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert used to determine whether Cert is self-issued.
+ * Must be non-NULL.
+ * "pSelfIssued"
+ * Address where Boolean 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 Cert 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_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext)
+{
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+
+ PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
+ PKIX_NULLCHECK_TWO(cert, pSelfIssued);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (subject == NULL || issuer == NULL) {
+ *pSelfIssued = PKIX_FALSE;
+ } else {
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (subject, issuer, pSelfIssued, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+ }
+
+cleanup:
+ PKIX_DECREF(subject);
+ PKIX_DECREF(issuer);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_Throw
+ * DESCRIPTION:
+ *
+ * Creates an Error using the value of "errorCode", the character array
+ * pointed to by "funcName", the character array pointed to by "errorText",
+ * and the Error pointed to by "cause" (if any), and stores it at "pError".
+ *
+ * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
+ * then there is no point creating a new Error object. Rather, we simply
+ * store "cause" at "pError".
+ *
+ * PARAMETERS:
+ * "errorCode"
+ * Value of error code.
+ * "funcName"
+ * Address of EscASCII array representing name of function throwing error.
+ * Must be non-NULL.
+ * "errnum"
+ * PKIX_ERRMSGNUM of error description for new error.
+ * "cause"
+ * Address of Error representing error's cause.
+ * "pError"
+ * 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 an Error 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_Throw(
+ PKIX_ERRORCLASS errorClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Throw");
+ PKIX_NULLCHECK_TWO(funcName, pError);
+
+ *pError = NULL;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_TRUE;
+ if (pkixLog) {
+#ifdef PKIX_ERROR_DESCRIPTION
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
+ funcName, PKIX_ErrorText[errorCode],
+ (cause ? PKIX_ErrorText[cause->errCode] : "null")));
+#else
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n",
+ funcName, errorCode));
+#endif /* PKIX_ERROR_DESCRIPTION */
+ PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
+ if (cause) {
+ if (cause->errClass == PKIX_FATAL_ERROR){
+ PKIX_INCREF(cause);
+ *pError = cause;
+ goto cleanup;
+ }
+ }
+
+ if (overrideClass == PKIX_FATAL_ERROR){
+ errorClass = overrideClass;
+ }
+
+ pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
+ errorCode, &error, plContext);
+
+ if (!pkixTempResult) {
+ /* Setting plErr error code:
+ * get it from PORT_GetError if it is a leaf error and
+ * default error code does not exist(eq 0) */
+ if (!cause && !error->plErr) {
+ error->plErr = PKIX_PL_GetPLErrorCode();
+ }
+ }
+
+ *pError = error;
+
+cleanup:
+
+ PKIX_DEBUG_EXIT(ERROR);
+ pkixErrorClass = 0;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_FALSE;
+
+ if (runningLeakTest && fnStackNameArr) {
+ PR_LOG(pkixLog, 5,
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
+ stackPosition, " ", fnStackNameArr[stackPosition],
+ stackPosition, myFuncName));
+ fnStackNameArr[stackPosition--] = NULL;
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+ return (pkixTempResult);
+}
+
+/*
+ * FUNCTION: pkix_CheckTypes
+ * DESCRIPTION:
+ *
+ * Checks that the types of the Object pointed to by "first" and the Object
+ * pointed to by "second" are both equal to the value of "type". If they
+ * are not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "first"
+ * Address of first Object. Must be non-NULL.
+ * "second"
+ * Address of second Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "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 an Error 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_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ PKIX_UInt32 firstType, secondType;
+
+ PKIX_ENTER(OBJECT, "pkix_CheckTypes");
+ PKIX_NULLCHECK_TWO(first, second);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
+ PKIX_COULDNOTGETFIRSTOBJECTTYPE);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETSECONDOBJECTTYPE);
+
+ if ((firstType != type)||(firstType != secondType)) {
+ PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_CheckType
+ * DESCRIPTION:
+ *
+ * Checks that the type of the Object pointed to by "object" is equal to the
+ * value of "type". If it is not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "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 an Error 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_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ return (pkix_CheckTypes(object, object, type, plContext));
+}
+
+/*
+ * FUNCTION: pkix_hash
+ * DESCRIPTION:
+ *
+ * Computes a hash value for "length" bytes starting at the array of bytes
+ * pointed to by "bytes" and stores the result at "pHash".
+ *
+ * XXX To speed this up, we could probably read 32 bits at a time from
+ * bytes (maybe even 64 bits on some platforms)
+ *
+ * PARAMETERS:
+ * "bytes"
+ * Address of array of bytes to hash. Must be non-NULL.
+ * "length"
+ * Number of bytes to hash.
+ * "pHash"
+ * 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *pHash,
+ void *plContext)
+{
+ PKIX_UInt32 i;
+ PKIX_UInt32 hash;
+
+ PKIX_ENTER(OBJECT, "pkix_hash");
+ if (length != 0) {
+ PKIX_NULLCHECK_ONE(bytes);
+ }
+ PKIX_NULLCHECK_ONE(pHash);
+
+ hash = 0;
+ for (i = 0; i < length; i++) {
+ /* hash = 31 * hash + bytes[i]; */
+ hash = (hash << 5) - hash + bytes[i];
+ }
+
+ *pHash = hash;
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_countArray
+ * DESCRIPTION:
+ *
+ * Counts the number of elements in the null-terminated array of pointers
+ * pointed to by "array" and returns the result.
+ *
+ * PARAMETERS
+ * "array"
+ * Address of null-terminated array of pointers.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the number of elements in the array.
+ */
+PKIX_UInt32
+pkix_countArray(void **array)
+{
+ PKIX_UInt32 count = 0;
+
+ if (array) {
+ while (*array++) {
+ count++;
+ }
+ }
+ return (count);
+}
+
+/*
+ * FUNCTION: pkix_duplicateImmutable
+ * DESCRIPTION:
+ *
+ * Convenience callback function used for duplicating immutable objects.
+ * Since the objects can not be modified, this function simply increments the
+ * reference count on the object, and returns a reference to that object.
+ *
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_INCREF(object);
+
+ *pNewObject = object;
+
+cleanup:
+ PKIX_RETURN(OBJECT);
+}
+
+/* --String-Encoding-Conversion-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_hex2i
+ * DESCRIPTION:
+ *
+ * Converts hexadecimal character "c" to its integer value and returns result.
+ *
+ * PARAMETERS
+ * "c"
+ * Character to convert to a hex value.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
+ */
+PKIX_UInt32
+pkix_hex2i(char c)
+{
+ if ((c >= '0')&&(c <= '9'))
+ return (c-'0');
+ else if ((c >= 'a')&&(c <= 'f'))
+ return (c-'a'+10);
+ else if ((c >= 'A')&&(c <= 'F'))
+ return (c-'A'+10);
+ else
+ return ((PKIX_UInt32)(-1));
+}
+
+/*
+ * FUNCTION: pkix_i2hex
+ * DESCRIPTION:
+ *
+ * Converts integer value "digit" to its ASCII hex value
+ *
+ * PARAMETERS
+ * "digit"
+ * Value of integer to convert to ASCII hex value. Must be 0-15.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The ASCII hexadecimal value of "digit".
+ */
+char
+pkix_i2hex(char digit)
+{
+ if ((digit >= 0)&&(digit <= 9))
+ return (digit+'0');
+ else if ((digit >= 0xa)&&(digit <= 0xf))
+ return (digit - 10 + 'a');
+ else
+ return (-1);
+}
+
+/*
+ * FUNCTION: pkix_isPlaintext
+ * DESCRIPTION:
+ *
+ * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
+ * depending on the value of "debug".
+ *
+ * In EscASCII, [01, 7E] except '&' are plaintext.
+ * In EscASCII_Debug [20, 7E] except '&' are plaintext.
+ *
+ * PARAMETERS:
+ * "c"
+ * Character to check.
+ * "debug"
+ * Value of debug flag.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * True if "c" is plaintext.
+ */
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
+ return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
+}
+
+/* --Cache-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
+ * and "anchors" as the hash keys. If there is no item to match the key,
+ * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
+ * compared to "testDate". If expired, the item is removed and PKIX_FALSE is
+ * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the
+ * BuildResult is stored at "pBuildResult".
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time validity and cache validity.
+ * May be NULL. If testDate is NULL, this cache item will not be out-dated.
+ * "pFound"
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pBuildResult"
+ * Address where BuildResult 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 an Error 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_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_Int32 cmpValidTimeResult = 0;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
+
+ *pFound = PKIX_FALSE;
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Lookup
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+
+ pkix_ccLookupCount++;
+
+ /* retrieve data from hashed value list */
+
+ if (cachedValues != NULL && cachedCertChainError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* check validity time and cache age time */
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &validityDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* if testDate is not set, this cache item is not out-dated */
+ if (testDate) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)validityDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ /* certs' date are all valid and cache item is not old */
+ if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 2,
+ (PKIX_PL_Object **) pBuildResult,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ pkix_ccRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* out-dated item, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(validityDate);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Remove
+ * DESCRIPTION:
+ *
+ * Remove CertChain Hash Table entry based on "targetCert" and "anchors"
+ * as the hash keys. If there is no item to match the key, no action is
+ * taken.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * 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 an Error 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_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
+ PKIX_NULLCHECK_TWO(targetCert, anchors);
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+
+ pkix_ccRemoveCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Add
+ * DESCRIPTION:
+ *
+ * Add a BuildResult to the CertChain Hash Table for a "buildResult" with
+ * "targetCert" and "anchors" as the hash keys.
+ * "validityDate" is the most restricted notAfter date of all Certs in
+ * this CertChain and is verified when this BuildChain is retrieved.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "validityDate"
+ * Address of PKIX_PL_Date contains the most restriced notAfter time of
+ * all "certs". Must be non-NULL.
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "buildResult"
+ * Address of BuildResult to be cached. 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 an Error 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_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (CACHE_ITEM_PERIOD_SECONDS,
+ &cacheValidUntilDate,
+ plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Add
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_ccAddCount++;
+
+ if (cachedCertChainError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Lookup
+ * DESCRIPTION:
+ *
+ * Look up Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and returns values Certs in "pCerts".
+ * If there isn't an item to match the key, a PKIX_FALSE is returned at
+ * "pFound". The item's cache time is verified with "testDate". If out-dated,
+ * this item is removed and PKIX_FALSE is returned at "pFound".
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time cache validity.
+ * Must be non-NULL. If testDate is NULL, this cache item won't be out
+ * dated.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCerts"
+ * Address PKIX_List where the CertChain will be stored. Must be no-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 an Error 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_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCertList = NULL;
+ PKIX_List *selCertList = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_Date *invalidAfterDate = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_Error *selectorError = NULL;
+ PKIX_CertSelector_MatchCallback selectorMatch = NULL;
+ PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
+ PKIX_NULLCHECK_TWO(store, certSelParams);
+ PKIX_NULLCHECK_TWO(pFound, pCerts);
+
+ *pFound = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Lookup
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+ pkix_cLookupCount++;
+
+ if (cachedValues != NULL && cachedCertError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpCacheTimeResult <= 0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &cachedCertList,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Certs put on cache satifies only for Subject,
+ * user selector and ComCertSelParams to filter.
+ */
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (certSel, &selectorMatch, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * If any of the Cert on the list is out-dated, invalidate
+ * this cache item.
+ */
+ PKIX_CHECK(PKIX_List_GetLength
+ (cachedCertList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++){
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedCertList,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ (cert, &invalidAfterDate, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)invalidAfterDate,
+ (PKIX_PL_Object *)testDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpValidTimeResult < 0) {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* one cert is out-dated, remove item from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ goto cleanup;
+ }
+
+ selectorError = selectorMatch(certSel, cert, plContext);
+ if (!selectorError){
+ /* put on the return list */
+ PKIX_CHECK(PKIX_List_AppendItem
+ (selCertList,
+ (PKIX_PL_Object *)cert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ *pFound = PKIX_TRUE;
+ } else {
+ PKIX_DECREF(selectorError);
+ }
+
+ PKIX_DECREF(cert);
+ PKIX_DECREF(invalidAfterDate);
+
+ }
+
+ if (*pFound) {
+ PKIX_INCREF(selCertList);
+ *pCerts = selCertList;
+ }
+
+ } else {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+ /* cache item is out-dated, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(certSel);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(cachedCertList);
+ PKIX_DECREF(selCertList);
+ PKIX_DECREF(invalidAfterDate);
+ PKIX_DECREF(cachedCertError);
+ PKIX_DECREF(selectorError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Add
+ * DESCRIPTION:
+ *
+ * Add Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and have "certs" as the key value.
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "certs"
+ * Address PKIX_List of Certs will be stored. Must be no-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 an Error 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_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCerts = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
+ PKIX_UInt32 numCerts = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
+ PKIX_NULLCHECK_THREE(store, certSelParams, certs);
+
+ PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (numCerts == 0) {
+ /* Don't want to add an empty list. */
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ if (trustCallback) {
+ cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
+ }
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (cachePeriod, &cacheValidUntilDate, plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DUPLICATE(certs, &cachedCerts, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cachedCerts,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Add
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_cAddCount++;
+
+ if (cachedCertError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedCerts);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cachedCertError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and returns values
+ * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCrls"
+ * Address PKIX_List where the CRLEntry will be stored. Must be no-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 an Error 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_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedCrlEntryList = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_TWO(pFound, pCrls);
+
+ *pFound = PKIX_FALSE;
+
+ /* Find CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Lookup
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedCrlEntryList,
+ plContext);
+ pkix_ceLookupCount++;
+
+ /*
+ * We don't need check Date to invalidate this cache item,
+ * the item is uniquely defined and won't be reverted. Let
+ * the FIFO for cleaning up.
+ */
+
+ if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
+
+ PKIX_INCREF(cachedCrlEntryList);
+ *pCrls = cachedCrlEntryList;
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ *pFound = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryList);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Add
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
+ * the hash value. If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "crls"
+ * Address PKIX_List where the CRLEntry is stored. Must be no-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 an Error 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_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_ONE(crls);
+
+ /* Add CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Add
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) crls,
+ plContext);
+ pkix_ceAddCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+
+/* TEST_START_FN and testStartFnStackPosition define at what state
+ * of the stack the object leak testing should begin. The condition
+ * in pkix_CheckForGeneratedError works the following way: do leak
+ * testing if at position testStartFnStackPosition in stack array
+ * (fnStackNameArr) we have called function TEST_START_FN.
+ * Note, that stack array get filled only when executing libpkix
+ * functions.
+ * */
+#define TEST_START_FN "PKIX_BuildChain"
+
+PKIX_Error*
+pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errSetFlag,
+ void * plContext)
+{
+ PKIX_Error *genErr = NULL;
+ PKIX_UInt32 pos = 0;
+ PKIX_UInt32 strLen = 0;
+
+ if (fnName) {
+ if (fnStackNameArr[testStartFnStackPosition] == NULL ||
+ strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN)
+ ) {
+ /* return with out error if not with in boundary */
+ return NULL;
+ }
+ if (!strcmp(fnName, TEST_START_FN)) {
+ *errSetFlag = PKIX_TRUE;
+ noErrorState = PKIX_FALSE;
+ errorGenerated = PKIX_FALSE;
+ }
+ }
+
+ if (noErrorState || errorGenerated) return NULL;
+
+ if (fnName && (
+ !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
+ !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
+ !strcmp(fnName, "pkix_UnlockObject") ||
+ !strcmp(fnName, "pkix_Throw") ||
+ !strcmp(fnName, "pkix_trace_dump_cert") ||
+ !strcmp(fnName, "PKIX_PL_Free"))) {
+ /* do not generate error for this functions */
+ noErrorState = PKIX_TRUE;
+ *errSetFlag = PKIX_TRUE;
+ return NULL;
+ }
+
+ if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
+ return NULL;
+ }
+
+ PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
+ errorGenerated = PKIX_TRUE;
+ noErrorState = PKIX_TRUE;
+ genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
+ errClass, plContext);
+ while(fnStackNameArr[pos]) {
+ strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1;
+ }
+ strLen += 1; /* end of line. */
+ pos = 0;
+ errorFnStackString = PORT_ZAlloc(strLen);
+ while(fnStackNameArr[pos]) {
+ strcat(errorFnStackString, "/");
+ strcat(errorFnStackString, fnStackNameArr[pos++]);
+ }
+ noErrorState = PKIX_FALSE;
+
+ return genErr;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
new file mode 100644
index 0000000000..5a8ef2741e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
@@ -0,0 +1,1588 @@
+/* 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_tools.h
+ *
+ * Header for Utility Functions and Macros
+ *
+ */
+
+#ifndef _PKIX_TOOLS_H
+#define _PKIX_TOOLS_H
+
+#include "pkix.h"
+#include <stddef.h>
+#include <stdio.h>
+#include "secport.h"
+#include "prlong.h"
+
+/* private PKIX system headers */
+#include "pkix_basicconstraintschecker.h"
+#include "pkix_buildresult.h"
+#include "pkix_certchainchecker.h"
+#include "pkix_certselector.h"
+#include "pkix_comcertselparams.h"
+#include "pkix_comcrlselparams.h"
+#include "pkix_crlselector.h"
+#include "pkix_error.h"
+#include "pkix_expirationchecker.h"
+#include "pkix_list.h"
+#include "pkix_logger.h"
+#include "pkix_namechainingchecker.h"
+#include "pkix_nameconstraintschecker.h"
+#include "pkix_policychecker.h"
+#include "pkix_policynode.h"
+#include "pkix_procparams.h"
+#include "pkix_resourcelimits.h"
+#include "pkix_revocationmethod.h"
+#include "pkix_revocationchecker.h"
+#include "pkix_crlchecker.h"
+#include "pkix_ocspchecker.h"
+#include "pkix_signaturechecker.h"
+#include "pkix_store.h"
+#include "pkix_targetcertchecker.h"
+#include "pkix_validate.h"
+#include "pkix_valresult.h"
+#include "pkix_verifynode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkixStdVarsStr {
+ const char *aMyFuncName;
+ PKIX_Error *aPkixErrorResult;
+ PKIX_Error *aPkixTempResult;
+ PKIX_Error *aPkixReturnResult;
+ PKIX_ERRORCODE aPkixErrorCode;
+ PKIX_Boolean aPkixErrorReceived;
+ PKIX_Boolean aPkixTempErrorReceived;
+ PKIX_ERRORCLASS aPkixErrorClass;
+ PKIX_UInt32 aPkixType;
+ PKIX_PL_Object *aLockedObject;
+ PKIX_List *aPkixErrorList;
+} PKIX_StdVars;
+
+#ifdef PKIX_STDVARS_POINTER
+#define myFuncName stdVars->aMyFuncName
+#define pkixErrorResult stdVars->aPkixErrorResult
+#define pkixTempResult stdVars->aPkixTempResult
+#define pkixReturnResult stdVars->aPkixReturnResult
+#define pkixErrorCode stdVars->aPkixErrorCode
+#define pkixErrorReceived stdVars->aPkixErrorReceived
+#define pkixTempErrorReceived stdVars->aPkixTempErrorReceived
+#define pkixErrorClass stdVars->aPkixErrorClass
+#define pkixType stdVars->aPkixType
+#define lockedObject stdVars->aLockedObject
+#define pkixErrorList stdVars->aPkixErrorList
+#define stdVarsPtr stdVars
+#else
+#define myFuncName stdVars.aMyFuncName
+#define pkixErrorResult stdVars.aPkixErrorResult
+#define pkixTempResult stdVars.aPkixTempResult
+#define pkixReturnResult stdVars.aPkixReturnResult
+#define pkixErrorCode stdVars.aPkixErrorCode
+#define pkixErrorReceived stdVars.aPkixErrorReceived
+#define pkixTempErrorReceived stdVars.aPkixTempErrorReceived
+#define pkixErrorClass stdVars.aPkixErrorClass
+#define pkixType stdVars.aPkixType
+#define lockedObject stdVars.aLockedObject
+#define pkixErrorList stdVars.aPkixErrorList
+#define stdVarsPtr &stdVars
+#endif
+
+extern PKIX_Error * PKIX_DoReturn(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger,
+ void * plContext);
+
+extern PKIX_Error * PKIX_DoThrow(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode,
+ PKIX_ERRORCLASS overrideClass,
+ void * plContext);
+
+extern void PKIX_DoAddError(PKIX_StdVars * stdVars,
+ PKIX_Error * error,
+ void * plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errorStateSet,
+ void * plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+extern const PKIX_StdVars zeroStdVars;
+
+extern PRLogModuleInfo *pkixLog;
+
+/*
+ * UTILITY MACROS
+ * Documentation for these common utility macros can be found in the
+ * Implementation Guidelines document (Section 4.3)
+ *
+ * In general, macros with multiple statements (or a single "if" statement)
+ * use the "do {<body>} while (0)" technique in order to convert the multiple
+ * statements into one statement, thus avoiding the dangling else problem.
+ * For macros which ALWAYS exit with a "return" or "goto", there is no
+ * need to use this technique (and it yields compiler warnings of "statement
+ * not reached"), so we just use "{<body>}" to group the statements together.
+ */
+
+#if !defined (PKIX_OBJECT_LEAK_TEST)
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ myFuncName = cMyFuncName
+
+
+#else /* PKIX_OBJECT_LEAK_TEST */
+
+extern char **fnStackNameArr;
+extern PKIX_UInt32 *fnStackInvCountArr;
+extern PKIX_UInt32 stackPosition;
+extern PKIX_Boolean noErrorState;
+extern PKIX_Boolean errorGenerated;
+extern PKIX_Boolean runningLeakTest;
+extern PLHashTable *fnInvTable;
+extern PKIX_UInt32 testStartFnStackPosition;
+extern char *errorFnStackString;
+
+extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key);
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ PKIX_Boolean errorSetFlag = PKIX_FALSE; \
+ myFuncName = cMyFuncName; \
+ if (runningLeakTest) { \
+ if (fnStackNameArr) { \
+ fnStackInvCountArr[stackPosition] += 1; \
+ stackPosition += 1; \
+ fnStackInvCountArr[stackPosition] = 0; \
+ fnStackNameArr[stackPosition] = (char*)myFuncName; \
+ fnStackNameArr[stackPosition + 1] = NULL; \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ } \
+ do { \
+ pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \
+ funcName, &errorSetFlag, \
+ plContext); \
+ if (pkixErrorResult) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) { \
+ noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return pkixErrorResult; \
+ } \
+ } while (0); \
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+#ifdef DEBUG
+#define _PKIX_DEBUG_TRACE(cond, prefix, level) \
+ do { \
+ if (cond) { \
+ pkix_Logger_Check(pkixLoggersDebugTrace, myFuncName, \
+ prefix, pkixType, level, plContext); \
+ } \
+ } while (0)
+#else
+#define _PKIX_DEBUG_TRACE(cond, prefix, level)
+#endif
+
+#define _PKIX_LOG_ERROR(code, level) \
+ { \
+ if (pkixLoggersErrors) { \
+ pkix_Logger_CheckWithCode(pkixLoggersErrors, code, \
+ NULL, pkixType, level, plContext); \
+ } \
+ }
+
+#define PKIX_ENTER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type); \
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, ">>>", PKIX_LOGGER_LEVEL_TRACE);
+
+#define PKIX_ENTER_NO_LOGGER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type);
+
+#define PKIX_DEBUG_ENTER(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Entering %s).\n", myFuncName)
+
+#define PKIX_DEBUG_EXIT(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Exiting %s).\n", myFuncName)
+
+#define PKIX_OBJECT_UNLOCK(obj) \
+ do { \
+ if (obj && lockedObject == (PKIX_PL_Object *)(obj)){ \
+ pkixTempResult = \
+ PKIX_PL_Object_Unlock \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ lockedObject = NULL; \
+ } else { \
+ PORT_Assert(lockedObject == NULL); \
+ } \
+ } while (0)
+
+#define PKIX_DECREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_DecRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_THROW(type, descNum) \
+ return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \
+ pkixErrorClass, plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+#define PKIX_RETURN(type) \
+ if (runningLeakTest && fnStackNameArr) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#else
+#define PKIX_RETURN(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+#if defined(DEBUG) && !defined(DEBUG_nb95248)
+#define PKIX_RETURN_NO_LOGGER(type) \
+ { \
+ PKIX_OBJECT_UNLOCK(lockedObject); \
+ if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \
+ PKIX_THROW(type, pkixErrorCode); \
+ PKIX_DEBUG_EXIT(type); \
+ return NULL; \
+ }
+#else
+#define PKIX_RETURN_NO_LOGGER(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_FALSE, plContext);
+#endif
+
+/* disable to disable ;-) */
+/* #define WANT_TRACE_CHECK_FAILURES */
+
+#ifdef WANT_TRACE_CHECK_FAILURES
+#define TRACE_CHECK_FAILURE(what, errorstring) \
+ if (pkixLog) { \
+ PR_LOG(pkixLog, PR_LOG_DEBUG, \
+ ("====> [%s] failed: %s\n", #what, errorstring)); \
+ }
+#else
+#define TRACE_CHECK_FAILURE(what, errorstring)
+#endif
+
+#define PKIX_CHECK(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/* like PKIX_CHECK but without goto cleanup */
+#define PKIX_CHECK_NO_GOTO(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ } \
+ } while (0)
+
+#define PKIX_CHECK_ONLY_FATAL(func, descNum) \
+ do { \
+ pkixTempErrorReceived = PKIX_FALSE; \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixTempErrorReceived = PKIX_TRUE; \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ if (pkixErrorClass == PKIX_FATAL_ERROR) { \
+ goto cleanup; \
+ } \
+ PKIX_DECREF(pkixErrorResult); \
+ } \
+ } while (0)
+
+#define PKIX_LOG_ERROR(descNum) \
+ _PKIX_LOG_ERROR(descNum, PKIX_LOGGER_LEVEL_ERROR)
+
+#define PKIX_ERROR(descNum) \
+ { \
+ PKIX_LOG_ERROR(descNum) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_ALLOC_ERROR() \
+ { \
+ PKIX_LOG_ERROR(PKIX_ALLOCERROR) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorResult = PKIX_ALLOC_ERROR(); \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_FATAL(descNum) \
+ { \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto cleanup; \
+ }
+
+#define PKIX_CHECK_FATAL(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto fatal; \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_ONE(a) \
+ do { \
+ if ((a) == NULL){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_TWO(a, b) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_THREE(a, b, c) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || ((c) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_FOUR(a, b, c, d) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || \
+ ((c) == NULL) || ((d) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_OBJECT_LOCK(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = \
+ PKIX_PL_Object_Lock((PKIX_PL_Object*)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ pkixErrorCode = PKIX_OBJECTLOCKFAILED; \
+ goto cleanup; \
+ } \
+ lockedObject = (PKIX_PL_Object *)(obj); \
+ } \
+ } while (0)
+
+#define PKIX_ERROR_CREATE(type, descNum, error) \
+ { \
+ pkixTempResult = (PKIX_Error*)pkix_Throw \
+ (PKIX_ ## type ## _ERROR, myFuncName, \
+ descNum, PKIX_ ## type ## _ERROR, pkixErrorResult, \
+ &error, plContext); \
+ if (pkixTempResult) { \
+ error = pkixTempResult; \
+ pkixTempResult = NULL; \
+ } \
+ }
+
+
+#define PKIX_ERROR_RECEIVED \
+ (pkixErrorReceived || pkixErrorResult || pkixTempErrorReceived || \
+ pkixErrorList)
+
+#define PKIX_INCREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_IncRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ goto cleanup; \
+ } \
+ } \
+ } while (0)
+
+#define PKIX_FREE(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = PKIX_PL_Free((obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_EXACTLY_ONE_NULL(a, b) (((a) && !(b)) || ((b) && !(a)))
+
+/* DIGIT MACROS */
+
+#define PKIX_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
+
+#define PKIX_ISXDIGIT(c) \
+ (PKIX_ISDIGIT(c) || ( (((c)|0x20) >= 'a') && (((c)|0x20) <= 'f') ))
+
+#define PKIX_TOSTRING(a, b, c, d) \
+ do { \
+ int descNum; \
+ if ((a) != NULL) { \
+ pkixErrorResult = \
+ PKIX_PL_Object_ToString((PKIX_PL_Object *)(a), (b), (c)); \
+ descNum = (d); \
+ } else { \
+ pkixErrorResult = \
+ PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, (b), (c)); \
+ descNum = PKIX_STRINGCREATEFAILED; \
+ } \
+ PKIX_CHECK(pkixErrorResult, descNum); \
+ } while (0)
+
+#define PKIX_EQUALS(a, b, c, d, e) \
+ do { \
+ if ((a) != NULL && (b) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Equals\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object*)(b), \
+ (c), \
+ (d)), \
+ (e)); \
+ } else if ((a) == NULL && (b) == NULL) { \
+ *(c) = PKIX_TRUE; \
+ } else { \
+ *(c) = PKIX_FALSE; \
+ } \
+ } while (0)
+
+#define PKIX_HASHCODE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Hashcode\
+ ((PKIX_PL_Object *)(a), (b), (c)), (d)); \
+ } else { \
+ *(b) = 0; \
+ } \
+ } while (0)
+
+#define PKIX_DUPLICATE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Duplicate\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object **)(b), \
+ (c)), \
+ (d)); \
+ } else { \
+ *(b) = (a); \
+ } \
+ } while (0)
+
+/*
+ * DEBUG MACROS
+ *
+ * Each type has an associated debug flag, which can
+ * be set on the compiler line using "-D<debugflag>". For convenience,
+ * "-DPKIX_DEBUGALL" turns on debug for all the components.
+ *
+ * If a type's debug flag is defined, then its two associated macros
+ * are defined: PKIX_type_DEBUG(expr) and PKIX_type_DEBUG_ARG(expr, arg),
+ * which call PKIX_DEBUG(expr) and PKIX_DEBUG_ARG(expr, arg) respectively,
+ * which, in turn, enable standard and consistently formatted output.
+ *
+ * If a type's debug flag is not defined, the two associated macros
+ * are defined as a NO-OP. As such, any PKIX_type_DEBUG or PKIX_type_DEBUG_ARG
+ * macros for an undefined type will be stripped from the code during
+ * pre-processing, thereby reducing code size.
+ */
+
+#ifdef PKIX_DEBUGALL
+#define PKIX_REFCOUNTDEBUG 1
+#define PKIX_MEMDEBUG 1
+#define PKIX_MUTEXDEBUG 1
+#define PKIX_OBJECTDEBUG 1
+#define PKIX_STRINGDEBUG 1
+#define PKIX_OIDDEBUG 1
+#define PKIX_LISTDEBUG 1
+#define PKIX_ERRORDEBUG 1
+#define PKIX_BYTEARRAYDEBUG 1
+#define PKIX_RWLOCKDEBUG 1
+#define PKIX_BIGINTDEBUG 1
+#define PKIX_HASHTABLEDEBUG 1
+#define PKIX_X500NAMEDEBUG 1
+#define PKIX_GENERALNAMEDEBUG 1
+#define PKIX_PUBLICKEYDEBUG 1
+#define PKIX_CERTDEBUG 1
+#define PKIX_HTTPCLIENTDEBUG 1
+#define PKIX_DATEDEBUG 1
+#define PKIX_TRUSTANCHORDEBUG 1
+#define PKIX_PROCESSINGPARAMSDEBUG 1
+#define PKIX_VALIDATEPARAMSDEBUG 1
+#define PKIX_VALIDATERESULTDEBUG 1
+#define PKIX_VALIDATEDEBUG 1
+#define PKIX_CERTCHAINCHECKERDEBUG 1
+#define PKIX_REVOCATIONCHECKERDEBUG 1
+#define PKIX_CERTSELECTORDEBUG 1
+#define PKIX_COMCERTSELPARAMSDEBUG 1
+#define PKIX_TARGETCERTCHECKERSTATEDEBUG 1
+#define PKIX_INITIALIZEPARAMSDEBUG 1
+#define PKIX_CERTBASICCONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_SUBJALTNAMECHECKERSTATEDEBUG 1
+
+#define PKIX_CERTPOLICYQUALIFIERDEBUG 1
+#define PKIX_CERTPOLICYINFODEBUG 1
+#define PKIX_CERTPOLICYNODEDEBUG 1
+#define PKIX_CERTPOLICYCHECKERSTATEDEBUG 1
+#define PKIX_LIFECYCLEDEBUG 1
+#define PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_CRLDEBUG 1
+#define PKIX_CRLENTRYDEBUG 1
+#define PKIX_CRLSELECTORDEBUG 1
+#define PKIX_COMCRLSELPARAMSDEBUG 1
+#define PKIX_CERTSTOREDEBUG 1
+#define PKIX_COLLECTIONCERTSTORECONTEXTDEBUG 1
+#define PKIX_DEFAULTCRLCHECKERSTATEDEBUG 1
+#define PKIX_CERTPOLICYMAPDEBUG 1
+#define PKIX_BUILDDEBUG 1
+#define PKIX_BUILDRESULTDEBUG 1
+#define PKIX_FORWARDBUILDERSTATEDEBUG 1
+#define PKIX_SIGNATURECHECKERSTATEDEBUG 1
+#define PKIX_USERDEFINEDMODULESDEBUG 1
+#define PKIX_CONTEXTDEBUG 1
+#define PKIX_DEFAULTREVOCATIONCHECKERDEBUG 1
+#define PKIX_LDAPREQUESTDEBUG 1
+#define PKIX_LDAPRESPONSEDEBUG 1
+#define PKIX_LDAPCLIENTDEBUG 1
+#define PKIX_LDAPDEFAULTCLIENTDEBUG 1
+#define PKIX_SOCKETDEBUG 1
+#define PKIX_RESOURCELIMITSDEBUG 1
+#define PKIX_LOGGERDEBUG 1
+#define PKIX_MONITORLOCKDEBUG 1
+#define PKIX_INFOACCESSDEBUG 1
+#define PKIX_AIAMGRDEBUG 1
+#define PKIX_OCSPCHECKERDEBUG 1
+#define PKIX_OCSPREQUESTDEBUG 1
+#define PKIX_OCSPRESPONSEDEBUG 1
+#define PKIX_HTTPDEFAULTCLIENTDEBUG 1
+#define PKIX_HTTPCERTSTORECONTEXTDEBUG 1
+#define PKIX_VERIFYNODEDEBUG 1
+#endif
+
+/*
+ * XXX Both PKIX_DEBUG and PKIX_DEBUG_ARG currently use printf.
+ * This needs to be replaced with Loggers.
+ */
+
+#ifdef DEBUG
+#define PKIX_DEBUG(expr) \
+ do { \
+ _PKIX_DEBUG_TRACE(pkixLoggersErrors, expr, PKIX_LOGGER_LEVEL_DEBUG); \
+ (void) fprintf(stderr, "(%s: ", myFuncName); \
+ (void) fprintf(stderr, expr); \
+ } while (0)
+#else
+#define PKIX_DEBUG(expr)
+#endif
+
+/* Logging doesn't support DEBUG with ARG: cannot convert control and arg */
+#define PKIX_DEBUG_ARG(expr, arg) \
+ do { \
+ (void) printf("(%s: ", myFuncName); \
+ (void) printf(expr, arg); \
+ } while (0)
+
+#if PKIX_FATALDEBUG
+#define PKIX_FATAL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FATAL_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REFCOUNTDEBUG
+#define PKIX_REF_COUNT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REF_COUNT_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MEMDEBUG
+#define PKIX_MEM_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MEM_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MUTEXDEBUG
+#define PKIX_MUTEX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MUTEX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OBJECTDEBUG
+#define PKIX_OBJECT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OBJECT_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_ERRORDEBUG
+#define PKIX_ERROR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_ERROR_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_STRINGDEBUG
+#define PKIX_STRING_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_STRING_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OIDDEBUG
+#define PKIX_OID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OID_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LISTDEBUG
+#define PKIX_LIST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIST_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RWLOCKDEBUG
+#define PKIX_RWLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RWLOCK_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BYTEARRAYDEBUG
+#define PKIX_BYTEARRAY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BYTEARRAY_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HASHTABLEDEBUG
+#define PKIX_HASHTABLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HASHTABLE_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_X500NAMEDEBUG
+#define PKIX_X500NAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_X500NAME_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_GENERALNAMEDEBUG
+#define PKIX_GENERALNAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_GENERALNAME_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PUBLICKEYDEBUG
+#define PKIX_PUBLICKEY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PUBLICKEY_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTDEBUG
+#define PKIX_CERT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERT_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDPDEBUG
+#define PKIX_CRLDP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLDP_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCLIENTDEBUG
+#define PKIX_HTTPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCLIENT_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BIGINTDEBUG
+#define PKIX_BIGINT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BIGINT_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_DATEDEBUG
+#define PKIX_DATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_DATE_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TRUSTANCHORDEBUG
+#define PKIX_TRUSTANCHOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TRUSTANCHOR_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PROCESSINGPARAMSDEBUG
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEPARAMSDEBUG
+#define PKIX_VALIDATEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATEPARAMS_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATERESULTDEBUG
+#define PKIX_VALIDATERESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATERESULT_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEDEBUG
+#define PKIX_VALIDATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATE_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDDEBUG
+#define PKIX_BUILD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILD_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTCHAINCHECKERDEBUG
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONMETHODDEBUG
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSELECTORDEBUG
+#define PKIX_CERTSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSELECTOR_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCERTSELPARAMSDEBUG
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TARGETCERTCHECKERSTATEDEBUG
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INITIALIZEPARAMSDEBUG
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTBASICCONSTRAINTSDEBUG
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSDEBUG
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SUBJALTNAMECHECKERSTATEDEBUG
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYQUALIFIERDEBUG
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYINFODEBUG
+#define PKIX_CERTPOLICYINFO_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYINFO_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYNODEDEBUG
+#define PKIX_CERTPOLICYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYNODE_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LIFECYCLEDEBUG
+#define PKIX_LIFECYCLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIFECYCLE_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDEBUG
+#define PKIX_CRL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRL_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLENTRYDEBUG
+#define PKIX_CRLENTRY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLENTRY_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLSELECTORDEBUG
+#define PKIX_CRLSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLSELECTOR_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCRLSELPARAMSDEBUG
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSTOREDEBUG
+#define PKIX_CERTSTORE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSTORE_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COLLECTIONCERTSTORECONTEXTDEBUG
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLCHECKERDEBUG
+#define PKIX_CRLCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLCHECKER_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYMAPDEBUG
+#define PKIX_CERTPOLICYMAP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYMAP_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDRESULTDEBUG
+#define PKIX_BUILDRESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILDRESULT_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SIGNATURECHECKERSTATEDEBUG
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_USERDEFINEDMODULESDEBUG
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CONTEXTDEBUG
+#define PKIX_CONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CONTEXT_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPREQUESTDEBUG
+#define PKIX_LDAPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPREQUEST_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPRESPONSEDEBUG
+#define PKIX_LDAPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPRESPONSE_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPCLIENTDEBUG
+#define PKIX_LDAPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPCLIENT_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPDEFAULTCLIENTDEBUG
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SOCKETDEBUG
+#define PKIX_SOCKET_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SOCKET_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RESOURCELIMITSDEBUG
+#define PKIX_RESOURCELIMITS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RESOURCELIMITS_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LOGGERDEBUG
+#define PKIX_LOGGER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LOGGER_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MONITORLOCKDEBUG
+#define PKIX_MONITORLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MONITORLOCK_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INFOACCESSDEBUG
+#define PKIX_INFOACCESS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INFOACCESS_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_AIAMGRDEBUG
+#define PKIX_AIAMGR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_AIAMGR_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCHECKERDEBUG
+#define PKIX_OCSPCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCHECKER_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCERTIDDEBUG
+#define PKIX_OCSPCERTID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCERTID_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPREQUESTDEBUG
+#define PKIX_OCSPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPREQUEST_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPRESPONSEDEBUG
+#define PKIX_OCSPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPRESPONSE_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPDEFAULTCLIENTDEBUG
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCERTSTORECONTEXTDEBUG
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VERIFYNODEDEBUG
+#define PKIX_VERIFYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VERIFYNODE_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_EKUCHECKER
+#define PKIX_EKUCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_EKUCHECKER_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTVFYPKIXDEBUG
+#define PKIX_CERTVFYPKIX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTVFYPKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg)
+#endif
+
+/*
+ * All object types register themselves with the system using a
+ * pkix_ClassTable_Entry, which consists of a set of functions for that
+ * type and an ASCII string (char *) which is used by the default
+ * ToStringCallback (if necessary). System types register themselves directly
+ * when their respective PKIX_"type"_RegisterSelf functions are called.
+ * User-defined types can be registered using PKIX_PL_Object_RegisterType.
+ * (see comments in pkix_pl_system.h)
+ */
+
+typedef struct pkix_ClassTable_EntryStruct pkix_ClassTable_Entry;
+struct pkix_ClassTable_EntryStruct {
+ char *description;
+ PKIX_UInt32 objCounter;
+ PKIX_UInt32 typeObjectSize;
+ PKIX_PL_DestructorCallback destructor;
+ PKIX_PL_EqualsCallback equalsFunction;
+ PKIX_PL_HashcodeCallback hashcodeFunction;
+ PKIX_PL_ToStringCallback toStringFunction;
+ PKIX_PL_ComparatorCallback comparator;
+ PKIX_PL_DuplicateCallback duplicateFunction;
+};
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error code. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ */
+extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES];
+
+#define MAX_STACK_DEPTH 1000
+
+extern PRLogModuleInfo *pkixLog;
+
+#define PKIX_MAGIC_HEADER PR_UINT64(0xFEEDC0FFEEFACADE)
+#define PKIX_MAGIC_HEADER_DESTROYED PR_UINT64(0xBAADF00DDEADBEEF)
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext);
+
+PKIX_Error *
+pkix_Throw(
+ PKIX_ERRORCLASS errClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorTextCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *hash,
+ void *plContext);
+
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext);
+
+PKIX_UInt32
+pkix_countArray(void **array);
+
+PKIX_UInt32
+pkix_hex2i(char c);
+
+char
+pkix_i2hex(char c);
+
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug);
+
+PKIX_Error *
+pkix_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrlEntryList,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crlEntryList,
+ void *plContext);
+
+#ifdef PR_LOGGING
+void
+pkix_trace_dump_cert(
+ const char *info,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TOOLS_H */
diff --git a/security/nss/lib/libpkix/pkix/util/util.gyp b/security/nss/lib/libpkix/pkix/util/util.gyp
new file mode 100644
index 0000000000..078852f52b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/util.gyp
@@ -0,0 +1,27 @@
+# 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': 'pkixutil',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_error.c',
+ 'pkix_errpaths.c',
+ 'pkix_list.c',
+ 'pkix_logger.c',
+ 'pkix_tools.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file