summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix/util
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix/util')
-rw-r--r--security/nss/lib/libpkix/pkix/util/Makefile44
-rw-r--r--security/nss/lib/libpkix/pkix/util/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/util/manifest.mn25
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.c565
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.h36
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_errpaths.c103
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.c1701
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.h95
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.c1088
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.h57
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.c1525
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.h1588
-rw-r--r--security/nss/lib/libpkix/pkix/util/util.gyp27
13 files changed, 6882 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/util/Makefile b/security/nss/lib/libpkix/pkix/util/Makefile
new file mode 100644
index 0000000000..2b5492506c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/Makefile
@@ -0,0 +1,44 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
diff --git a/security/nss/lib/libpkix/pkix/util/exports.gyp b/security/nss/lib/libpkix/pkix/util/exports.gyp
new file mode 100644
index 0000000000..8318c6c347
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/exports.gyp
@@ -0,0 +1,28 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_util_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_error.h',
+ 'pkix_list.h',
+ 'pkix_logger.h',
+ 'pkix_tools.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/util/manifest.mn b/security/nss/lib/libpkix/pkix/util/manifest.mn
new file mode 100644
index 0000000000..e7d9f973c7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/manifest.mn
@@ -0,0 +1,25 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_tools.h \
+ pkix_error.h \
+ pkix_logger.h \
+ pkix_list.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_tools.c \
+ pkix_error.c \
+ pkix_logger.c \
+ pkix_list.c \
+ pkix_errpaths.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixutil
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.c b/security/nss/lib/libpkix/pkix/util/pkix_error.c
new file mode 100644
index 0000000000..9d730ca161
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c
@@ -0,0 +1,565 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_error.c
+ *
+ * Error Object Functions
+ *
+ */
+
+#include "pkix_error.h"
+
+#undef PKIX_ERRORENTRY
+
+#define PKIX_ERRORENTRY(name,desc,nsserr) #desc
+
+#if defined PKIX_ERROR_DESCRIPTION
+
+const char * const PKIX_ErrorText[] =
+{
+#include "pkix_errorstrings.h"
+};
+
+#else
+
+#include "prprf.h"
+
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+extern const PKIX_Int32 PKIX_PLErrorIndex[];
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Error_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Error *firstError = NULL;
+ PKIX_Error *secondError = NULL;
+ PKIX_Error *firstCause = NULL;
+ PKIX_Error *secondCause = NULL;
+ PKIX_PL_Object *firstInfo = NULL;
+ PKIX_PL_Object *secondInfo = NULL;
+ PKIX_ERRORCLASS firstClass, secondClass;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean boolResult, unequalFlag;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ unequalFlag = PKIX_FALSE;
+
+ /* First just compare pointer values to save time */
+ if (firstObject == secondObject) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ } else {
+ /* Result will only be set to true if all tests pass */
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTANERROROBJECT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_ERRORGETTINGSECONDOBJECTTYPE);
+
+ /* If types differ, then return false. Result is already set */
+ if (secondType != PKIX_ERROR_TYPE) goto cleanup;
+
+ /* It is safe to cast to PKIX_Error */
+ firstError = (PKIX_Error *) firstObject;
+ secondError = (PKIX_Error *) secondObject;
+
+ /* Compare error codes */
+ firstClass = firstError->errClass;
+ secondClass = secondError->errClass;
+
+ /* If codes differ, return false. Result is already set */
+ if (firstClass != secondClass) goto cleanup;
+
+ /* Compare causes */
+ firstCause = firstError->cause;
+ secondCause = secondError->cause;
+
+ /* Ensure that either both or none of the causes are NULL */
+ if (((firstCause != NULL) && (secondCause == NULL))||
+ ((firstCause == NULL) && (secondCause != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstCause != NULL) && (secondCause != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstCause,
+ (PKIX_PL_Object*)secondCause,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the cause errors are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+ /* Compare info fields */
+ firstInfo = firstError->info;
+ secondInfo = secondError->info;
+
+ if (firstInfo != secondInfo) goto cleanup;
+
+ /* Ensure that either both or none of the infos are NULL */
+ if (((firstInfo != NULL) && (secondInfo == NULL))||
+ ((firstInfo == NULL) && (secondInfo != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstInfo != NULL) && (secondInfo != NULL)) {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstInfo,
+ (PKIX_PL_Object*)secondInfo,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the infos are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+
+ /* Compare descs */
+ if (firstError->errCode != secondError->errCode) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ if (firstError->plErr != secondError->plErr) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the unequalFlag was set, return false */
+ if (unequalFlag) goto cleanup;
+
+ /* Errors are equal in all fields at this point */
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ PKIX_DECREF(error->cause);
+
+ PKIX_DECREF(error->info);
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+
+/* XXX This is not thread safe */
+static PKIX_UInt32 pkix_error_cause_depth = 1;
+
+/*
+ * FUNCTION: pkix_Error_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+ PKIX_Error *cause = NULL;
+ PKIX_PL_String *desc = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *causeString = NULL;
+ PKIX_PL_String *optCauseString = NULL;
+ PKIX_PL_String *errorNameString = NULL;
+ char *format = NULL;
+ PKIX_ERRORCLASS errClass;
+
+ PKIX_ENTER(ERROR, "pkix_Error_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ /* Get this error's errClass, description and the string of its cause */
+ errClass = error->errClass;
+
+ /* Get the description string */
+ PKIX_Error_GetDescription(error, &desc, plContext);
+
+ /* Get the cause */
+ cause = error->cause;
+
+ /* Get the causes's description string */
+ if (cause != NULL) {
+ pkix_error_cause_depth++;
+
+ /* Get the cause string */
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)cause, &causeString, plContext),
+ PKIX_ERRORGETTINGCAUSESTRING);
+
+ format = "\n*** Cause (%d): %s";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the optional Cause String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&optCauseString,
+ plContext,
+ formatString,
+ pkix_error_cause_depth,
+ causeString),
+ PKIX_SPRINTFFAILED);
+
+ PKIX_DECREF(formatString);
+
+ pkix_error_cause_depth--;
+ }
+
+ /* Create the Format String */
+ if (optCauseString != NULL) {
+ format = "*** %s Error- %s%s";
+ } else {
+ format = "*** %s Error- %s";
+ }
+
+ /* Ensure that error errClass is known, otherwise default to Object */
+ if (errClass >= PKIX_NUMERRORCLASSES) {
+ errClass = 0;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[errClass],
+ 0,
+ &errorNameString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the output String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ formatString,
+ errorNameString,
+ desc,
+ optCauseString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(desc);
+ PKIX_DECREF(causeString);
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(optCauseString);
+ PKIX_DECREF(errorNameString);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "pkix_Error_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pResult);
+
+ /* XXX Unimplemented */
+ /* XXX Need to make hashcodes equal when two errors are equal */
+ *pResult = (PKIX_UInt32)((char *)object - (char *)NULL);
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Initializers------------------------------------------------- */
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error errClass. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ *
+ * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types.
+ * (More precisely, as a list of invocations of ERRMACRO(type).) The
+ * macro is expanded in pkixt.h to define error numbers, and here to
+ * provide corresponding strings. For example, since the fifth ERRMACRO
+ * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and
+ * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX".
+ */
+#undef ERRMACRO
+#define ERRMACRO(type) #type
+
+const char *
+PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] =
+{
+ PKIX_ERRORCLASSES
+};
+
+/*
+ * FUNCTION: pkix_Error_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_ERROR_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_Error_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf");
+
+ entry.description = "Error";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Error);
+ entry.destructor = pkix_Error_Destroy;
+ entry.equalsFunction = pkix_Error_Equals;
+ entry.hashcodeFunction = pkix_Error_Hashcode;
+ entry.toStringFunction = pkix_Error_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_ERROR_TYPE] = entry;
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_Create(
+ PKIX_ERRORCLASS errClass,
+ PKIX_Error *cause,
+ PKIX_PL_Object *info,
+ PKIX_ERRORCODE errCode,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *tempCause = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "PKIX_Error_Create");
+
+ PKIX_NULLCHECK_ONE(pError);
+
+ /*
+ * when called here, if PKIX_PL_Object_Alloc returns an error,
+ * it must be a PKIX_ALLOC_ERROR
+ */
+ pkixErrorResult = PKIX_PL_Object_Alloc
+ (PKIX_ERROR_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_Error))),
+ (PKIX_PL_Object **)&error,
+ plContext);
+
+ if (pkixErrorResult) return (pkixErrorResult);
+
+ error->errClass = errClass;
+
+ /* Ensure we don't have a loop. Follow causes until NULL */
+ for (tempCause = cause;
+ tempCause != NULL;
+ tempCause = tempCause->cause) {
+ /* If we detect a loop, throw a new error */
+ if (tempCause == error) {
+ PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED);
+ }
+ }
+
+ PKIX_INCREF(cause);
+ error->cause = cause;
+
+ PKIX_INCREF(info);
+ error->info = info;
+
+ error->errCode = errCode;
+
+ error->plErr = PKIX_PLErrorIndex[error->errCode];
+
+ *pError = error;
+ error = NULL;
+
+cleanup:
+ /* PKIX-XXX Fix for leak during error creation */
+ PKIX_DECREF(error);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorClass(
+ PKIX_Error *error,
+ PKIX_ERRORCLASS *pClass,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass");
+ PKIX_NULLCHECK_TWO(error, pClass);
+
+ *pClass = error->errClass;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorCode(
+ PKIX_Error *error,
+ PKIX_ERRORCODE *pCode,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode");
+ PKIX_NULLCHECK_TWO(error, pCode);
+
+ *pCode = error->errCode;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetCause(
+ PKIX_Error *error,
+ PKIX_Error **pCause,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetCause");
+ PKIX_NULLCHECK_TWO(error, pCause);
+
+ if (error->cause != PKIX_ALLOC_ERROR()){
+ PKIX_INCREF(error->cause);
+ }
+
+ *pCause = error->cause;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetSupplementaryInfo(
+ PKIX_Error *error,
+ PKIX_PL_Object **pInfo,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo");
+ PKIX_NULLCHECK_TWO(error, pInfo);
+
+ PKIX_INCREF(error->info);
+
+ *pInfo = error->info;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetDescription(
+ PKIX_Error *error,
+ PKIX_PL_String **pDesc,
+ void *plContext)
+{
+ PKIX_PL_String *descString = NULL;
+#ifndef PKIX_ERROR_DESCRIPTION
+ char errorStr[32];
+#endif
+
+ PKIX_ENTER(ERROR, "PKIX_Error_GetDescription");
+ PKIX_NULLCHECK_TWO(error, pDesc);
+
+#ifndef PKIX_ERROR_DESCRIPTION
+ PR_snprintf(errorStr, 32, "Error code: %d", error->errCode);
+#endif
+
+ PKIX_PL_String_Create(PKIX_ESCASCII,
+#if defined PKIX_ERROR_DESCRIPTION
+ (void *)PKIX_ErrorText[error->errCode],
+#else
+ errorStr,
+#endif
+ 0,
+ &descString,
+ plContext);
+
+ *pDesc = descString;
+
+ PKIX_RETURN(ERROR);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.h b/security/nss/lib/libpkix/pkix/util/pkix_error.h
new file mode 100644
index 0000000000..ca4171ab17
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.h
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_error.h
+ *
+ * Error Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_ERROR_H
+#define _PKIX_ERROR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ErrorStruct {
+ PKIX_ERRORCODE errCode;
+ PKIX_ERRORCLASS errClass; /* was formerly "code" */
+ PKIX_Int32 plErr;
+ PKIX_Error *cause;
+ PKIX_PL_Object *info;
+};
+
+/* see source file for function documentation */
+
+extern PKIX_Error * pkix_Error_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_ERROR_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
new file mode 100644
index 0000000000..a33ccf7ddb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
@@ -0,0 +1,103 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_errpaths.c
+ *
+ * Error Handling Helper Functions
+ *
+ */
+
+#define PKIX_STDVARS_POINTER
+#include "pkix_error.h"
+
+const PKIX_StdVars zeroStdVars;
+
+PKIX_Error*
+PKIX_DoThrow(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode, PKIX_ERRORCLASS overrideClass,
+ void *plContext)
+{
+ if (!pkixErrorReceived && !pkixErrorResult && pkixErrorList) {
+ pkixTempResult = PKIX_List_GetItem(pkixErrorList, 0,
+ (PKIX_PL_Object**)&pkixReturnResult,
+ plContext);
+ } else {
+ pkixTempResult = (PKIX_Error*)pkix_Throw(errClass, myFuncName, errCode,
+ overrideClass, pkixErrorResult,
+ &pkixReturnResult, plContext);
+ }
+ if (pkixReturnResult) {
+ if (pkixErrorResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ pkixTempResult = pkixReturnResult;
+ } else if (pkixErrorResult) {
+ if (pkixTempResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixTempResult);
+ }
+ pkixTempResult = pkixErrorResult;
+ }
+ if (pkixErrorList) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext);
+ pkixErrorList = NULL;
+ }
+ return pkixTempResult;
+}
+
+PKIX_Error *
+PKIX_DoReturn(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger, void *plContext)
+{
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (pkixErrorReceived || pkixErrorResult || pkixErrorList)
+ return PKIX_DoThrow(stdVars, errClass, pkixErrorCode, pkixErrorClass,
+ plContext);
+ /* PKIX_DEBUG_EXIT(type); */
+ if (doLogger)
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE);
+ return NULL;
+}
+
+/* PKIX_DoAddError - creates the list of received error if it does not exist
+ * yet and adds newly received error into the list. */
+void
+PKIX_DoAddError(PKIX_StdVars *stdVars, PKIX_Error *error, void * plContext)
+{
+ PKIX_List *localList = NULL;
+ PKIX_Error *localError = NULL;
+ PKIX_Boolean listCreated = PKIX_FALSE;
+
+ if (!pkixErrorList) {
+ localError = PKIX_List_Create(&localList, plContext);
+ if (localError)
+ goto cleanup;
+ listCreated = PKIX_TRUE;
+ } else {
+ localList = pkixErrorList;
+ }
+
+ localError = PKIX_List_AppendItem(localList, (PKIX_PL_Object*)error,
+ plContext);
+ PORT_Assert (localError == NULL);
+ if (localError != NULL) {
+ if (listCreated) {
+ /* ignore the error code of DecRef function */
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localList, plContext);
+ localList = NULL;
+ }
+ } else {
+ pkixErrorList = localList;
+ }
+
+cleanup:
+
+ if (localError && localError != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localError, plContext);
+ }
+
+ if (error && error != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
+ }
+}
+
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.c b/security/nss/lib/libpkix/pkix/util/pkix_list.c
new file mode 100644
index 0000000000..d02b66e6d6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.c
@@ -0,0 +1,1701 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_list.c
+ *
+ * List Object Functions
+ *
+ */
+
+#include "pkix_list.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_List_Create_Internal
+ * DESCRIPTION:
+ *
+ * Creates a new List, using the Boolean value of "isHeader" to determine
+ * whether the new List should be a header, and stores it at "pList". The
+ * List is initially empty and holds no items. To initially add items to
+ * the List, use PKIX_List_AppendItem.
+ *
+ * PARAMETERS:
+ * "isHeader"
+ * Boolean value indicating whether new List should be a header.
+ * "pList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_Create_Internal(
+ PKIX_Boolean isHeader,
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Create_Internal");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LIST_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_List))),
+ (PKIX_PL_Object **)&list, plContext),
+ PKIX_ERRORCREATINGLISTITEM);
+
+ list->item = NULL;
+ list->next = NULL;
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = isHeader;
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *nextItem = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a list */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ /* We have a valid list. DecRef its item and recurse on next */
+ PKIX_DECREF(list->item);
+ while ((nextItem = list->next) != NULL) {
+ list->next = nextItem->next;
+ nextItem->next = NULL;
+ PKIX_DECREF(nextItem);
+ }
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the List pointed
+ * to by "list" and stores its address in the object pointed to by "pString".
+ *
+ * PARAMETERS
+ * "list"
+ * Address of List whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a List Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_ToString_Helper(
+ PKIX_List *list,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *itemString = NULL;
+ PKIX_PL_String *nextString = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString_Helper");
+ PKIX_NULLCHECK_TWO(list, pString);
+
+ /* special case when list is the header */
+ if (list->isHeader){
+
+ PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext),
+ PKIX_LISTISEMPTYFAILED);
+
+ if (empty){
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "EMPTY",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_ERRORCREATINGITEMSTRING);
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ } else {
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &itemString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+ }
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString, plContext, format, itemString),
+ PKIX_SPRINTFFAILED);
+ } else {
+ /* Get a string for this list's item */
+ if (list->item == NULL) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "(null)",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)list->item,
+ &itemString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ }
+ if (list->next == NULL) {
+ /* Just return the itemstring */
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ }
+
+ /* Recursive call to get string for this list's next pointer */
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &nextString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s, %s",
+ 0,
+ &format,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ format,
+ itemString,
+ nextString),
+ PKIX_SPRINTFFAILED);
+ }
+
+cleanup:
+
+ PKIX_DECREF(itemString);
+ PKIX_DECREF(nextString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_String *listString = NULL;
+ PKIX_PL_String *format = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(%s)", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(listString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_List *firstList = NULL;
+ PKIX_List *secondList = NULL;
+ PKIX_UInt32 firstLength = 0;
+ PKIX_UInt32 secondLength = 0;
+ PKIX_PL_Object *firstItem = NULL;
+ PKIX_PL_Object *secondItem = NULL;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a List */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLIST);
+
+ /*
+ * Since we know first is a List, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a List, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LIST_TYPE) goto cleanup;
+
+ firstList = (PKIX_List *)first;
+ secondList = (PKIX_List *)second;
+
+ if ((!firstList->isHeader) && (!secondList->isHeader)){
+ PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS);
+ }
+
+ firstLength = firstList->length;
+ secondLength = secondList->length;
+
+ cmpResult = PKIX_FALSE;
+ if (firstLength == secondLength){
+ for (i = 0, cmpResult = PKIX_TRUE;
+ ((i < firstLength) && cmpResult);
+ i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (firstList, i, &firstItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &secondItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if ((!firstItem && secondItem) ||
+ (firstItem && !secondItem)){
+ cmpResult = PKIX_FALSE;
+ } else if (!firstItem && !secondItem){
+ continue;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (firstItem,
+ secondItem,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+ }
+ }
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *element = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ for (i = 0; i < length; i++){
+ PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (!element){
+ tempHash = 100;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ (element, &tempHash, plContext),
+ PKIX_LISTHASHCODEFAILED);
+ }
+
+ hash = 31 * hash + tempHash;
+
+ PKIX_DECREF(element);
+ }
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_DECREF(element);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *listDuplicate = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (list->immutable){
+ PKIX_CHECK(pkix_duplicateImmutable
+ (object, pNewObject, plContext),
+ PKIX_DUPLICATEIMMUTABLEFAILED);
+ } else {
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (list->isHeader, &listDuplicate, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ listDuplicate->length = list->length;
+
+ PKIX_INCREF(list->item);
+ listDuplicate->item = list->item;
+
+ if (list->next == NULL){
+ listDuplicate->next = NULL;
+ } else {
+ /* Recursively Duplicate list */
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *)list->next,
+ (PKIX_PL_Object **)&listDuplicate->next,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+ }
+
+ *pNewObject = (PKIX_PL_Object *)listDuplicate;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(listDuplicate);
+ }
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_GetElement
+ * DESCRIPTION:
+ *
+ * Copies the "list"'s element at "index" into "element". The input List must
+ * be the header of the List (as opposed to being an element of the List). The
+ * index counts from zero and must be less than the List's length. This
+ * function does NOT increment the reference count of the List element since
+ * the returned element's reference will not be stored by the calling
+ * function.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List (must be header) to get element from. Must be non-NULL.
+ * "index"
+ * Index of list to get element from. Must be less than List's length.
+ * "pElement"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_GetElement(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_List **pElement,
+ void *plContext)
+{
+ PKIX_List *iterator = NULL;
+ PKIX_UInt32 length;
+ PKIX_UInt32 position = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_GetElement");
+ PKIX_NULLCHECK_TWO(list, pElement);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (index >= length) {
+ PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS);
+ }
+
+ for (iterator = list; position++ <= index; iterator = iterator->next)
+ ;
+
+ (*pElement) = iterator;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LIST_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_List_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LIST, "pkix_List_RegisterSelf");
+
+ entry.description = "List";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_List);
+ entry.destructor = pkix_List_Destroy;
+ entry.equalsFunction = pkix_List_Equals;
+ entry.hashcodeFunction = pkix_List_Hashcode;
+ entry.toStringFunction = pkix_List_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_List_Duplicate;
+
+ systemClasses[PKIX_LIST_TYPE] = entry;
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Contains
+ * DESCRIPTION:
+ *
+ * Checks a List pointed to by "list", to determine whether it includes
+ * an entry that is equal to the Object pointed to by "object", and stores
+ * the result in "pFound".
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object to be checked for; must be non-NULL
+ * "pFound"
+ * Address where the result of the search will be stored. Must
+ * be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Contains");
+ PKIX_NULLCHECK_THREE(list, object, pFound);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ break;
+ }
+ }
+
+ *pFound = match;
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Remove
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object pointed to by "object". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object to be checked for and deleted, if found; must be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Validate Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Remove");
+ PKIX_NULLCHECK_TWO(list, object);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (list, index, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ break;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_RemoveItems
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object in the "deleteList". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * Object in "list" is checked for object in "deleteList" and deleted if
+ * found; may be empty; must be non-NULL
+ * "deleteList"
+ * List of objects to be searched ; may be empty; must be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Validate Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_RemoveItems");
+ PKIX_NULLCHECK_TWO(list, deleteList);
+
+ PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (deleteList, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(pkix_List_Remove
+ (list, current, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_MergeLists
+ * DESCRIPTION:
+ *
+ * Creates a new list consisting of the items from "firstList", followed by
+ * the items on "secondList", returns the new list at "pMergedList". If
+ * both input lists are NULL or empty, the result is an empty list. If an error
+ * occurs, the result is NULL.
+ *
+ * PARAMETERS:
+ * "firstList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "secondList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "pMergedList"
+ * Address where returned object is stored.
+ * "plContext"
+ * platform-specific context pointer * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a List Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_MergeLists");
+ PKIX_NULLCHECK_ONE(pMergedList);
+
+ *pMergedList = NULL;
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (firstList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ numItems = 0;
+ if (secondList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (secondList,
+ &numItems,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list, item, plContext), PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ *pMergedList = list;
+ list = NULL;
+
+cleanup:
+ PKIX_DECREF(list);
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendList
+ * DESCRIPTION:
+ *
+ * Append items on "fromList" to the "toList". Item reference count on
+ * "toList" is not incremented, but items appended from "fromList" are
+ * incremented.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of list to be appended to. Must be non-NULL.
+ * "fromList"
+ * Address of list to be appended from. May be NULL or empty.
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a List Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_AppendList");
+ PKIX_NULLCHECK_ONE(toList);
+
+ /* if fromList is NULL or is an empty list, no action */
+
+ if (fromList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numItems == 0) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+cleanup:
+
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendUnique
+ * DESCRIPTION:
+ *
+ * Adds each Object in the List pointed to by "fromList" to the List pointed
+ * to by "toList", if it is not already a member of that List. In other words,
+ * "toList" becomes the union of the two sets.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of a List of Objects to be augmented by "fromList". Must be
+ * non-NULL, but may be empty.
+ * "fromList"
+ * Address of a List of Objects to be added, if not already present, to
+ * "toList". Must be non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 listLen = 0;
+ PKIX_UInt32 listIx = 0;
+ PKIX_PL_Object *object = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_List_AppendUnique");
+ PKIX_NULLCHECK_TWO(fromList, toList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (listIx = 0; listIx < listLen; listIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, listIx, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (toList, object, &isContained, plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isContained == PKIX_FALSE) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (toList, object, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(object);
+ }
+
+cleanup:
+
+ PKIX_DECREF(object);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_QuickSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is quick sort (n*logn).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_List *lessList = NULL;
+ PKIX_List *greaterList = NULL;
+ PKIX_List *sortedLessList = NULL;
+ PKIX_List *sortedGreaterList = NULL;
+ PKIX_PL_Object *object = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_List_QuickSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&lessList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&greaterList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, 0, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Pick the first item on the list as the one to be compared.
+ * Separate rest of the itmes into two lists: less-than or greater-
+ * than lists. Sort those two lists recursively. Insert sorted
+ * less-than list before the picked item and append the greater-
+ * than list after the picked item.
+ */
+ for (i = 1; i < size; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+
+ if (cmpResult >= 0) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (lessList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (greaterList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(cmpObj);
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&sortedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (lessList, comparator, &sortedLessList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedLessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, lessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext),
+ PKIX_LISTAPPENDFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (greaterList, comparator, &sortedGreaterList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedGreaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, greaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ *pSortedList = sortedList;
+
+cleanup:
+
+ PKIX_DECREF(cmpObj);
+ PKIX_DECREF(object);
+ PKIX_DECREF(sortedGreaterList);
+ PKIX_DECREF(sortedLessList);
+ PKIX_DECREF(greaterList);
+ PKIX_DECREF(lessList);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_BubbleSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is bubble sort (n*n).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_PL_Object *leastObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i, j;
+
+ PKIX_ENTER(BUILD, "pkix_List_BubbleSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ if (fromList->immutable) {
+ PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST);
+ }
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *) fromList,
+ (PKIX_PL_Object **) &sortedList,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ /*
+ * Move from the first of the item on the list, For each iteration,
+ * compare and swap the least value to the head of the comparisoning
+ * sub-list.
+ */
+ for (i = 0; i < size - 1; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, i, &leastObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ for (j = i + 1; j < size; j++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, j, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(comparator
+ (leastObj, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+ if (cmpResult > 0) {
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, j, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ leastObj = cmpObj;
+ cmpObj = NULL;
+ } else {
+ PKIX_DECREF(cmpObj);
+ }
+ }
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, i, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ }
+
+ }
+
+ *pSortedList = sortedList;
+ sortedList = NULL;
+cleanup:
+
+ PKIX_DECREF(sortedList);
+ PKIX_DECREF(leastObj);
+ PKIX_DECREF(cmpObj);
+
+ PKIX_RETURN(LIST);
+}
+
+/* --Public-List-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_List_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_Create(
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_Create");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetImmutable(
+ PKIX_List *list,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_SetImmutable");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ list->immutable = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsImmutable(
+ PKIX_List *list,
+ PKIX_Boolean *pImmutable,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_IsImmutable");
+ PKIX_NULLCHECK_TWO(list, pImmutable);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pImmutable = list->immutable;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetLength(
+ PKIX_List *list,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_GetLength");
+ PKIX_NULLCHECK_TWO(list, pLength);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pLength = list->length;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsEmpty(
+ PKIX_List *list,
+ PKIX_Boolean *pEmpty,
+ void *plContext)
+{
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(LIST, "PKIX_List_IsEmpty");
+ PKIX_NULLCHECK_TWO(list, pEmpty);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (length == 0){
+ *pEmpty = PKIX_TRUE;
+ } else {
+ *pEmpty = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_AppendItem(
+ PKIX_List *list,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *lastElement = NULL;
+ PKIX_List *newElement = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "PKIX_List_AppendItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* find last element of list and create new element there */
+
+ lastElement = list;
+ for (i = 0; i < length; i++){
+ lastElement = lastElement->next;
+ }
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (PKIX_FALSE, &newElement, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ PKIX_INCREF(item);
+ newElement->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ lastElement->next = newElement;
+ newElement = NULL;
+ list->length += 1;
+
+cleanup:
+
+ PKIX_DECREF(newElement);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_InsertItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *newElem = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_InsertItem");
+ PKIX_NULLCHECK_ONE(list);
+
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ /* Create a new list object */
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ if (list->length) {
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ /* Copy the old element's contents into the new element */
+ newElem->item = element->item;
+ /* Add new item to the list */
+ PKIX_INCREF(item);
+ element->item = item;
+ /* Set the new element's next pointer to the old element's next */
+ newElem->next = element->next;
+ /* Set the old element's next pointer to the new element */
+ element->next = newElem;
+ newElem = NULL;
+ } else {
+ PKIX_INCREF(item);
+ newElem->item = item;
+ newElem->next = NULL;
+ list->next = newElem;
+ newElem = NULL;
+ }
+ list->length++;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+ PKIX_DECREF(newElem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object **pItem,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_GetItem");
+ PKIX_NULLCHECK_TWO(list, pItem);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ PKIX_INCREF(element->item);
+ *pItem = element->item;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element;
+
+ PKIX_ENTER(LIST, "PKIX_List_SetItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ /* Set New Contents */
+ PKIX_INCREF(item);
+ element->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_DeleteItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *prevElement = NULL;
+ PKIX_List *nextElement = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_DeleteItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ nextElement = element->next;
+
+ if (nextElement != NULL) {
+ /* If the next element exists, splice it out. */
+
+ /* Don't need to change ref counts for targets of next */
+ element->item = nextElement->item;
+ nextElement->item = NULL;
+
+ /* Don't need to change ref counts for targets of next */
+ element->next = nextElement->next;
+ nextElement->next = NULL;
+
+ PKIX_DECREF(nextElement);
+
+ } else { /* The element is at the tail of the list */
+ if (index != 0) {
+ PKIX_CHECK(pkix_List_GetElement
+ (list, index-1, &prevElement, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ } else if (index == 0){ /* prevElement must be header */
+ prevElement = list;
+ }
+ prevElement->next = NULL;
+
+ /* Delete the element */
+ PKIX_DECREF(element);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ list->length = list->length - 1;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_ReverseList(
+ PKIX_List *list,
+ PKIX_List **pReversedList,
+ void *plContext)
+{
+ PKIX_List *reversedList = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_PL_Object *duplicateItem = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_ReverseList");
+ PKIX_NULLCHECK_TWO(list, pReversedList);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* Create a new list object */
+ PKIX_CHECK(PKIX_List_Create(&reversedList, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ /*
+ * Starting with the last item and traversing backwards (from
+ * the original list), append each item to the reversed list
+ */
+
+ for (i = 1; i <= length; i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, (length - i), &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ (item, &duplicateItem, plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (reversedList, duplicateItem, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+ }
+
+ *pReversedList = reversedList;
+
+cleanup:
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(reversedList);
+ }
+
+ PKIX_RETURN(LIST);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.h b/security/nss/lib/libpkix/pkix/util/pkix_list.h
new file mode 100644
index 0000000000..13e104f21a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.h
@@ -0,0 +1,95 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_list.h
+ *
+ * List Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LIST_H
+#define _PKIX_LIST_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PKIX_Error *
+(*PKIX_List_SortComparatorCallback)(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext);
+
+struct PKIX_ListStruct {
+ PKIX_PL_Object *item;
+ PKIX_List *next;
+ PKIX_Boolean immutable;
+ PKIX_UInt32 length;
+ PKIX_Boolean isHeader;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_List_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *target,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LIST_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.c b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
new file mode 100644
index 0000000000..10f537a319
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
@@ -0,0 +1,1088 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_logger.c
+ *
+ * Logger Object Functions
+ *
+ */
+
+#include "pkix_logger.h"
+#ifndef PKIX_ERROR_DESCRIPTION
+#include "prprf.h"
+#endif
+
+/* Global variable to keep PKIX_Logger List */
+PKIX_List *pkixLoggers = NULL;
+
+/*
+ * Once the Logger has been set, for any logging related operations, we have
+ * to go through the List to find a match, and if found, issue the
+ * corresponding callback. The overhead to check for DEBUG and TRACE in each
+ * PKIX function entering and exiting is very expensive (400X), and redundant
+ * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
+ * pkixLoggers is separated into two lists based on its Loggers' trace level.
+ *
+ * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
+ * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
+ * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
+ * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
+ * pkixLoggersDebugTrace.
+ *
+ * Currently we provide five logging levels and the default setting are by:
+ *
+ * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
+ * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
+ * WARNING is not invoked as default
+ * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
+ * compilation -DPKIX_<component>DEBUG flag to turn on
+ * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
+ * level. TRACE provides duplicate information of DEBUG, but needs no
+ * recompilation and cannot choose component. To allow application
+ * to use DEBUG level, TRACE is put as last.
+ *
+ */
+PKIX_List *pkixLoggersErrors = NULL;
+PKIX_List *pkixLoggersDebugTrace = NULL;
+
+/* To ensure atomic update on pkixLoggers lists */
+PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Logger_CheckErrors
+ * DESCRIPTION:
+ *
+ * This function goes through each PKIX_Logger at "pkixLoggersList" and
+ * checks if "maxLevel" and "logComponent" satisfies what is specified in the
+ * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
+ * passes a PKIX_PL_String that is the concatenation of "message" and
+ * "message2" to the application for processing.
+ * Since this call is inserted into a handful of PKIX macros, no macros are
+ * applied in this function, to avoid infinite recursion.
+ * If an error occurs, this call is aborted.
+ *
+ * PARAMETERS:
+ * "pkixLoggersList"
+ * A list of PKIX_Loggers to be examined for invoking callback. Must be
+ * non-NULL.
+ * "message"
+ * Address of "message" to be logged. Must be non-NULL.
+ * "message2"
+ * Address of "message2" to be concatenated and logged. May be NULL.
+ * "logComponent"
+ * A PKIX_UInt32 that indicates the component the message is from.
+ * "maxLevel"
+ * A PKIX_UInt32 that represents the level of severity of the message.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *messageString = NULL;
+ PKIX_PL_String *message2String = NULL;
+ PKIX_PL_String *msgString = NULL;
+ PKIX_Error *error = NULL;
+ PKIX_Boolean needLogging = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ /*
+ * We cannot use any the PKIX_ macros here, since this function is
+ * called from some of these macros. It can create infinite recursion.
+ */
+
+ if ((pkixLoggersList == NULL) || (message == NULL)) {
+ return(NULL);
+ }
+
+ /*
+ * Disable all subsequent loggings to avoid recursion. The result is
+ * if other thread is calling this function at the same time, there
+ * won't be any logging because the pkixLoggersErrors and
+ * pkixLoggersDebugTrace are set to null.
+ * It would be nice if we provide control per thread (e.g. make
+ * plContext threadable) then we can avoid the recursion by setting
+ * flag at plContext. Then other thread's logging won't be affected.
+ *
+ * Also we need to use a reentrant Lock. Although we avoid recursion
+ * for TRACE. When there is an ERROR occurs in subsequent call, this
+ * function will be called.
+ */
+
+ error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* Convert message and message2 to String */
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message, 0, &messageString, plContext);
+ if (error) { goto cleanup; }
+
+ if (message2) {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message2, 0, &message2String, plContext);
+ if (error) { goto cleanup; }
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ } else {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ }
+
+ error = PKIX_PL_Sprintf
+ (&msgString,
+ plContext,
+ formatString,
+ messageString,
+ message2String);
+ if (error) { goto cleanup; }
+
+ /* Go through the Logger list */
+
+ error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
+ if (error) { goto cleanup; }
+
+ for (i = 0; i < length; i++) {
+
+ error = PKIX_List_GetItem
+ (pkixLoggersList,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext);
+ if (error) { goto cleanup; }
+
+ /* Intended logging level less or equal than the max */
+ needLogging = (currentLevel <= logger->maxLevel);
+
+ if (needLogging && (logger->callback)) {
+
+ /*
+ * We separate Logger into two lists based on log level
+ * but log level is not modified. We need to check here to
+ * avoid logging the higher log level (lower value) twice.
+ */
+ if (pkixLoggersList == pkixLoggersErrors) {
+ needLogging = needLogging &&
+ (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
+ } else if (pkixLoggersList == pkixLoggersDebugTrace) {
+ needLogging = needLogging &&
+ (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
+ }
+
+ if (needLogging) {
+ if (logComponent == logger->logComponent) {
+ needLogging = PKIX_TRUE;
+ } else {
+ needLogging = PKIX_FALSE;
+ }
+ }
+
+ if (needLogging) {
+ error = logger->callback
+ (logger,
+ msgString,
+ currentLevel,
+ logComponent,
+ plContext);
+ if (error) { goto cleanup; }
+ }
+ }
+
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ logger = NULL;
+ if (error) { goto cleanup; }
+
+ }
+
+cleanup:
+
+ if (formatString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)formatString, plContext);
+ }
+
+ if (messageString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)messageString, plContext);
+ }
+
+ if (message2String) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)message2String, plContext);
+ }
+
+ if (msgString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)msgString, plContext);
+ }
+
+ if (logger) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ }
+
+ if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ }
+
+ if (pkixLoggersDebugTrace == NULL &&
+ savedPkixLoggersDebugTrace != NULL) {
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ }
+
+ error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ return(NULL);
+}
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ char error[32];
+ char *errorString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
+#if defined PKIX_ERROR_DESCRIPTION
+ errorString = PKIX_ErrorText[errorCode];
+#else
+ PR_snprintf(error, 32, "Error code: %d", errorCode);
+ errorString = error;
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+ pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
+ message2, logComponent,
+ currentLevel, plContext);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ /* We have a valid logger. DecRef its item and recurse on next */
+
+ logger->callback = NULL;
+ PKIX_DECREF(logger->context);
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *contextString = NULL;
+ PKIX_PL_String *componentString = NULL;
+ PKIX_PL_String *loggerString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ asciiFormat =
+ "[\n"
+ "\tLogger: \n"
+ "\tContext: %s\n"
+ "\tMaximum Level: %d\n"
+ "\tComponent Name: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(logger->context, &contextString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
+ 0,
+ &componentString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&loggerString,
+ plContext,
+ formatString,
+ contextString,
+ logger->maxLevel,
+ componentString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = loggerString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(contextString);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_Logger *firstLogger = NULL;
+ PKIX_Logger *secondLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a Logger */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLOGGER);
+
+ /*
+ * Since we know first is a Logger, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a Logger, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
+
+ firstLogger = (PKIX_Logger *)first;
+ secondLogger = (PKIX_Logger *)second;
+
+ cmpResult = PKIX_FALSE;
+
+ if (firstLogger->callback != secondLogger->callback) {
+ goto cleanup;
+ }
+
+ if (firstLogger->logComponent != secondLogger->logComponent) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstLogger->context,
+ secondLogger->context,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ if (firstLogger->maxLevel != secondLogger->maxLevel) {
+ goto cleanup;
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ PKIX_HASHCODE(logger->context, &tempHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) +
+ logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * FUNCTION: pkix_Logger_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *) object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ dupLogger->callback = logger->callback;
+ dupLogger->maxLevel = logger->maxLevel;
+
+ PKIX_DUPLICATE
+ (logger->context,
+ &dupLogger->context,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ dupLogger->logComponent = logger->logComponent;
+
+ *pNewObject = (PKIX_PL_Object *) dupLogger;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(dupLogger);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_Logger_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
+
+ entry.description = "Logger";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Logger);
+ entry.destructor = pkix_Logger_Destroy;
+ entry.equalsFunction = pkix_Logger_Equals;
+ entry.hashcodeFunction = pkix_Logger_Hashcode;
+ entry.toStringFunction = pkix_Logger_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_Logger_Duplicate;
+
+ systemClasses[PKIX_LOGGER_TYPE] = entry;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/* --Public-Logger-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_Create(
+ PKIX_Logger_LogCallback callback,
+ PKIX_PL_Object *loggerContext,
+ PKIX_Logger **pLogger,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
+ PKIX_NULLCHECK_ONE(pLogger);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&logger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ logger->callback = callback;
+ logger->maxLevel = 0;
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+ PKIX_INCREF(loggerContext);
+ logger->context = loggerContext;
+
+ *pLogger = logger;
+ logger = NULL;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLogCallback(
+ PKIX_Logger *logger,
+ PKIX_Logger_LogCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
+ PKIX_NULLCHECK_TWO(logger, pCallback);
+
+ *pCallback = logger->callback;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggerContext(
+ PKIX_Logger *logger,
+ PKIX_PL_Object **pLoggerContext,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
+ PKIX_NULLCHECK_TWO(logger, pLoggerContext);
+
+ PKIX_INCREF(logger->context);
+ *pLoggerContext = logger->context;
+
+cleanup:
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 *pLevel,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_NULLCHECK_TWO(logger, pLevel);
+
+ *pLevel = logger->maxLevel;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 level,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_NULLCHECK_ONE(logger);
+
+ if (level > PKIX_LOGGER_LEVEL_MAX) {
+ PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
+ } else {
+ logger->maxLevel = level;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS *pComponent,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
+ PKIX_NULLCHECK_TWO(logger, pComponent);
+
+ *pComponent = logger->logComponent;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS component,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
+ PKIX_NULLCHECK_ONE(logger);
+
+ logger->logComponent = component;
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
+ * documented as not thread-safe. However they are thread-safe now. We need
+ * the lock when accessing the logger lists.
+ */
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_GetLoggers(
+ PKIX_List **pLoggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_UInt32 i, length;
+ PKIX_Boolean locked = PKIX_FALSE;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
+ PKIX_NULLCHECK_ONE(pLoggers);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /*
+ * Temporarily disable DEBUG/TRACE Logging to avoid possible
+ * deadlock:
+ * When the Logger List is being accessed, e.g. by PKIX_ENTER or
+ * PKIX_DECREF, pkix_Logger_Check may check whether logging
+ * is requested, creating a deadlock situation.
+ */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ if (pkixLoggers == NULL) {
+ length = 0;
+ } else {
+ PKIX_CHECK(PKIX_List_GetLength
+ (pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /* Create a list and copy the pkixLoggers item to the list */
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+ }
+
+ /* Set the list to be immutable */
+ PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pLoggers = list;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ /* Restore logging capability */
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ pkixLoggersErrors = savedPkixLoggersErrors;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_SetLoggers(
+ PKIX_List *loggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /* Disable tracing, etc. to avoid recursion and deadlock */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* discard any prior loggers */
+ PKIX_DECREF(pkixLoggers);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (loggers != NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (loggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /* Make two lists */
+
+ /* Put in pkixLoggersErrors in any case*/
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+
+ }
+
+ pkixLoggers = list;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(list);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+ pkixLoggers = NULL;
+ }
+
+ PKIX_DECREF(logger);
+
+ /* Reenable logging capability with new lists */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_AddLogger(
+ PKIX_Logger *logger,
+ void *plContext)
+{
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Logger *addLogger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
+ PKIX_NULLCHECK_ONE(logger);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (pkixLoggers == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (pkixLoggers,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &addLogger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+
+ /* Put in pkixLoggersErrors */
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(addLogger);
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(dupLogger);
+ PKIX_DECREF(addLogger);
+
+ /* Restore logging capability */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.h b/security/nss/lib/libpkix/pkix/util/pkix_logger.h
new file mode 100644
index 0000000000..9411aed2e2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.h
@@ -0,0 +1,57 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_logger.h
+ *
+ * Logger Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LOGGER_H
+#define _PKIX_LOGGER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKIX_List *pkixLoggers;
+extern PKIX_List *pkixLoggersErrors;
+extern PKIX_List *pkixLoggersDebugTrace;
+
+struct PKIX_LoggerStruct {
+ PKIX_Logger_LogCallback callback;
+ PKIX_PL_Object *context;
+ PKIX_UInt32 maxLevel;
+ PKIX_ERRORCLASS logComponent;
+};
+
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_Logger_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LOGGER_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
new file mode 100644
index 0000000000..4c01f8da14
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
@@ -0,0 +1,1525 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_tools.c
+ *
+ * Private Utility Functions
+ *
+ */
+
+#include "pkix_tools.h"
+
+#define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */
+
+/*
+ * This cahce period is only for CertCache. A Cert from a trusted CertStore
+ * should be checked more frequently for update new arrival, etc.
+ */
+#define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10)
+
+extern PKIX_PL_HashTable *cachedCertChainTable;
+extern PKIX_PL_HashTable *cachedCertTable;
+extern PKIX_PL_HashTable *cachedCrlEntryTable;
+
+/* Following variables are used to checked cache hits - can be taken out */
+extern int pkix_ccAddCount;
+extern int pkix_ccLookupCount;
+extern int pkix_ccRemoveCount;
+extern int pkix_cAddCount;
+extern int pkix_cLookupCount;
+extern int pkix_cRemoveCount;
+extern int pkix_ceAddCount;
+extern int pkix_ceLookupCount;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/* Following variables are used for object leak test */
+char *nonNullValue = "Non Empty Value";
+PKIX_Boolean noErrorState = PKIX_TRUE;
+PKIX_Boolean runningLeakTest;
+PKIX_Boolean errorGenerated;
+PKIX_UInt32 stackPosition;
+PKIX_UInt32 *fnStackInvCountArr;
+char **fnStackNameArr;
+PLHashTable *fnInvTable;
+PKIX_UInt32 testStartFnStackPosition;
+char *errorFnStackString;
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/* --Private-Functions-------------------------------------------- */
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/*
+ * FUNCTION: pkix_ErrorGen_Hash
+ * DESCRIPTION:
+ *
+ * Hash function to be used in object leak test hash table.
+ *
+ */
+PLHashNumber PR_CALLBACK
+pkix_ErrorGen_Hash (const void *key)
+{
+ char *str = NULL;
+ PLHashNumber rv = (*(PRUint8*)key) << 5;
+ PRUint32 i, counter = 0;
+ PRUint8 *rvc = (PRUint8 *)&rv;
+
+ while ((str = fnStackNameArr[counter++]) != NULL) {
+ PRUint32 len = strlen(str);
+ for( i = 0; i < len; i++ ) {
+ rvc[ i % sizeof(rv) ] ^= *str;
+ str++;
+ }
+ }
+
+ return rv;
+}
+
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/*
+ * FUNCTION: pkix_IsCertSelfIssued
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" is self-issued and stores the
+ * Boolean result at "pSelfIssued". A Cert is considered self-issued if the
+ * Cert's issuer matches the Cert's subject. If the subject or issuer is
+ * not specified, a PKIX_FALSE is returned.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert used to determine whether Cert is self-issued.
+ * Must be non-NULL.
+ * "pSelfIssued"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext)
+{
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+
+ PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
+ PKIX_NULLCHECK_TWO(cert, pSelfIssued);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (subject == NULL || issuer == NULL) {
+ *pSelfIssued = PKIX_FALSE;
+ } else {
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (subject, issuer, pSelfIssued, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+ }
+
+cleanup:
+ PKIX_DECREF(subject);
+ PKIX_DECREF(issuer);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_Throw
+ * DESCRIPTION:
+ *
+ * Creates an Error using the value of "errorCode", the character array
+ * pointed to by "funcName", the character array pointed to by "errorText",
+ * and the Error pointed to by "cause" (if any), and stores it at "pError".
+ *
+ * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
+ * then there is no point creating a new Error object. Rather, we simply
+ * store "cause" at "pError".
+ *
+ * PARAMETERS:
+ * "errorCode"
+ * Value of error code.
+ * "funcName"
+ * Address of EscASCII array representing name of function throwing error.
+ * Must be non-NULL.
+ * "errnum"
+ * PKIX_ERRMSGNUM of error description for new error.
+ * "cause"
+ * Address of Error representing error's cause.
+ * "pError"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_Throw(
+ PKIX_ERRORCLASS errorClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Throw");
+ PKIX_NULLCHECK_TWO(funcName, pError);
+
+ *pError = NULL;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_TRUE;
+ if (pkixLog) {
+#ifdef PKIX_ERROR_DESCRIPTION
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
+ funcName, PKIX_ErrorText[errorCode],
+ (cause ? PKIX_ErrorText[cause->errCode] : "null")));
+#else
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n",
+ funcName, errorCode));
+#endif /* PKIX_ERROR_DESCRIPTION */
+ PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
+ if (cause) {
+ if (cause->errClass == PKIX_FATAL_ERROR){
+ PKIX_INCREF(cause);
+ *pError = cause;
+ goto cleanup;
+ }
+ }
+
+ if (overrideClass == PKIX_FATAL_ERROR){
+ errorClass = overrideClass;
+ }
+
+ pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
+ errorCode, &error, plContext);
+
+ if (!pkixTempResult) {
+ /* Setting plErr error code:
+ * get it from PORT_GetError if it is a leaf error and
+ * default error code does not exist(eq 0) */
+ if (!cause && !error->plErr) {
+ error->plErr = PKIX_PL_GetPLErrorCode();
+ }
+ }
+
+ *pError = error;
+
+cleanup:
+
+ PKIX_DEBUG_EXIT(ERROR);
+ pkixErrorClass = 0;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_FALSE;
+
+ if (runningLeakTest && fnStackNameArr) {
+ PR_LOG(pkixLog, 5,
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
+ stackPosition, " ", fnStackNameArr[stackPosition],
+ stackPosition, myFuncName));
+ fnStackNameArr[stackPosition--] = NULL;
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+ return (pkixTempResult);
+}
+
+/*
+ * FUNCTION: pkix_CheckTypes
+ * DESCRIPTION:
+ *
+ * Checks that the types of the Object pointed to by "first" and the Object
+ * pointed to by "second" are both equal to the value of "type". If they
+ * are not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "first"
+ * Address of first Object. Must be non-NULL.
+ * "second"
+ * Address of second Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ PKIX_UInt32 firstType, secondType;
+
+ PKIX_ENTER(OBJECT, "pkix_CheckTypes");
+ PKIX_NULLCHECK_TWO(first, second);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
+ PKIX_COULDNOTGETFIRSTOBJECTTYPE);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETSECONDOBJECTTYPE);
+
+ if ((firstType != type)||(firstType != secondType)) {
+ PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_CheckType
+ * DESCRIPTION:
+ *
+ * Checks that the type of the Object pointed to by "object" is equal to the
+ * value of "type". If it is not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ return (pkix_CheckTypes(object, object, type, plContext));
+}
+
+/*
+ * FUNCTION: pkix_hash
+ * DESCRIPTION:
+ *
+ * Computes a hash value for "length" bytes starting at the array of bytes
+ * pointed to by "bytes" and stores the result at "pHash".
+ *
+ * XXX To speed this up, we could probably read 32 bits at a time from
+ * bytes (maybe even 64 bits on some platforms)
+ *
+ * PARAMETERS:
+ * "bytes"
+ * Address of array of bytes to hash. Must be non-NULL.
+ * "length"
+ * Number of bytes to hash.
+ * "pHash"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *pHash,
+ void *plContext)
+{
+ PKIX_UInt32 i;
+ PKIX_UInt32 hash;
+
+ PKIX_ENTER(OBJECT, "pkix_hash");
+ if (length != 0) {
+ PKIX_NULLCHECK_ONE(bytes);
+ }
+ PKIX_NULLCHECK_ONE(pHash);
+
+ hash = 0;
+ for (i = 0; i < length; i++) {
+ /* hash = 31 * hash + bytes[i]; */
+ hash = (hash << 5) - hash + bytes[i];
+ }
+
+ *pHash = hash;
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_countArray
+ * DESCRIPTION:
+ *
+ * Counts the number of elements in the null-terminated array of pointers
+ * pointed to by "array" and returns the result.
+ *
+ * PARAMETERS
+ * "array"
+ * Address of null-terminated array of pointers.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the number of elements in the array.
+ */
+PKIX_UInt32
+pkix_countArray(void **array)
+{
+ PKIX_UInt32 count = 0;
+
+ if (array) {
+ while (*array++) {
+ count++;
+ }
+ }
+ return (count);
+}
+
+/*
+ * FUNCTION: pkix_duplicateImmutable
+ * DESCRIPTION:
+ *
+ * Convenience callback function used for duplicating immutable objects.
+ * Since the objects can not be modified, this function simply increments the
+ * reference count on the object, and returns a reference to that object.
+ *
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_INCREF(object);
+
+ *pNewObject = object;
+
+cleanup:
+ PKIX_RETURN(OBJECT);
+}
+
+/* --String-Encoding-Conversion-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_hex2i
+ * DESCRIPTION:
+ *
+ * Converts hexadecimal character "c" to its integer value and returns result.
+ *
+ * PARAMETERS
+ * "c"
+ * Character to convert to a hex value.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
+ */
+PKIX_UInt32
+pkix_hex2i(char c)
+{
+ if ((c >= '0')&&(c <= '9'))
+ return (c-'0');
+ else if ((c >= 'a')&&(c <= 'f'))
+ return (c-'a'+10);
+ else if ((c >= 'A')&&(c <= 'F'))
+ return (c-'A'+10);
+ else
+ return ((PKIX_UInt32)(-1));
+}
+
+/*
+ * FUNCTION: pkix_i2hex
+ * DESCRIPTION:
+ *
+ * Converts integer value "digit" to its ASCII hex value
+ *
+ * PARAMETERS
+ * "digit"
+ * Value of integer to convert to ASCII hex value. Must be 0-15.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The ASCII hexadecimal value of "digit".
+ */
+char
+pkix_i2hex(char digit)
+{
+ if ((digit >= 0)&&(digit <= 9))
+ return (digit+'0');
+ else if ((digit >= 0xa)&&(digit <= 0xf))
+ return (digit - 10 + 'a');
+ else
+ return (-1);
+}
+
+/*
+ * FUNCTION: pkix_isPlaintext
+ * DESCRIPTION:
+ *
+ * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
+ * depending on the value of "debug".
+ *
+ * In EscASCII, [01, 7E] except '&' are plaintext.
+ * In EscASCII_Debug [20, 7E] except '&' are plaintext.
+ *
+ * PARAMETERS:
+ * "c"
+ * Character to check.
+ * "debug"
+ * Value of debug flag.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * True if "c" is plaintext.
+ */
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
+ return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
+}
+
+/* --Cache-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
+ * and "anchors" as the hash keys. If there is no item to match the key,
+ * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
+ * compared to "testDate". If expired, the item is removed and PKIX_FALSE is
+ * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the
+ * BuildResult is stored at "pBuildResult".
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time validity and cache validity.
+ * May be NULL. If testDate is NULL, this cache item will not be out-dated.
+ * "pFound"
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pBuildResult"
+ * Address where BuildResult will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_Int32 cmpValidTimeResult = 0;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
+
+ *pFound = PKIX_FALSE;
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Lookup
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+
+ pkix_ccLookupCount++;
+
+ /* retrieve data from hashed value list */
+
+ if (cachedValues != NULL && cachedCertChainError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* check validity time and cache age time */
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &validityDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* if testDate is not set, this cache item is not out-dated */
+ if (testDate) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)validityDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ /* certs' date are all valid and cache item is not old */
+ if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 2,
+ (PKIX_PL_Object **) pBuildResult,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ pkix_ccRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* out-dated item, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(validityDate);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Remove
+ * DESCRIPTION:
+ *
+ * Remove CertChain Hash Table entry based on "targetCert" and "anchors"
+ * as the hash keys. If there is no item to match the key, no action is
+ * taken.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
+ PKIX_NULLCHECK_TWO(targetCert, anchors);
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+
+ pkix_ccRemoveCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Add
+ * DESCRIPTION:
+ *
+ * Add a BuildResult to the CertChain Hash Table for a "buildResult" with
+ * "targetCert" and "anchors" as the hash keys.
+ * "validityDate" is the most restricted notAfter date of all Certs in
+ * this CertChain and is verified when this BuildChain is retrieved.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "validityDate"
+ * Address of PKIX_PL_Date contains the most restriced notAfter time of
+ * all "certs". Must be non-NULL.
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "buildResult"
+ * Address of BuildResult to be cached. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (CACHE_ITEM_PERIOD_SECONDS,
+ &cacheValidUntilDate,
+ plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Add
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_ccAddCount++;
+
+ if (cachedCertChainError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Lookup
+ * DESCRIPTION:
+ *
+ * Look up Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and returns values Certs in "pCerts".
+ * If there isn't an item to match the key, a PKIX_FALSE is returned at
+ * "pFound". The item's cache time is verified with "testDate". If out-dated,
+ * this item is removed and PKIX_FALSE is returned at "pFound".
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time cache validity.
+ * Must be non-NULL. If testDate is NULL, this cache item won't be out
+ * dated.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCerts"
+ * Address PKIX_List where the CertChain will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCertList = NULL;
+ PKIX_List *selCertList = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_Date *invalidAfterDate = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_Error *selectorError = NULL;
+ PKIX_CertSelector_MatchCallback selectorMatch = NULL;
+ PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
+ PKIX_NULLCHECK_TWO(store, certSelParams);
+ PKIX_NULLCHECK_TWO(pFound, pCerts);
+
+ *pFound = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Lookup
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+ pkix_cLookupCount++;
+
+ if (cachedValues != NULL && cachedCertError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpCacheTimeResult <= 0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &cachedCertList,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Certs put on cache satifies only for Subject,
+ * user selector and ComCertSelParams to filter.
+ */
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (certSel, &selectorMatch, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * If any of the Cert on the list is out-dated, invalidate
+ * this cache item.
+ */
+ PKIX_CHECK(PKIX_List_GetLength
+ (cachedCertList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++){
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedCertList,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ (cert, &invalidAfterDate, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)invalidAfterDate,
+ (PKIX_PL_Object *)testDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpValidTimeResult < 0) {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* one cert is out-dated, remove item from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ goto cleanup;
+ }
+
+ selectorError = selectorMatch(certSel, cert, plContext);
+ if (!selectorError){
+ /* put on the return list */
+ PKIX_CHECK(PKIX_List_AppendItem
+ (selCertList,
+ (PKIX_PL_Object *)cert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ *pFound = PKIX_TRUE;
+ } else {
+ PKIX_DECREF(selectorError);
+ }
+
+ PKIX_DECREF(cert);
+ PKIX_DECREF(invalidAfterDate);
+
+ }
+
+ if (*pFound) {
+ PKIX_INCREF(selCertList);
+ *pCerts = selCertList;
+ }
+
+ } else {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+ /* cache item is out-dated, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(certSel);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(cachedCertList);
+ PKIX_DECREF(selCertList);
+ PKIX_DECREF(invalidAfterDate);
+ PKIX_DECREF(cachedCertError);
+ PKIX_DECREF(selectorError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Add
+ * DESCRIPTION:
+ *
+ * Add Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and have "certs" as the key value.
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "certs"
+ * Address PKIX_List of Certs will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCerts = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
+ PKIX_UInt32 numCerts = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
+ PKIX_NULLCHECK_THREE(store, certSelParams, certs);
+
+ PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (numCerts == 0) {
+ /* Don't want to add an empty list. */
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ if (trustCallback) {
+ cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
+ }
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (cachePeriod, &cacheValidUntilDate, plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DUPLICATE(certs, &cachedCerts, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cachedCerts,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Add
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_cAddCount++;
+
+ if (cachedCertError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedCerts);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cachedCertError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and returns values
+ * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCrls"
+ * Address PKIX_List where the CRLEntry will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedCrlEntryList = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_TWO(pFound, pCrls);
+
+ *pFound = PKIX_FALSE;
+
+ /* Find CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Lookup
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedCrlEntryList,
+ plContext);
+ pkix_ceLookupCount++;
+
+ /*
+ * We don't need check Date to invalidate this cache item,
+ * the item is uniquely defined and won't be reverted. Let
+ * the FIFO for cleaning up.
+ */
+
+ if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
+
+ PKIX_INCREF(cachedCrlEntryList);
+ *pCrls = cachedCrlEntryList;
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ *pFound = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryList);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Add
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
+ * the hash value. If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "crls"
+ * Address PKIX_List where the CRLEntry is stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_ONE(crls);
+
+ /* Add CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Add
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) crls,
+ plContext);
+ pkix_ceAddCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+
+/* TEST_START_FN and testStartFnStackPosition define at what state
+ * of the stack the object leak testing should begin. The condition
+ * in pkix_CheckForGeneratedError works the following way: do leak
+ * testing if at position testStartFnStackPosition in stack array
+ * (fnStackNameArr) we have called function TEST_START_FN.
+ * Note, that stack array get filled only when executing libpkix
+ * functions.
+ * */
+#define TEST_START_FN "PKIX_BuildChain"
+
+PKIX_Error*
+pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errSetFlag,
+ void * plContext)
+{
+ PKIX_Error *genErr = NULL;
+ PKIX_UInt32 pos = 0;
+ PKIX_UInt32 strLen = 0;
+
+ if (fnName) {
+ if (fnStackNameArr[testStartFnStackPosition] == NULL ||
+ strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN)
+ ) {
+ /* return with out error if not with in boundary */
+ return NULL;
+ }
+ if (!strcmp(fnName, TEST_START_FN)) {
+ *errSetFlag = PKIX_TRUE;
+ noErrorState = PKIX_FALSE;
+ errorGenerated = PKIX_FALSE;
+ }
+ }
+
+ if (noErrorState || errorGenerated) return NULL;
+
+ if (fnName && (
+ !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
+ !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
+ !strcmp(fnName, "pkix_UnlockObject") ||
+ !strcmp(fnName, "pkix_Throw") ||
+ !strcmp(fnName, "pkix_trace_dump_cert") ||
+ !strcmp(fnName, "PKIX_PL_Free"))) {
+ /* do not generate error for this functions */
+ noErrorState = PKIX_TRUE;
+ *errSetFlag = PKIX_TRUE;
+ return NULL;
+ }
+
+ if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
+ return NULL;
+ }
+
+ PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
+ errorGenerated = PKIX_TRUE;
+ noErrorState = PKIX_TRUE;
+ genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
+ errClass, plContext);
+ while(fnStackNameArr[pos]) {
+ strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1;
+ }
+ strLen += 1; /* end of line. */
+ pos = 0;
+ errorFnStackString = PORT_ZAlloc(strLen);
+ while(fnStackNameArr[pos]) {
+ strcat(errorFnStackString, "/");
+ strcat(errorFnStackString, fnStackNameArr[pos++]);
+ }
+ noErrorState = PKIX_FALSE;
+
+ return genErr;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
new file mode 100644
index 0000000000..5a8ef2741e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
@@ -0,0 +1,1588 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_tools.h
+ *
+ * Header for Utility Functions and Macros
+ *
+ */
+
+#ifndef _PKIX_TOOLS_H
+#define _PKIX_TOOLS_H
+
+#include "pkix.h"
+#include <stddef.h>
+#include <stdio.h>
+#include "secport.h"
+#include "prlong.h"
+
+/* private PKIX system headers */
+#include "pkix_basicconstraintschecker.h"
+#include "pkix_buildresult.h"
+#include "pkix_certchainchecker.h"
+#include "pkix_certselector.h"
+#include "pkix_comcertselparams.h"
+#include "pkix_comcrlselparams.h"
+#include "pkix_crlselector.h"
+#include "pkix_error.h"
+#include "pkix_expirationchecker.h"
+#include "pkix_list.h"
+#include "pkix_logger.h"
+#include "pkix_namechainingchecker.h"
+#include "pkix_nameconstraintschecker.h"
+#include "pkix_policychecker.h"
+#include "pkix_policynode.h"
+#include "pkix_procparams.h"
+#include "pkix_resourcelimits.h"
+#include "pkix_revocationmethod.h"
+#include "pkix_revocationchecker.h"
+#include "pkix_crlchecker.h"
+#include "pkix_ocspchecker.h"
+#include "pkix_signaturechecker.h"
+#include "pkix_store.h"
+#include "pkix_targetcertchecker.h"
+#include "pkix_validate.h"
+#include "pkix_valresult.h"
+#include "pkix_verifynode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkixStdVarsStr {
+ const char *aMyFuncName;
+ PKIX_Error *aPkixErrorResult;
+ PKIX_Error *aPkixTempResult;
+ PKIX_Error *aPkixReturnResult;
+ PKIX_ERRORCODE aPkixErrorCode;
+ PKIX_Boolean aPkixErrorReceived;
+ PKIX_Boolean aPkixTempErrorReceived;
+ PKIX_ERRORCLASS aPkixErrorClass;
+ PKIX_UInt32 aPkixType;
+ PKIX_PL_Object *aLockedObject;
+ PKIX_List *aPkixErrorList;
+} PKIX_StdVars;
+
+#ifdef PKIX_STDVARS_POINTER
+#define myFuncName stdVars->aMyFuncName
+#define pkixErrorResult stdVars->aPkixErrorResult
+#define pkixTempResult stdVars->aPkixTempResult
+#define pkixReturnResult stdVars->aPkixReturnResult
+#define pkixErrorCode stdVars->aPkixErrorCode
+#define pkixErrorReceived stdVars->aPkixErrorReceived
+#define pkixTempErrorReceived stdVars->aPkixTempErrorReceived
+#define pkixErrorClass stdVars->aPkixErrorClass
+#define pkixType stdVars->aPkixType
+#define lockedObject stdVars->aLockedObject
+#define pkixErrorList stdVars->aPkixErrorList
+#define stdVarsPtr stdVars
+#else
+#define myFuncName stdVars.aMyFuncName
+#define pkixErrorResult stdVars.aPkixErrorResult
+#define pkixTempResult stdVars.aPkixTempResult
+#define pkixReturnResult stdVars.aPkixReturnResult
+#define pkixErrorCode stdVars.aPkixErrorCode
+#define pkixErrorReceived stdVars.aPkixErrorReceived
+#define pkixTempErrorReceived stdVars.aPkixTempErrorReceived
+#define pkixErrorClass stdVars.aPkixErrorClass
+#define pkixType stdVars.aPkixType
+#define lockedObject stdVars.aLockedObject
+#define pkixErrorList stdVars.aPkixErrorList
+#define stdVarsPtr &stdVars
+#endif
+
+extern PKIX_Error * PKIX_DoReturn(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger,
+ void * plContext);
+
+extern PKIX_Error * PKIX_DoThrow(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode,
+ PKIX_ERRORCLASS overrideClass,
+ void * plContext);
+
+extern void PKIX_DoAddError(PKIX_StdVars * stdVars,
+ PKIX_Error * error,
+ void * plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errorStateSet,
+ void * plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+extern const PKIX_StdVars zeroStdVars;
+
+extern PRLogModuleInfo *pkixLog;
+
+/*
+ * UTILITY MACROS
+ * Documentation for these common utility macros can be found in the
+ * Implementation Guidelines document (Section 4.3)
+ *
+ * In general, macros with multiple statements (or a single "if" statement)
+ * use the "do {<body>} while (0)" technique in order to convert the multiple
+ * statements into one statement, thus avoiding the dangling else problem.
+ * For macros which ALWAYS exit with a "return" or "goto", there is no
+ * need to use this technique (and it yields compiler warnings of "statement
+ * not reached"), so we just use "{<body>}" to group the statements together.
+ */
+
+#if !defined (PKIX_OBJECT_LEAK_TEST)
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ myFuncName = cMyFuncName
+
+
+#else /* PKIX_OBJECT_LEAK_TEST */
+
+extern char **fnStackNameArr;
+extern PKIX_UInt32 *fnStackInvCountArr;
+extern PKIX_UInt32 stackPosition;
+extern PKIX_Boolean noErrorState;
+extern PKIX_Boolean errorGenerated;
+extern PKIX_Boolean runningLeakTest;
+extern PLHashTable *fnInvTable;
+extern PKIX_UInt32 testStartFnStackPosition;
+extern char *errorFnStackString;
+
+extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key);
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ PKIX_Boolean errorSetFlag = PKIX_FALSE; \
+ myFuncName = cMyFuncName; \
+ if (runningLeakTest) { \
+ if (fnStackNameArr) { \
+ fnStackInvCountArr[stackPosition] += 1; \
+ stackPosition += 1; \
+ fnStackInvCountArr[stackPosition] = 0; \
+ fnStackNameArr[stackPosition] = (char*)myFuncName; \
+ fnStackNameArr[stackPosition + 1] = NULL; \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ } \
+ do { \
+ pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \
+ funcName, &errorSetFlag, \
+ plContext); \
+ if (pkixErrorResult) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) { \
+ noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return pkixErrorResult; \
+ } \
+ } while (0); \
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+#ifdef DEBUG
+#define _PKIX_DEBUG_TRACE(cond, prefix, level) \
+ do { \
+ if (cond) { \
+ pkix_Logger_Check(pkixLoggersDebugTrace, myFuncName, \
+ prefix, pkixType, level, plContext); \
+ } \
+ } while (0)
+#else
+#define _PKIX_DEBUG_TRACE(cond, prefix, level)
+#endif
+
+#define _PKIX_LOG_ERROR(code, level) \
+ { \
+ if (pkixLoggersErrors) { \
+ pkix_Logger_CheckWithCode(pkixLoggersErrors, code, \
+ NULL, pkixType, level, plContext); \
+ } \
+ }
+
+#define PKIX_ENTER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type); \
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, ">>>", PKIX_LOGGER_LEVEL_TRACE);
+
+#define PKIX_ENTER_NO_LOGGER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type);
+
+#define PKIX_DEBUG_ENTER(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Entering %s).\n", myFuncName)
+
+#define PKIX_DEBUG_EXIT(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Exiting %s).\n", myFuncName)
+
+#define PKIX_OBJECT_UNLOCK(obj) \
+ do { \
+ if (obj && lockedObject == (PKIX_PL_Object *)(obj)){ \
+ pkixTempResult = \
+ PKIX_PL_Object_Unlock \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ lockedObject = NULL; \
+ } else { \
+ PORT_Assert(lockedObject == NULL); \
+ } \
+ } while (0)
+
+#define PKIX_DECREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_DecRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_THROW(type, descNum) \
+ return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \
+ pkixErrorClass, plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+#define PKIX_RETURN(type) \
+ if (runningLeakTest && fnStackNameArr) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#else
+#define PKIX_RETURN(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+#if defined(DEBUG) && !defined(DEBUG_nb95248)
+#define PKIX_RETURN_NO_LOGGER(type) \
+ { \
+ PKIX_OBJECT_UNLOCK(lockedObject); \
+ if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \
+ PKIX_THROW(type, pkixErrorCode); \
+ PKIX_DEBUG_EXIT(type); \
+ return NULL; \
+ }
+#else
+#define PKIX_RETURN_NO_LOGGER(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_FALSE, plContext);
+#endif
+
+/* disable to disable ;-) */
+/* #define WANT_TRACE_CHECK_FAILURES */
+
+#ifdef WANT_TRACE_CHECK_FAILURES
+#define TRACE_CHECK_FAILURE(what, errorstring) \
+ if (pkixLog) { \
+ PR_LOG(pkixLog, PR_LOG_DEBUG, \
+ ("====> [%s] failed: %s\n", #what, errorstring)); \
+ }
+#else
+#define TRACE_CHECK_FAILURE(what, errorstring)
+#endif
+
+#define PKIX_CHECK(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/* like PKIX_CHECK but without goto cleanup */
+#define PKIX_CHECK_NO_GOTO(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ } \
+ } while (0)
+
+#define PKIX_CHECK_ONLY_FATAL(func, descNum) \
+ do { \
+ pkixTempErrorReceived = PKIX_FALSE; \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixTempErrorReceived = PKIX_TRUE; \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ if (pkixErrorClass == PKIX_FATAL_ERROR) { \
+ goto cleanup; \
+ } \
+ PKIX_DECREF(pkixErrorResult); \
+ } \
+ } while (0)
+
+#define PKIX_LOG_ERROR(descNum) \
+ _PKIX_LOG_ERROR(descNum, PKIX_LOGGER_LEVEL_ERROR)
+
+#define PKIX_ERROR(descNum) \
+ { \
+ PKIX_LOG_ERROR(descNum) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_ALLOC_ERROR() \
+ { \
+ PKIX_LOG_ERROR(PKIX_ALLOCERROR) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorResult = PKIX_ALLOC_ERROR(); \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_FATAL(descNum) \
+ { \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto cleanup; \
+ }
+
+#define PKIX_CHECK_FATAL(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto fatal; \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_ONE(a) \
+ do { \
+ if ((a) == NULL){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_TWO(a, b) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_THREE(a, b, c) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || ((c) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_FOUR(a, b, c, d) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || \
+ ((c) == NULL) || ((d) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_OBJECT_LOCK(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = \
+ PKIX_PL_Object_Lock((PKIX_PL_Object*)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ pkixErrorCode = PKIX_OBJECTLOCKFAILED; \
+ goto cleanup; \
+ } \
+ lockedObject = (PKIX_PL_Object *)(obj); \
+ } \
+ } while (0)
+
+#define PKIX_ERROR_CREATE(type, descNum, error) \
+ { \
+ pkixTempResult = (PKIX_Error*)pkix_Throw \
+ (PKIX_ ## type ## _ERROR, myFuncName, \
+ descNum, PKIX_ ## type ## _ERROR, pkixErrorResult, \
+ &error, plContext); \
+ if (pkixTempResult) { \
+ error = pkixTempResult; \
+ pkixTempResult = NULL; \
+ } \
+ }
+
+
+#define PKIX_ERROR_RECEIVED \
+ (pkixErrorReceived || pkixErrorResult || pkixTempErrorReceived || \
+ pkixErrorList)
+
+#define PKIX_INCREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_IncRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ goto cleanup; \
+ } \
+ } \
+ } while (0)
+
+#define PKIX_FREE(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = PKIX_PL_Free((obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_EXACTLY_ONE_NULL(a, b) (((a) && !(b)) || ((b) && !(a)))
+
+/* DIGIT MACROS */
+
+#define PKIX_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
+
+#define PKIX_ISXDIGIT(c) \
+ (PKIX_ISDIGIT(c) || ( (((c)|0x20) >= 'a') && (((c)|0x20) <= 'f') ))
+
+#define PKIX_TOSTRING(a, b, c, d) \
+ do { \
+ int descNum; \
+ if ((a) != NULL) { \
+ pkixErrorResult = \
+ PKIX_PL_Object_ToString((PKIX_PL_Object *)(a), (b), (c)); \
+ descNum = (d); \
+ } else { \
+ pkixErrorResult = \
+ PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, (b), (c)); \
+ descNum = PKIX_STRINGCREATEFAILED; \
+ } \
+ PKIX_CHECK(pkixErrorResult, descNum); \
+ } while (0)
+
+#define PKIX_EQUALS(a, b, c, d, e) \
+ do { \
+ if ((a) != NULL && (b) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Equals\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object*)(b), \
+ (c), \
+ (d)), \
+ (e)); \
+ } else if ((a) == NULL && (b) == NULL) { \
+ *(c) = PKIX_TRUE; \
+ } else { \
+ *(c) = PKIX_FALSE; \
+ } \
+ } while (0)
+
+#define PKIX_HASHCODE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Hashcode\
+ ((PKIX_PL_Object *)(a), (b), (c)), (d)); \
+ } else { \
+ *(b) = 0; \
+ } \
+ } while (0)
+
+#define PKIX_DUPLICATE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Duplicate\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object **)(b), \
+ (c)), \
+ (d)); \
+ } else { \
+ *(b) = (a); \
+ } \
+ } while (0)
+
+/*
+ * DEBUG MACROS
+ *
+ * Each type has an associated debug flag, which can
+ * be set on the compiler line using "-D<debugflag>". For convenience,
+ * "-DPKIX_DEBUGALL" turns on debug for all the components.
+ *
+ * If a type's debug flag is defined, then its two associated macros
+ * are defined: PKIX_type_DEBUG(expr) and PKIX_type_DEBUG_ARG(expr, arg),
+ * which call PKIX_DEBUG(expr) and PKIX_DEBUG_ARG(expr, arg) respectively,
+ * which, in turn, enable standard and consistently formatted output.
+ *
+ * If a type's debug flag is not defined, the two associated macros
+ * are defined as a NO-OP. As such, any PKIX_type_DEBUG or PKIX_type_DEBUG_ARG
+ * macros for an undefined type will be stripped from the code during
+ * pre-processing, thereby reducing code size.
+ */
+
+#ifdef PKIX_DEBUGALL
+#define PKIX_REFCOUNTDEBUG 1
+#define PKIX_MEMDEBUG 1
+#define PKIX_MUTEXDEBUG 1
+#define PKIX_OBJECTDEBUG 1
+#define PKIX_STRINGDEBUG 1
+#define PKIX_OIDDEBUG 1
+#define PKIX_LISTDEBUG 1
+#define PKIX_ERRORDEBUG 1
+#define PKIX_BYTEARRAYDEBUG 1
+#define PKIX_RWLOCKDEBUG 1
+#define PKIX_BIGINTDEBUG 1
+#define PKIX_HASHTABLEDEBUG 1
+#define PKIX_X500NAMEDEBUG 1
+#define PKIX_GENERALNAMEDEBUG 1
+#define PKIX_PUBLICKEYDEBUG 1
+#define PKIX_CERTDEBUG 1
+#define PKIX_HTTPCLIENTDEBUG 1
+#define PKIX_DATEDEBUG 1
+#define PKIX_TRUSTANCHORDEBUG 1
+#define PKIX_PROCESSINGPARAMSDEBUG 1
+#define PKIX_VALIDATEPARAMSDEBUG 1
+#define PKIX_VALIDATERESULTDEBUG 1
+#define PKIX_VALIDATEDEBUG 1
+#define PKIX_CERTCHAINCHECKERDEBUG 1
+#define PKIX_REVOCATIONCHECKERDEBUG 1
+#define PKIX_CERTSELECTORDEBUG 1
+#define PKIX_COMCERTSELPARAMSDEBUG 1
+#define PKIX_TARGETCERTCHECKERSTATEDEBUG 1
+#define PKIX_INITIALIZEPARAMSDEBUG 1
+#define PKIX_CERTBASICCONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_SUBJALTNAMECHECKERSTATEDEBUG 1
+
+#define PKIX_CERTPOLICYQUALIFIERDEBUG 1
+#define PKIX_CERTPOLICYINFODEBUG 1
+#define PKIX_CERTPOLICYNODEDEBUG 1
+#define PKIX_CERTPOLICYCHECKERSTATEDEBUG 1
+#define PKIX_LIFECYCLEDEBUG 1
+#define PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_CRLDEBUG 1
+#define PKIX_CRLENTRYDEBUG 1
+#define PKIX_CRLSELECTORDEBUG 1
+#define PKIX_COMCRLSELPARAMSDEBUG 1
+#define PKIX_CERTSTOREDEBUG 1
+#define PKIX_COLLECTIONCERTSTORECONTEXTDEBUG 1
+#define PKIX_DEFAULTCRLCHECKERSTATEDEBUG 1
+#define PKIX_CERTPOLICYMAPDEBUG 1
+#define PKIX_BUILDDEBUG 1
+#define PKIX_BUILDRESULTDEBUG 1
+#define PKIX_FORWARDBUILDERSTATEDEBUG 1
+#define PKIX_SIGNATURECHECKERSTATEDEBUG 1
+#define PKIX_USERDEFINEDMODULESDEBUG 1
+#define PKIX_CONTEXTDEBUG 1
+#define PKIX_DEFAULTREVOCATIONCHECKERDEBUG 1
+#define PKIX_LDAPREQUESTDEBUG 1
+#define PKIX_LDAPRESPONSEDEBUG 1
+#define PKIX_LDAPCLIENTDEBUG 1
+#define PKIX_LDAPDEFAULTCLIENTDEBUG 1
+#define PKIX_SOCKETDEBUG 1
+#define PKIX_RESOURCELIMITSDEBUG 1
+#define PKIX_LOGGERDEBUG 1
+#define PKIX_MONITORLOCKDEBUG 1
+#define PKIX_INFOACCESSDEBUG 1
+#define PKIX_AIAMGRDEBUG 1
+#define PKIX_OCSPCHECKERDEBUG 1
+#define PKIX_OCSPREQUESTDEBUG 1
+#define PKIX_OCSPRESPONSEDEBUG 1
+#define PKIX_HTTPDEFAULTCLIENTDEBUG 1
+#define PKIX_HTTPCERTSTORECONTEXTDEBUG 1
+#define PKIX_VERIFYNODEDEBUG 1
+#endif
+
+/*
+ * XXX Both PKIX_DEBUG and PKIX_DEBUG_ARG currently use printf.
+ * This needs to be replaced with Loggers.
+ */
+
+#ifdef DEBUG
+#define PKIX_DEBUG(expr) \
+ do { \
+ _PKIX_DEBUG_TRACE(pkixLoggersErrors, expr, PKIX_LOGGER_LEVEL_DEBUG); \
+ (void) fprintf(stderr, "(%s: ", myFuncName); \
+ (void) fprintf(stderr, expr); \
+ } while (0)
+#else
+#define PKIX_DEBUG(expr)
+#endif
+
+/* Logging doesn't support DEBUG with ARG: cannot convert control and arg */
+#define PKIX_DEBUG_ARG(expr, arg) \
+ do { \
+ (void) printf("(%s: ", myFuncName); \
+ (void) printf(expr, arg); \
+ } while (0)
+
+#if PKIX_FATALDEBUG
+#define PKIX_FATAL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FATAL_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REFCOUNTDEBUG
+#define PKIX_REF_COUNT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REF_COUNT_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MEMDEBUG
+#define PKIX_MEM_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MEM_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MUTEXDEBUG
+#define PKIX_MUTEX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MUTEX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OBJECTDEBUG
+#define PKIX_OBJECT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OBJECT_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_ERRORDEBUG
+#define PKIX_ERROR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_ERROR_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_STRINGDEBUG
+#define PKIX_STRING_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_STRING_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OIDDEBUG
+#define PKIX_OID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OID_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LISTDEBUG
+#define PKIX_LIST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIST_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RWLOCKDEBUG
+#define PKIX_RWLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RWLOCK_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BYTEARRAYDEBUG
+#define PKIX_BYTEARRAY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BYTEARRAY_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HASHTABLEDEBUG
+#define PKIX_HASHTABLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HASHTABLE_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_X500NAMEDEBUG
+#define PKIX_X500NAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_X500NAME_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_GENERALNAMEDEBUG
+#define PKIX_GENERALNAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_GENERALNAME_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PUBLICKEYDEBUG
+#define PKIX_PUBLICKEY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PUBLICKEY_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTDEBUG
+#define PKIX_CERT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERT_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDPDEBUG
+#define PKIX_CRLDP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLDP_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCLIENTDEBUG
+#define PKIX_HTTPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCLIENT_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BIGINTDEBUG
+#define PKIX_BIGINT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BIGINT_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_DATEDEBUG
+#define PKIX_DATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_DATE_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TRUSTANCHORDEBUG
+#define PKIX_TRUSTANCHOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TRUSTANCHOR_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PROCESSINGPARAMSDEBUG
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEPARAMSDEBUG
+#define PKIX_VALIDATEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATEPARAMS_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATERESULTDEBUG
+#define PKIX_VALIDATERESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATERESULT_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEDEBUG
+#define PKIX_VALIDATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATE_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDDEBUG
+#define PKIX_BUILD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILD_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTCHAINCHECKERDEBUG
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONMETHODDEBUG
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSELECTORDEBUG
+#define PKIX_CERTSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSELECTOR_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCERTSELPARAMSDEBUG
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TARGETCERTCHECKERSTATEDEBUG
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INITIALIZEPARAMSDEBUG
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTBASICCONSTRAINTSDEBUG
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSDEBUG
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SUBJALTNAMECHECKERSTATEDEBUG
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYQUALIFIERDEBUG
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYINFODEBUG
+#define PKIX_CERTPOLICYINFO_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYINFO_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYNODEDEBUG
+#define PKIX_CERTPOLICYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYNODE_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LIFECYCLEDEBUG
+#define PKIX_LIFECYCLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIFECYCLE_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDEBUG
+#define PKIX_CRL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRL_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLENTRYDEBUG
+#define PKIX_CRLENTRY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLENTRY_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLSELECTORDEBUG
+#define PKIX_CRLSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLSELECTOR_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCRLSELPARAMSDEBUG
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSTOREDEBUG
+#define PKIX_CERTSTORE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSTORE_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COLLECTIONCERTSTORECONTEXTDEBUG
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLCHECKERDEBUG
+#define PKIX_CRLCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLCHECKER_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYMAPDEBUG
+#define PKIX_CERTPOLICYMAP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYMAP_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDRESULTDEBUG
+#define PKIX_BUILDRESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILDRESULT_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SIGNATURECHECKERSTATEDEBUG
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_USERDEFINEDMODULESDEBUG
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CONTEXTDEBUG
+#define PKIX_CONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CONTEXT_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPREQUESTDEBUG
+#define PKIX_LDAPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPREQUEST_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPRESPONSEDEBUG
+#define PKIX_LDAPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPRESPONSE_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPCLIENTDEBUG
+#define PKIX_LDAPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPCLIENT_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPDEFAULTCLIENTDEBUG
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SOCKETDEBUG
+#define PKIX_SOCKET_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SOCKET_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RESOURCELIMITSDEBUG
+#define PKIX_RESOURCELIMITS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RESOURCELIMITS_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LOGGERDEBUG
+#define PKIX_LOGGER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LOGGER_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MONITORLOCKDEBUG
+#define PKIX_MONITORLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MONITORLOCK_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INFOACCESSDEBUG
+#define PKIX_INFOACCESS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INFOACCESS_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_AIAMGRDEBUG
+#define PKIX_AIAMGR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_AIAMGR_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCHECKERDEBUG
+#define PKIX_OCSPCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCHECKER_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCERTIDDEBUG
+#define PKIX_OCSPCERTID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCERTID_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPREQUESTDEBUG
+#define PKIX_OCSPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPREQUEST_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPRESPONSEDEBUG
+#define PKIX_OCSPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPRESPONSE_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPDEFAULTCLIENTDEBUG
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCERTSTORECONTEXTDEBUG
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VERIFYNODEDEBUG
+#define PKIX_VERIFYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VERIFYNODE_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_EKUCHECKER
+#define PKIX_EKUCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_EKUCHECKER_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTVFYPKIXDEBUG
+#define PKIX_CERTVFYPKIX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTVFYPKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg)
+#endif
+
+/*
+ * All object types register themselves with the system using a
+ * pkix_ClassTable_Entry, which consists of a set of functions for that
+ * type and an ASCII string (char *) which is used by the default
+ * ToStringCallback (if necessary). System types register themselves directly
+ * when their respective PKIX_"type"_RegisterSelf functions are called.
+ * User-defined types can be registered using PKIX_PL_Object_RegisterType.
+ * (see comments in pkix_pl_system.h)
+ */
+
+typedef struct pkix_ClassTable_EntryStruct pkix_ClassTable_Entry;
+struct pkix_ClassTable_EntryStruct {
+ char *description;
+ PKIX_UInt32 objCounter;
+ PKIX_UInt32 typeObjectSize;
+ PKIX_PL_DestructorCallback destructor;
+ PKIX_PL_EqualsCallback equalsFunction;
+ PKIX_PL_HashcodeCallback hashcodeFunction;
+ PKIX_PL_ToStringCallback toStringFunction;
+ PKIX_PL_ComparatorCallback comparator;
+ PKIX_PL_DuplicateCallback duplicateFunction;
+};
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error code. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ */
+extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES];
+
+#define MAX_STACK_DEPTH 1000
+
+extern PRLogModuleInfo *pkixLog;
+
+#define PKIX_MAGIC_HEADER PR_UINT64(0xFEEDC0FFEEFACADE)
+#define PKIX_MAGIC_HEADER_DESTROYED PR_UINT64(0xBAADF00DDEADBEEF)
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext);
+
+PKIX_Error *
+pkix_Throw(
+ PKIX_ERRORCLASS errClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorTextCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *hash,
+ void *plContext);
+
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext);
+
+PKIX_UInt32
+pkix_countArray(void **array);
+
+PKIX_UInt32
+pkix_hex2i(char c);
+
+char
+pkix_i2hex(char c);
+
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug);
+
+PKIX_Error *
+pkix_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrlEntryList,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crlEntryList,
+ void *plContext);
+
+#ifdef PR_LOGGING
+void
+pkix_trace_dump_cert(
+ const char *info,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TOOLS_H */
diff --git a/security/nss/lib/libpkix/pkix/util/util.gyp b/security/nss/lib/libpkix/pkix/util/util.gyp
new file mode 100644
index 0000000000..078852f52b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/util.gyp
@@ -0,0 +1,27 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixutil',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_error.c',
+ 'pkix_errpaths.c',
+ 'pkix_list.c',
+ 'pkix_logger.c',
+ 'pkix_tools.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file