summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix/results
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix/results')
-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
12 files changed, 3719 insertions, 0 deletions
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