summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/system
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/system')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/Makefile47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp37
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn43
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c398
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h40
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c504
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h40
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c1073
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h159
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c26
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c383
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h29
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c279
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h91
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c168
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h24
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c136
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h33
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c163
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h33
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c1440
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h76
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c316
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h39
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c584
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h102
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c217
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h35
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c628
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h37
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp36
31 files changed, 7216 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile
new file mode 100644
index 0000000000..2b4b1574ab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile
@@ -0,0 +1,47 @@
+#! 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_pl_nss/system/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
new file mode 100644
index 0000000000..a2f759441e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
@@ -0,0 +1,37 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_pl_nss_system_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_pl_bigint.h',
+ 'pkix_pl_bytearray.h',
+ 'pkix_pl_common.h',
+ 'pkix_pl_hashtable.h',
+ 'pkix_pl_lifecycle.h',
+ 'pkix_pl_mem.h',
+ 'pkix_pl_monitorlock.h',
+ 'pkix_pl_mutex.h',
+ 'pkix_pl_object.h',
+ 'pkix_pl_oid.h',
+ 'pkix_pl_primhash.h',
+ 'pkix_pl_rwlock.h',
+ 'pkix_pl_string.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn
new file mode 100644
index 0000000000..a143a03eed
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn
@@ -0,0 +1,43 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_pl_common.h \
+ pkix_pl_mem.h \
+ pkix_pl_object.h \
+ pkix_pl_string.h \
+ pkix_pl_primhash.h \
+ pkix_pl_bigint.h \
+ pkix_pl_mutex.h \
+ pkix_pl_bytearray.h \
+ pkix_pl_lifecycle.h \
+ pkix_pl_oid.h \
+ pkix_pl_hashtable.h \
+ pkix_pl_rwlock.h \
+ pkix_pl_monitorlock.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_pl_bigint.c \
+ pkix_pl_bytearray.c \
+ pkix_pl_common.c \
+ pkix_pl_error.c \
+ pkix_pl_hashtable.c \
+ pkix_pl_lifecycle.c \
+ pkix_pl_mem.c \
+ pkix_pl_monitorlock.c \
+ pkix_pl_mutex.c \
+ pkix_pl_object.c \
+ pkix_pl_oid.c \
+ pkix_pl_primhash.c \
+ pkix_pl_rwlock.c \
+ pkix_pl_string.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixsystem
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c
new file mode 100644
index 0000000000..cd8e15ee4b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c
@@ -0,0 +1,398 @@
+/* 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_pl_bigint.c
+ *
+ * BigInt Object Functions
+ *
+ */
+
+#include "pkix_pl_bigint.h"
+
+/* --Private-Big-Int-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_BigInt *firstBigInt = NULL;
+ PKIX_PL_BigInt *secondBigInt = NULL;
+ char *firstPtr = NULL;
+ char *secondPtr = NULL;
+ PKIX_UInt32 firstLen, secondLen;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
+ PKIX_ARGUMENTSNOTBIGINTS);
+
+ /* It's safe to cast */
+ firstBigInt = (PKIX_PL_BigInt*)firstObject;
+ secondBigInt = (PKIX_PL_BigInt*)secondObject;
+
+ *pResult = 0;
+ firstPtr = firstBigInt->dataRep;
+ secondPtr = secondBigInt->dataRep;
+ firstLen = firstBigInt->length;
+ secondLen = secondBigInt->length;
+
+ if (firstLen < secondLen) {
+ *pResult = -1;
+ } else if (firstLen > secondLen) {
+ *pResult = 1;
+ } else if (firstLen == secondLen) {
+ PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
+ *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen);
+ }
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ PKIX_FREE(bigInt->dataRep);
+ bigInt->dataRep = NULL;
+ bigInt->length = 0;
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_BigInt_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+ char *outputText = NULL;
+ PKIX_UInt32 i, j, lengthChars;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ /* number of chars = 2 * (number of bytes) + null terminator */
+ lengthChars = (bigInt->length * 2) + 1;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (lengthChars, (void **)&outputText, plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){
+ outputText[j] = pkix_i2hex
+ ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4));
+ outputText[j+1] = pkix_i2hex
+ ((char) (*(bigInt->dataRep+i) & 0x0f));
+ }
+
+ outputText[lengthChars-1] = '\0';
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ outputText,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_FREE(outputText);
+
+ PKIX_RETURN(BIGINT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((void *)bigInt->dataRep,
+ bigInt->length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTBIGINT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
+
+ PKIX_CHECK(pkix_pl_BigInt_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_BIGINTCOMPARATORFAILED);
+
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BIGINT_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_pl_BigInt_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
+
+ entry.description = "BigInt";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_BigInt);
+ entry.destructor = pkix_pl_BigInt_Destroy;
+ entry.equalsFunction = pkix_pl_BigInt_Equals;
+ entry.hashcodeFunction = pkix_pl_BigInt_Hashcode;
+ entry.toStringFunction = pkix_pl_BigInt_ToString;
+ entry.comparator = pkix_pl_BigInt_Comparator;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BIGINT_TYPE] = entry;
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_CreateWithBytes
+ * DESCRIPTION:
+ *
+ * Creates a new BigInt of size "length" representing the array of bytes
+ * pointed to by "bytes" and stores it at "pBigInt". The caller should make
+ * sure that the first byte is not 0x00 (unless it is the the only byte).
+ * This function does not do that checking.
+ *
+ * Once created, a PKIX_PL_BigInt object is immutable.
+ *
+ * PARAMETERS:
+ * "bytes"
+ * Address of array of bytes. Must be non-NULL.
+ * "length"
+ * Length of the array. Must be non-zero.
+ * "pBigInt"
+ * 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_pl_BigInt_CreateWithBytes(
+ char *bytes,
+ PKIX_UInt32 length,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
+ PKIX_NULLCHECK_TWO(pBigInt, bytes);
+
+ if (length == 0) {
+ PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BIGINT_TYPE,
+ sizeof (PKIX_PL_BigInt),
+ (PKIX_PL_Object **)&bigInt,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (length, (void **)&(bigInt->dataRep), plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
+
+ bigInt->length = length;
+
+ *pBigInt = bigInt;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(bigInt);
+ }
+
+ PKIX_RETURN(BIGINT);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_BigInt_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 lengthBytes;
+ PKIX_UInt32 lengthString;
+ PKIX_UInt32 i;
+ char currChar;
+
+ PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
+ PKIX_NULLCHECK_TWO(pBigInt, stringRep);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &lengthString,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ if ((lengthString == 0) || ((lengthString % 2) != 0)){
+ PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
+ }
+
+ if (lengthString != 2){
+ if ((asciiString[0] == '0') && (asciiString[1] == '0')){
+ PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
+ }
+ }
+
+ for (i = 0; i < lengthString; i++) {
+ currChar = asciiString[i];
+ if (!PKIX_ISXDIGIT(currChar)){
+ PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BIGINT_TYPE,
+ sizeof (PKIX_PL_BigInt),
+ (PKIX_PL_Object **)&bigInt,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* number of bytes = 0.5 * (number of chars) */
+ lengthBytes = lengthString/2;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (lengthBytes, (void **)&(bigInt->dataRep), plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < lengthString; i += 2){
+ (bigInt->dataRep)[i/2] =
+ (pkix_hex2i(asciiString[i])<<4) |
+ pkix_hex2i(asciiString[i+1]);
+ }
+
+ bigInt->length = lengthBytes;
+
+ *pBigInt = bigInt;
+
+cleanup:
+
+ PKIX_FREE(asciiString);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(bigInt);
+ }
+
+ PKIX_RETURN(BIGINT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h
new file mode 100644
index 0000000000..b3df808a8d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_bigint.h
+ *
+ * Bigint Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BIGINT_H
+#define _PKIX_PL_BIGINT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_BigIntStruct {
+ char *dataRep;
+ PKIX_UInt32 length;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_BigInt_CreateWithBytes(
+ char *bytes,
+ PKIX_UInt32 length,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext);
+
+PKIX_Error *pkix_pl_BigInt_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BIGINT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c
new file mode 100644
index 0000000000..0a2e9c08f3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c
@@ -0,0 +1,504 @@
+/* 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_pl_bytearray.c
+ *
+ * ByteArray Object Functions
+ *
+ */
+
+#include "pkix_pl_bytearray.h"
+
+/* --Private-ByteArray-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_ToHexString
+ * DESCRIPTION:
+ *
+ * Creates a hex-String representation of the ByteArray pointed to by "array"
+ * and stores the result at "pString". The hex-String consists of hex-digit
+ * pairs separated by spaces, and the entire string enclosed within square
+ * brackets, e.g. [43 61 6E 20 79 6F 75 20 72 65 61 64 20 74 68 69 73 3F].
+ * A zero-length ByteArray is represented as [].
+ * PARAMETERS
+ * "array"
+ * ByteArray to be represented by the hex-String; must be non-NULL
+ * "pString"
+ * Address where String 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_pl_ByteArray_ToHexString(
+ PKIX_PL_ByteArray *array,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *tempText = NULL;
+ char *stringText = NULL; /* "[XX XX XX ...]" */
+ PKIX_UInt32 i, outputLen, bufferSize;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToHexString");
+ PKIX_NULLCHECK_TWO(array, pString);
+
+ if ((array->length) == 0) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "[]", 0, pString, plContext),
+ PKIX_COULDNOTCREATESTRING);
+ } else {
+ /*
+ * Allocate space for format string
+ * '[' + "XX" + (n-1)*" XX" + ']' + '\0'
+ */
+ bufferSize = 2 + (3*(array->length));
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (bufferSize, (void **)&stringText, plContext),
+ PKIX_COULDNOTALLOCATEMEMORY);
+
+ stringText[0] = 0;
+ outputLen = 0;
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ ("[%02X", (0x0FF&((char *)(array->array))[0]));
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+
+ for (i = 1; i < array->length; i++) {
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ (" %02X", (0x0FF&((char *)(array->array))[i]));
+
+ if (tempText == NULL){
+ PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
+ }
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+ tempText = NULL;
+ }
+
+ stringText[outputLen++] = ']';
+ stringText[outputLen] = 0;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ stringText,
+ 0,
+ pString,
+ plContext),
+ PKIX_COULDNOTCREATESTRING);
+ }
+
+cleanup:
+
+ PKIX_FREE(stringText);
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ *
+ * NOTE:
+ * It is not clear that this definition of comparing byte arrays makes
+ * sense. It does allow you to tell whether two blocks of memory are
+ * identical, so we only use it for the Equals function (i.e. we don't
+ * register it as a Compare function for ByteArray).
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *firstByteArray = NULL;
+ PKIX_PL_ByteArray *secondByteArray = NULL;
+ unsigned char *firstData = NULL;
+ unsigned char *secondData = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_ARGUMENTSNOTBYTEARRAYS);
+
+ /* It's safe to cast */
+ firstByteArray = (PKIX_PL_ByteArray *)firstObject;
+ secondByteArray = (PKIX_PL_ByteArray *)secondObject;
+
+ *pResult = 0;
+ firstData = (unsigned char *)firstByteArray->array;
+ secondData = (unsigned char *)secondByteArray->array;
+
+ if (firstByteArray->length < secondByteArray->length) {
+ *pResult = -1;
+ } else if (firstByteArray->length > secondByteArray->length) {
+ *pResult = 1;
+ } else if (firstByteArray->length == secondByteArray->length) {
+ /* Check if both array contents are identical */
+ for (i = 0;
+ (i < firstByteArray->length) && (*pResult == 0);
+ i++) {
+ if (firstData[i] < secondData[i]) {
+ *pResult = -1;
+ } else if (firstData[i] > secondData[i]) {
+ *pResult = 1;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+ char *tempText = NULL;
+ char *stringText = NULL; /* "[OOO, OOO, ... OOO]" */
+ PKIX_UInt32 i, outputLen, bufferSize;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray *)object;
+
+ if ((array->length) == 0) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "[]", 0, pString, plContext),
+ PKIX_COULDNOTCREATESTRING);
+ } else {
+ /* Allocate space for "XXX, ". */
+ bufferSize = 2+5*array->length;
+
+ /* Allocate space for format string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (bufferSize, (void **)&stringText, plContext),
+ PKIX_MALLOCFAILED);
+
+ stringText[0] = 0;
+ outputLen = 0;
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText =
+ PR_smprintf
+ ("[%03u", (0x0FF&((char *)(array->array))[0]));
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+
+ for (i = 1; i < array->length; i++) {
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ (", %03u",
+ (0x0FF&((char *)(array->array))[i]));
+
+ if (tempText == NULL){
+ PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
+ }
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+ tempText = NULL;
+ }
+
+ stringText[outputLen++] = ']';
+ stringText[outputLen] = 0;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, stringText, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ }
+
+cleanup:
+
+ PKIX_FREE(stringText);
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* Sanity check: Test that "first" is a ByteArray */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_FIRSTARGUMENTNOTBYTEARRAY);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ /* If types differ, then we will return false */
+ *pResult = PKIX_FALSE;
+
+ /* Second type may not be a BA */
+ if (secondType != PKIX_BYTEARRAY_TYPE) goto cleanup;
+
+ /* It's safe to cast here */
+ PKIX_CHECK(pkix_pl_ByteArray_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_BYTEARRAYCOMPARATORFAILED);
+
+ /* ByteArrays are equal iff Comparator Result is 0 */
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray*)object;
+
+ PKIX_FREE(array->array);
+ array->array = NULL;
+ array->length = 0;
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)array->array,
+ array->length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BYTEARRAY_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_pl_ByteArray_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_RegisterSelf");
+
+ entry.description = "ByteArray";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_ByteArray);
+ entry.destructor = pkix_pl_ByteArray_Destroy;
+ entry.equalsFunction = pkix_pl_ByteArray_Equals;
+ entry.hashcodeFunction = pkix_pl_ByteArray_Hashcode;
+ entry.toStringFunction = pkix_pl_ByteArray_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BYTEARRAY_TYPE] = entry;
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_Create(
+ void *array,
+ PKIX_UInt32 length,
+ PKIX_PL_ByteArray **pByteArray,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_Create");
+ PKIX_NULLCHECK_ONE(pByteArray);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BYTEARRAY_TYPE,
+ sizeof (PKIX_PL_ByteArray),
+ (PKIX_PL_Object **)&byteArray,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECTSTORAGE);
+
+ byteArray->length = length;
+ byteArray->array = NULL;
+
+ if (length != 0){
+ /* Alloc space for array */
+ PKIX_NULLCHECK_ONE(array);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (length, (void**)&(byteArray->array), plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(byteArray->array, array, length);
+ }
+
+ *pByteArray = byteArray;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(byteArray);
+ }
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetPointer (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetPointer(
+ PKIX_PL_ByteArray *byteArray,
+ void **pArray,
+ void *plContext)
+{
+ void *bytes = NULL;
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetPointer");
+ PKIX_NULLCHECK_TWO(byteArray, pArray);
+
+ if (byteArray->length != 0){
+ PKIX_CHECK(PKIX_PL_Malloc
+ (byteArray->length, &bytes, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy
+ (bytes, byteArray->array, byteArray->length);
+ }
+
+ *pArray = bytes;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(bytes);
+ }
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetLength (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetLength(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetLength");
+ PKIX_NULLCHECK_TWO(byteArray, pLength);
+
+ *pLength = byteArray->length;
+
+ PKIX_RETURN(BYTEARRAY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h
new file mode 100644
index 0000000000..4ba18eed74
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h
@@ -0,0 +1,40 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_bytearray.h
+ *
+ * ByteArray Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BYTEARRAY_H
+#define _PKIX_PL_BYTEARRAY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_ByteArrayStruct {
+ void *array;
+ PKIX_UInt32 length;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_ByteArray_ToHexString(
+ PKIX_PL_ByteArray *array,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_ByteArray_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BYTEARRAY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c
new file mode 100644
index 0000000000..831ce538d3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c
@@ -0,0 +1,1073 @@
+/* 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_common.c
+ *
+ * Common utility functions used by various PKIX_PL functions
+ *
+ */
+
+#include "pkix_pl_common.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_LockObject
+ * DESCRIPTION:
+ *
+ * Locks the object pointed to by "object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of object. 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_LockObject(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader;
+
+ PKIX_ENTER(OBJECT, "pkix_LockObject");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+
+ objectHeader = object-1;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(objectHeader->lock);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_UnlockObject
+ * DESCRIPTION:
+ *
+ * Unlocks the object pointed to by "object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object. 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_UnlockObject(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader;
+ PRStatus result;
+
+ PKIX_ENTER(OBJECT, "pkix_UnlockObject");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+
+ objectHeader = object-1;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ result = PR_Unlock(objectHeader->lock);
+
+ if (result == PR_FAILURE) {
+ PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n");
+ PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_UInt32_Overflows
+ * DESCRIPTION:
+ *
+ * Returns a PKIX_Boolean indicating whether the unsigned integer
+ * represented by "string" is too large to fit in 32-bits (i.e.
+ * whether it overflows). With the exception of the string "0",
+ * all other strings are stripped of any leading zeros. It is assumed
+ * that every character in "string" is from the set {'0' - '9'}.
+ *
+ * PARAMETERS
+ * "string"
+ * Address of array of bytes representing PKIX_UInt32 that's being tested
+ * for 32-bit overflow
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * PKIX_TRUE if PKIX_UInt32 represented by "string" overflows;
+ * PKIX_FALSE otherwise
+ */
+PKIX_Boolean
+pkix_pl_UInt32_Overflows(char *string){
+ char *firstNonZero = NULL;
+ PKIX_UInt32 length, i;
+ char *MAX_UINT32_STRING = "4294967295";
+
+ PKIX_DEBUG_ENTER(OID);
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ length = PL_strlen(string);
+
+ if (length < MAX_DIGITS_32){
+ return (PKIX_FALSE);
+ }
+
+ firstNonZero = string;
+ for (i = 0; i < length; i++){
+ if (*string == '0'){
+ firstNonZero++;
+ }
+ }
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ length = PL_strlen(firstNonZero);
+
+ if (length > MAX_DIGITS_32){
+ return (PKIX_TRUE);
+ }
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ if (length == MAX_DIGITS_32){
+ PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
+ if (PORT_Strcmp(firstNonZero, MAX_UINT32_STRING) > 0){
+ return (PKIX_TRUE);
+ }
+ }
+
+ return (PKIX_FALSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_getOIDToken
+ * DESCRIPTION:
+ *
+ * Takes the array of DER-encoded bytes pointed to by "derBytes"
+ * (representing an OID) and the value of "index" representing the index into
+ * the array, and decodes the bytes until an integer token is retrieved. If
+ * successful, this function stores the integer component at "pToken" and
+ * stores the index representing the next byte in the array at "pIndex"
+ * (following the last byte that was used in the decoding). This new output
+ * index can be used in subsequent calls as an input index, allowing each
+ * token of the OID to be retrieved consecutively. Note that there is a
+ * special case for the first byte, in that it encodes two separate integer
+ * tokens. For example, the byte {2a} represents the integer tokens {1,2}.
+ * This special case is not handled here and must be handled by the caller.
+ *
+ * PARAMETERS
+ * "derBytes"
+ * Address of array of bytes representing a DER-encoded OID.
+ * Must be non-NULL.
+ * "index"
+ * Index into the array that this function will begin decoding at.
+ * "pToken"
+ * Destination for decoded OID token. Must be non-NULL.
+ * "pIndex"
+ * Destination for index of next byte following last byte used.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object 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_pl_getOIDToken(
+ char *derBytes,
+ PKIX_UInt32 index,
+ PKIX_UInt32 *pToken,
+ PKIX_UInt32 *pIndex,
+ void *plContext)
+{
+ PKIX_UInt32 retval, i, tmp;
+
+ PKIX_ENTER(OID, "pkix_pl_getOIDToken");
+ PKIX_NULLCHECK_THREE(derBytes, pToken, pIndex);
+
+ /*
+ * We should only need to parse a maximum of four bytes, because
+ * RFC 3280 "mandates support for OIDs which have arc elements
+ * with values that are less than 2^28, that is, they MUST be between
+ * 0 and 268,435,455, inclusive. This allows each arc element to be
+ * represented within a single 32 bit word."
+ */
+
+ for (i = 0, retval = 0; i < 4; i++) {
+ retval <<= 7;
+ tmp = derBytes[index];
+ index++;
+ retval |= (tmp & 0x07f);
+ if ((tmp & 0x080) == 0){
+ *pToken = retval;
+ *pIndex = index;
+ goto cleanup;
+ }
+ }
+
+ PKIX_ERROR(PKIX_INVALIDENCODINGOIDTOKENVALUETOOBIG);
+
+cleanup:
+
+ PKIX_RETURN(OID);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_helperBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts an array of integers pointed to by "tokens" with a length of
+ * "numTokens", to an ASCII string consisting of those integers with dots in
+ * between them and stores the result at "pAscii". The ASCII representation is
+ * guaranteed to end with a NUL character. This is particularly useful for
+ * OID's and IP Addresses.
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ *
+ * PARAMETERS
+ * "tokens"
+ * Address of array of integers. Must be non-NULL.
+ * "numTokens"
+ * Length of array of integers. Must be non-zero.
+ * "pAscii"
+ * 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 Object 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_pl_helperBytes2Ascii(
+ PKIX_UInt32 *tokens,
+ PKIX_UInt32 numTokens,
+ char **pAscii,
+ void *plContext)
+{
+ char *tempString = NULL;
+ char *outputString = NULL;
+ char *format = "%d";
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 outputLen = 0;
+ PKIX_Int32 error;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii");
+ PKIX_NULLCHECK_TWO(tokens, pAscii);
+
+ if (numTokens == 0) {
+ PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO);
+ }
+
+ /*
+ * tempString will hold the string representation of a PKIX_UInt32 type
+ * The maximum value that can be held by an unsigned 32-bit integer
+ * is (2^32 - 1) = 4294967295 (which is ten digits long)
+ * Since tempString will hold the string representation of a
+ * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0')
+ */
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (MAX_DIGITS_32 + 1, (void **)&tempString, plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < numTokens; i++){
+ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
+ error = PR_snprintf(tempString,
+ MAX_DIGITS_32 + 1,
+ format,
+ tokens[i]);
+ if (error == -1){
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempString);
+
+ /* Include a dot to separate each number */
+ outputLen++;
+ }
+
+ /* Allocate space for the destination string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (outputLen, (void **)&outputString, plContext),
+ PKIX_MALLOCFAILED);
+
+ *outputString = '\0';
+
+ /* Concatenate all strings together */
+ for (i = 0; i < numTokens; i++){
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
+ error = PR_snprintf(tempString,
+ MAX_DIGITS_32 + 1,
+ format,
+ tokens[i]);
+ if (error == -1){
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
+ (void) PL_strcat(outputString, tempString);
+
+ /* we don't want to put a "." at the very end */
+ if (i < (numTokens - 1)){
+ PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
+ (void) PL_strcat(outputString, ".");
+ }
+ }
+
+ /* Ensure output string ends with terminating null */
+ outputString[outputLen-1] = '\0';
+
+ *pAscii = outputString;
+ outputString = NULL;
+
+cleanup:
+
+ PKIX_FREE(outputString);
+ PKIX_FREE(tempString);
+
+ PKIX_RETURN(OBJECT);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_ipAddrBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts the DER encoding of an IPAddress pointed to by "secItem" to an
+ * ASCII representation and stores the result at "pAscii". The ASCII
+ * representation is guaranteed to end with a NUL character. The input
+ * SECItem must contain non-NULL data and must have a positive length.
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ * XXX this function assumes that IPv4 addresses are being used
+ * XXX what about IPv6? can NSS tell the difference
+ *
+ * PARAMETERS
+ * "secItem"
+ * Address of SECItem which contains bytes and length of DER encoding.
+ * Must be non-NULL.
+ * "pAscii"
+ * 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 Object 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_pl_ipAddrBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext)
+{
+ char *data = NULL;
+ PKIX_UInt32 *tokens = NULL;
+ PKIX_UInt32 numTokens = 0;
+ PKIX_UInt32 i = 0;
+ char *asciiString = NULL;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii");
+ PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);
+
+ if (secItem->len == 0) {
+ PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO);
+ }
+
+ data = (char *)(secItem->data);
+ numTokens = secItem->len;
+
+ /* allocate space for array of integers */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numTokens * sizeof (PKIX_UInt32),
+ (void **)&tokens,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* populate array of integers */
+ for (i = 0; i < numTokens; i++){
+ tokens[i] = data[i];
+ }
+
+ /* convert array of integers to ASCII */
+ PKIX_CHECK(pkix_pl_helperBytes2Ascii
+ (tokens, numTokens, &asciiString, plContext),
+ PKIX_HELPERBYTES2ASCIIFAILED);
+
+ *pAscii = asciiString;
+
+cleanup:
+
+ PKIX_FREE(tokens);
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_oidBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts the DER encoding of an OID pointed to by "secItem" to an ASCII
+ * representation and stores it at "pAscii". The ASCII representation is
+ * guaranteed to end with a NUL character. The input SECItem must contain
+ * non-NULL data and must have a positive length.
+ *
+ * Example: the six bytes {2a 86 48 86 f7 0d} represent the
+ * four integer tokens {1, 2, 840, 113549}, which we will convert
+ * into ASCII yielding "1.2.840.113549"
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ *
+ * PARAMETERS
+ * "secItem"
+ * Address of SECItem which contains bytes and length of DER encoding.
+ * Must be non-NULL.
+ * "pAscii"
+ * 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 OID 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_pl_oidBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext)
+{
+ char *data = NULL;
+ PKIX_UInt32 *tokens = NULL;
+ PKIX_UInt32 token = 0;
+ PKIX_UInt32 numBytes = 0;
+ PKIX_UInt32 numTokens = 0;
+ PKIX_UInt32 i = 0, x = 0, y = 0;
+ PKIX_UInt32 index = 0;
+ char *asciiString = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii");
+ PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);
+
+ if (secItem->len == 0) {
+ PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO);
+ }
+
+ data = (char *)(secItem->data);
+ numBytes = secItem->len;
+ numTokens = 0;
+
+ /* calculate how many integer tokens are represented by the bytes. */
+ for (i = 0; i < numBytes; i++){
+ if ((data[i] & 0x080) == 0){
+ numTokens++;
+ }
+ }
+
+ /* if we are unable to retrieve any tokens at all, we throw an error */
+ if (numTokens == 0){
+ PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID);
+ }
+
+ /* add one more token b/c the first byte always contains two tokens */
+ numTokens++;
+
+ /* allocate space for array of integers */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numTokens * sizeof (PKIX_UInt32),
+ (void **)&tokens,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* populate array of integers */
+ for (i = 0; i < numTokens; i++){
+
+ /* retrieve integer token */
+ PKIX_CHECK(pkix_pl_getOIDToken
+ (data, index, &token, &index, plContext),
+ PKIX_GETOIDTOKENFAILED);
+
+ if (i == 0){
+
+ /*
+ * special case: the first DER-encoded byte represents
+ * two tokens. We take advantage of fact that first
+ * token must be 0, 1, or 2; and second token must be
+ * between {0, 39} inclusive if first token is 0 or 1.
+ */
+
+ if (token < 40)
+ x = 0;
+ else if (token < 80)
+ x = 1;
+ else
+ x = 2;
+ y = token - (x * 40);
+
+ tokens[0] = x;
+ tokens[1] = y;
+ i++;
+ } else {
+ tokens[i] = token;
+ }
+ }
+
+ /* convert array of integers to ASCII */
+ PKIX_CHECK(pkix_pl_helperBytes2Ascii
+ (tokens, numTokens, &asciiString, plContext),
+ PKIX_HELPERBYTES2ASCIIFAILED);
+
+ *pAscii = asciiString;
+
+cleanup:
+
+ PKIX_FREE(tokens);
+ PKIX_RETURN(OID);
+
+}
+
+/*
+ * FUNCTION: pkix_UTF16_to_EscASCII
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf16String" with length of
+ * "utf16Length" (which must be even) into a freshly allocated Escaped ASCII
+ * string and stores a pointer to that string at "pDest" and stores the
+ * string's length at "pLength". The Escaped ASCII string's length does not
+ * include the final NUL character. The caller is responsible for freeing
+ * "pDest" using PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug
+ * encoding.
+ *
+ * PARAMETERS:
+ * "utf16String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf16Length"
+ * Length of data source. Must be even.
+ * "debug"
+ * Boolean value indicating whether debug mode is desired.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length 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 String 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_UTF16_to_EscASCII(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean debug,
+ char **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ char *destPtr = NULL;
+ PKIX_UInt32 i, charLen;
+ PKIX_UInt32 x = 0, y = 0, z = 0;
+ unsigned char *utf16Char = (unsigned char *)utf16String;
+
+ PKIX_ENTER(STRING, "pkix_UTF16_to_EscASCII");
+ PKIX_NULLCHECK_THREE(utf16String, pDest, pLength);
+
+ /* Assume every pair of bytes becomes &#xNNNN; */
+ charLen = 4*utf16Length;
+
+ /* utf16Lenght must be even */
+ if ((utf16Length % 2) != 0){
+ PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR);
+ }
+
+ /* Count how many bytes we need */
+ for (i = 0; i < utf16Length; i += 2) {
+ if ((utf16Char[i] == 0x00)&&
+ pkix_isPlaintext(utf16Char[i+1], debug)) {
+ if (utf16Char[i+1] == '&') {
+ /* Need to convert this to &amp; */
+ charLen -= 3;
+ } else {
+ /* We can fit this into one char */
+ charLen -= 7;
+ }
+ } else if ((utf16Char[i] >= 0xD8) && (utf16Char[i] <= 0xDB)) {
+ if ((i+3) >= utf16Length) {
+ PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR);
+ } else if ((utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF)) {
+ /* Quartet of bytes will become &#xNNNNNNNN; */
+ charLen -= 4;
+ /* Quartet of bytes will produce 12 chars */
+ i += 2;
+ } else {
+ /* Second pair should be DC00-DFFF */
+ PKIX_ERROR(PKIX_UTF16LOWZONEERROR);
+ }
+ }
+ }
+
+ *pLength = charLen;
+
+ /* Ensure this string is null terminated */
+ charLen++;
+
+ /* Allocate space for character array */
+ PKIX_CHECK(PKIX_PL_Malloc(charLen, (void **)pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ destPtr = *pDest;
+ for (i = 0; i < utf16Length; i += 2) {
+ if ((utf16Char[i] == 0x00)&&
+ pkix_isPlaintext(utf16Char[i+1], debug)) {
+ /* Write a single character */
+ *destPtr++ = utf16Char[i+1];
+ } else if ((utf16Char[i+1] == '&') && (utf16Char[i] == 0x00)){
+ *destPtr++ = '&';
+ *destPtr++ = 'a';
+ *destPtr++ = 'm';
+ *destPtr++ = 'p';
+ *destPtr++ = ';';
+ } else if ((utf16Char[i] >= 0xD8)&&
+ (utf16Char[i] <= 0xDB)&&
+ (utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF)) {
+ /*
+ * Special UTF pairs are of the form:
+ * x = D800..DBFF; y = DC00..DFFF;
+ * The result is of the form:
+ * ((x - D800) * 400 + (y - DC00)) + 0001 0000
+ */
+ x = 0x0FFFF & ((utf16Char[i]<<8) | utf16Char[i+1]);
+ y = 0x0FFFF & ((utf16Char[i+2]<<8) | utf16Char[i+3]);
+ z = ((x - 0xD800) * 0x400 + (y - 0xDC00)) + 0x00010000;
+
+ /* Sprintf &#xNNNNNNNN; */
+ PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
+ if (PR_snprintf(destPtr, 13, "&#x%08X;", z) ==
+ (PKIX_UInt32)(-1)) {
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+ i += 2;
+ destPtr += 12;
+ } else {
+ /* Sprintf &#xNNNN; */
+ PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
+ if (PR_snprintf
+ (destPtr,
+ 9,
+ "&#x%02X%02X;",
+ utf16Char[i],
+ utf16Char[i+1]) ==
+ (PKIX_UInt32)(-1)) {
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+ destPtr += 8;
+ }
+ }
+ *destPtr = '\0';
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_EscASCII_to_UTF16
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "escAsciiString" with length of
+ * "escAsciiLength" into a freshly allocated UTF-16 string and stores a
+ * pointer to that string at "pDest" and stores the string's length at
+ * "pLength". The caller is responsible for freeing "pDest" using
+ * PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug encoding.
+ *
+ * PARAMETERS:
+ * "escAsciiString"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "escAsciiLength"
+ * Length of data source. Must be even.
+ * "debug"
+ * Boolean value indicating whether debug mode is desired.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length 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 String 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_EscASCII_to_UTF16(
+ const char *escAsciiString,
+ PKIX_UInt32 escAsciiLen,
+ PKIX_Boolean debug,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_UInt32 newLen, i, j, charSize;
+ PKIX_UInt32 x = 0, y = 0, z = 0;
+ unsigned char *destPtr = NULL;
+ unsigned char testChar, testChar2;
+ unsigned char *stringData = (unsigned char *)escAsciiString;
+
+ PKIX_ENTER(STRING, "pkix_EscASCII_to_UTF16");
+ PKIX_NULLCHECK_THREE(escAsciiString, pDest, pLength);
+
+ if (escAsciiLen == 0) {
+ PKIX_CHECK(PKIX_PL_Malloc(escAsciiLen, pDest, plContext),
+ PKIX_MALLOCFAILED);
+ goto cleanup;
+ }
+
+ /* Assume each unicode character takes two bytes */
+ newLen = escAsciiLen*2;
+
+ /* Count up number of unicode encoded characters */
+ for (i = 0; i < escAsciiLen; i++) {
+ if (!pkix_isPlaintext(stringData[i], debug)&&
+ (stringData[i] != '&')) {
+ PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ } else if (PL_strstr(escAsciiString+i, "&amp;") ==
+ escAsciiString+i) {
+ /* Convert EscAscii "&amp;" to two bytes */
+ newLen -= 8;
+ i += 4;
+ } else if ((PL_strstr(escAsciiString+i, "&#x") ==
+ escAsciiString+i)||
+ (PL_strstr(escAsciiString+i, "&#X") ==
+ escAsciiString+i)) {
+ if (((i+7) <= escAsciiLen)&&
+ (escAsciiString[i+7] == ';')) {
+ /* Convert &#xNNNN; to two bytes */
+ newLen -= 14;
+ i += 7;
+ } else if (((i+11) <= escAsciiLen)&&
+ (escAsciiString[i+11] == ';')) {
+ /* Convert &#xNNNNNNNN; to four bytes */
+ newLen -= 20;
+ i += 11;
+ } else {
+ PKIX_ERROR(PKIX_ILLEGALUSEOFAMP);
+ }
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Malloc(newLen, pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ /* Copy into newly allocated space */
+ destPtr = (unsigned char *)*pDest;
+
+ i = 0;
+ while (i < escAsciiLen) {
+ /* Copy each byte until you hit a &amp; */
+ if (pkix_isPlaintext(escAsciiString[i], debug)) {
+ *destPtr++ = 0x00;
+ *destPtr++ = escAsciiString[i++];
+ } else if (PL_strstr(escAsciiString+i, "&amp;") ==
+ escAsciiString+i) {
+ /* Convert EscAscii "&amp;" to two bytes */
+ *destPtr++ = 0x00;
+ *destPtr++ = '&';
+ i += 5;
+ } else if (((PL_strstr(escAsciiString+i, "&#x") ==
+ escAsciiString+i)||
+ (PL_strstr(escAsciiString+i, "&#X") ==
+ escAsciiString+i))&&
+ ((i+7) <= escAsciiLen)) {
+
+ /* We're either looking at &#xNNNN; or &#xNNNNNNNN; */
+ charSize = (escAsciiString[i+7] == ';')?4:8;
+
+ /* Skip past the &#x */
+ i += 3;
+
+ /* Make sure there is a terminating semi-colon */
+ if (((i+charSize) > escAsciiLen)||
+ (escAsciiString[i+charSize] != ';')) {
+ PKIX_ERROR(PKIX_TRUNCATEDUNICODEINESCAPEDASCII);
+ }
+
+ for (j = 0; j < charSize; j++) {
+ if (!PKIX_ISXDIGIT
+ (escAsciiString[i+j])) {
+ PKIX_ERROR(PKIX_ILLEGALUNICODECHARACTER);
+ } else if (charSize == 8) {
+ x |= (pkix_hex2i
+ (escAsciiString[i+j]))
+ <<(4*(7-j));
+ }
+ }
+
+ testChar =
+ (pkix_hex2i(escAsciiString[i])<<4)|
+ pkix_hex2i(escAsciiString[i+1]);
+ testChar2 =
+ (pkix_hex2i(escAsciiString[i+2])<<4)|
+ pkix_hex2i(escAsciiString[i+3]);
+
+ if (charSize == 4) {
+ if ((testChar >= 0xD8)&&
+ (testChar <= 0xDF)) {
+ PKIX_ERROR(PKIX_ILLEGALSURROGATEPAIR);
+ } else if ((testChar == 0x00)&&
+ pkix_isPlaintext(testChar2, debug)) {
+ PKIX_ERROR(
+ PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ *destPtr++ = testChar;
+ *destPtr++ = testChar2;
+ } else if (charSize == 8) {
+ /* First two chars must be 0001-0010 */
+ if (!((testChar == 0x00)&&
+ ((testChar2 >= 0x01)&&
+ (testChar2 <= 0x10)))) {
+ PKIX_ERROR(
+ PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ /*
+ * Unicode Strings of the form:
+ * x = 0001 0000..0010 FFFF
+ * Encoded as pairs of UTF-16 where
+ * y = ((x - 0001 0000) / 400) + D800
+ * z = ((x - 0001 0000) % 400) + DC00
+ */
+ x -= 0x00010000;
+ y = (x/0x400)+ 0xD800;
+ z = (x%0x400)+ 0xDC00;
+
+ /* Copy four bytes */
+ *destPtr++ = (y&0xFF00)>>8;
+ *destPtr++ = (y&0x00FF);
+ *destPtr++ = (z&0xFF00)>>8;
+ *destPtr++ = (z&0x00FF);
+ }
+ /* Move past the Hex digits and the semi-colon */
+ i += charSize+1;
+ } else {
+ /* Do not allow any other non-plaintext character */
+ PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ }
+
+ *pLength = newLen;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_UTF16_to_UTF8
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf16String" with length of
+ * "utf16Length" into a freshly allocated UTF-8 string and stores a pointer
+ * to that string at "pDest" and stores the string's length at "pLength" (not
+ * counting the null terminator, if requested. The caller is responsible for
+ * freeing "pDest" using PKIX_PL_Free.
+ *
+ * PARAMETERS:
+ * "utf16String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf16Length"
+ * Length of data source. Must be even.
+ * "null-term"
+ * Boolean value indicating whether output should be null-terminated.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length 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 String 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_UTF16_to_UTF8(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean null_term,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_Boolean result;
+ PKIX_UInt32 reallocLen;
+ char *endPtr = NULL;
+
+ PKIX_ENTER(STRING, "pkix_UTF16_to_UTF8");
+ PKIX_NULLCHECK_THREE(utf16String, pDest, pLength);
+
+ /* XXX How big can a UTF8 string be compared to a UTF16? */
+ PKIX_CHECK(PKIX_PL_Calloc(1, utf16Length*2, pDest, plContext),
+ PKIX_CALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n");
+ result = PORT_UCS2_UTF8Conversion
+ (PKIX_FALSE, /* False = From UCS2 */
+ (unsigned char *)utf16String,
+ utf16Length,
+ (unsigned char *)*pDest,
+ utf16Length*2, /* Max Size */
+ pLength);
+ if (result == PR_FALSE){
+ PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED);
+ }
+
+ reallocLen = *pLength;
+
+ if (null_term){
+ reallocLen++;
+ }
+
+ PKIX_CHECK(PKIX_PL_Realloc(*pDest, reallocLen, pDest, plContext),
+ PKIX_REALLOCFAILED);
+
+ if (null_term){
+ endPtr = (char*)*pDest + reallocLen - 1;
+ *endPtr = '\0';
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_UTF8_to_UTF16
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf8String" with length of
+ * "utf8Length" into a freshly allocated UTF-16 string and stores a pointer
+ * to that string at "pDest" and stores the string's length at "pLength". The
+ * caller is responsible for freeing "pDest" using PKIX_PL_Free.
+ *
+ * PARAMETERS:
+ * "utf8String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf8Length"
+ * Length of data source. Must be even.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length 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 String 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_UTF8_to_UTF16(
+ const void *utf8String,
+ PKIX_UInt32 utf8Length,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_Boolean result;
+
+ PKIX_ENTER(STRING, "pkix_UTF8_to_UTF16");
+ PKIX_NULLCHECK_THREE(utf8String, pDest, pLength);
+
+ /* XXX How big can a UTF8 string be compared to a UTF16? */
+ PKIX_CHECK(PKIX_PL_Calloc(1, utf8Length*2, pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n");
+ result = PORT_UCS2_UTF8Conversion
+ (PKIX_TRUE, /* True = From UTF8 */
+ (unsigned char *)utf8String,
+ utf8Length,
+ (unsigned char *)*pDest,
+ utf8Length*2, /* Max Size */
+ pLength);
+ if (result == PR_FALSE){
+ PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Realloc(*pDest, *pLength, pDest, plContext),
+ PKIX_REALLOCFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h
new file mode 100644
index 0000000000..2946e07a67
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h
@@ -0,0 +1,159 @@
+/* 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_pl_common.h
+ *
+ * Common central header file included by all PL source files
+ *
+ */
+
+#ifndef _PKIX_PL_COMMON_H
+#define _PKIX_PL_COMMON_H
+
+/* PKIX HEADERS */
+#include "pkix_tools.h"
+
+/* NSS headers */
+#include "nss.h"
+#include "secport.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "base64.h"
+#include "cert.h"
+#include "certdb.h"
+#include "genname.h"
+#include "xconst.h"
+#include "keyhi.h"
+#include "ocsp.h"
+#include "ocspt.h"
+#include "pk11pub.h"
+#include "pkcs11.h"
+#include "pkcs11t.h"
+#include "prio.h"
+
+/* NSPR headers */
+#include "nspr.h"
+
+/* private PKIX_PL_NSS system headers */
+#include "pkix_pl_object.h"
+#include "pkix_pl_string.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapt.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_aiamgr.h"
+#include "pkix_pl_bigint.h"
+#include "pkix_pl_oid.h"
+#include "pkix_pl_x500name.h"
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_publickey.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_date.h"
+#include "pkix_pl_primhash.h"
+#include "pkix_pl_basicconstraints.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_cert.h"
+#include "pkix_pl_certpolicyinfo.h"
+#include "pkix_pl_certpolicymap.h"
+#include "pkix_pl_certpolicyqualifier.h"
+#include "pkix_pl_crldp.h"
+#include "pkix_pl_crl.h"
+#include "pkix_pl_crlentry.h"
+#include "pkix_pl_nameconstraints.h"
+#include "pkix_pl_ocsprequest.h"
+#include "pkix_pl_ocspresponse.h"
+#include "pkix_pl_pk11certstore.h"
+#include "pkix_pl_socket.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapcertstore.h"
+#include "pkix_pl_ldaprequest.h"
+#include "pkix_pl_ldapresponse.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_nsscontext.h"
+#include "pkix_pl_httpcertstore.h"
+#include "pkix_pl_httpdefaultclient.h"
+#include "pkix_pl_infoaccess.h"
+#include "pkix_sample_modules.h"
+
+#define MAX_DIGITS_32 (PKIX_UInt32) 10
+
+#define PKIX_PL_NSSCALL(type, func, args) \
+ PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \
+ (func args)
+
+#define PKIX_PL_NSSCALLRV(type, lvalue, func, args) \
+ PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \
+ lvalue = (func args)
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_LockObject(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+PKIX_Error *
+pkix_UnlockObject(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+PKIX_Boolean
+pkix_pl_UInt32_Overflows(char *string);
+
+PKIX_Error *
+pkix_pl_helperBytes2Ascii(
+ PKIX_UInt32 *tokens,
+ PKIX_UInt32 numTokens,
+ char **pAscii,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_ipAddrBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_oidBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext);
+
+/* --String-Encoding-Conversion-Functions------------------------ */
+
+PKIX_Error *
+pkix_UTF16_to_EscASCII(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean debug,
+ char **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_EscASCII_to_UTF16(
+ const char *escAsciiString,
+ PKIX_UInt32 escAsciiLen,
+ PKIX_Boolean debug,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_UTF16_to_UTF8(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean null_Term,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_UTF8_to_UTF16(
+ const void *utf8Source,
+ PKIX_UInt32 utf8Length,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+#endif /* _PKIX_PL_COMMON_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c
new file mode 100644
index 0000000000..2631aed031
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_error.c
+ *
+ * PL error functions
+ *
+ */
+
+#include "pkix_pl_common.h"
+
+#undef PKIX_ERRORENTRY
+
+#define PKIX_ERRORENTRY(name,desc,plerr) plerr
+
+const PKIX_Int32 PKIX_PLErrorIndex[] =
+{
+#include "pkix_errorstrings.h"
+};
+
+int
+PKIX_PL_GetPLErrorCode()
+{
+ return PORT_GetError();
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
new file mode 100644
index 0000000000..260365375e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
@@ -0,0 +1,383 @@
+/* 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_pl_hashtable.c
+ *
+ * Hashtable Object Functions
+ *
+ */
+
+#include "pkix_pl_hashtable.h"
+
+/* --Private-Structure-------------------------------------------- */
+
+struct PKIX_PL_HashTableStruct {
+ pkix_pl_PrimHashTable *primHash;
+ PKIX_PL_Mutex *tableLock;
+ PKIX_UInt32 maxEntriesPerBucket;
+};
+
+/* --Private-Functions-------------------------------------------- */
+
+#define PKIX_MUTEX_UNLOCK(mutex) \
+ do { \
+ if (mutex && lockedMutex == (PKIX_PL_Mutex *)(mutex)) { \
+ pkixTempResult = \
+ PKIX_PL_Mutex_Unlock((mutex), plContext); \
+ PORT_Assert(pkixTempResult == NULL); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ lockedMutex = NULL; \
+ } else { \
+ PORT_Assert(lockedMutex == NULL); \
+ }\
+ } while (0)
+
+
+#define PKIX_MUTEX_LOCK(mutex) \
+ do { \
+ if (mutex){ \
+ PORT_Assert(lockedMutex == NULL); \
+ PKIX_CHECK(PKIX_PL_Mutex_Lock((mutex), plContext), \
+ PKIX_MUTEXLOCKFAILED); \
+ lockedMutex = (mutex); \
+ } \
+ } while (0)
+
+/*
+ * FUNCTION: pkix_pl_HashTable_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_HashTable_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_HashTable *ht = NULL;
+ pkix_pl_HT_Elem *item = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_HASHTABLE_TYPE, plContext),
+ PKIX_OBJECTNOTHASHTABLE);
+
+ ht = (PKIX_PL_HashTable*) object;
+
+ /* DecRef every object in the primitive hash table */
+ for (i = 0; i < ht->primHash->size; i++) {
+ for (item = ht->primHash->buckets[i];
+ item != NULL;
+ item = item->next) {
+ PKIX_DECREF(item->key);
+ PKIX_DECREF(item->value);
+ }
+ }
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Destroy(ht->primHash, plContext),
+ PKIX_PRIMHASHTABLEDESTROYFAILED);
+
+ PKIX_DECREF(ht->tableLock);
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_HashTable_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_HASHTABLE_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_pl_HashTable_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_RegisterSelf");
+
+ entry.description = "HashTable";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_HashTable);
+ entry.destructor = pkix_pl_HashTable_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_HASHTABLE_TYPE] = entry;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Create(
+ PKIX_UInt32 numBuckets,
+ PKIX_UInt32 maxEntriesPerBucket,
+ PKIX_PL_HashTable **pResult,
+ void *plContext)
+{
+ PKIX_PL_HashTable *hashTable = NULL;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Create");
+ PKIX_NULLCHECK_ONE(pResult);
+
+ if (numBuckets == 0) {
+ PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
+ }
+
+ /* Allocate a new hashtable */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_HASHTABLE_TYPE,
+ sizeof (PKIX_PL_HashTable),
+ (PKIX_PL_Object **)&hashTable,
+ plContext),
+ PKIX_COULDNOTCREATEHASHTABLEOBJECT);
+
+ /* Create the underlying primitive hash table type */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Create
+ (numBuckets, &hashTable->primHash, plContext),
+ PKIX_PRIMHASHTABLECREATEFAILED);
+
+ /* Create a lock for this table */
+ PKIX_CHECK(PKIX_PL_Mutex_Create(&hashTable->tableLock, plContext),
+ PKIX_ERRORCREATINGTABLELOCK);
+
+ hashTable->maxEntriesPerBucket = maxEntriesPerBucket;
+
+ *pResult = hashTable;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(hashTable);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Add (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Add(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object *value,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_PL_Object *deletedKey = NULL;
+ PKIX_PL_Object *deletedValue = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+ PKIX_UInt32 bucketSize = 0;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Add");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_THREE(ht, key, value);
+#else
+ PKIX_NULLCHECK_TWO(key, value);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+ /* Insert into primitive hashtable */
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_GetBucketSize
+ (ht->primHash,
+ hashCode,
+ &bucketSize,
+ plContext),
+ PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED);
+
+ if (ht->maxEntriesPerBucket != 0 &&
+ bucketSize >= ht->maxEntriesPerBucket) {
+ /* drop the last one in the bucket */
+ PKIX_CHECK(pkix_pl_PrimHashTable_RemoveFIFO
+ (ht->primHash,
+ hashCode,
+ (void **) &deletedKey,
+ (void **) &deletedValue,
+ plContext),
+ PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED);
+ PKIX_DECREF(deletedKey);
+ PKIX_DECREF(deletedValue);
+ }
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Add
+ (ht->primHash,
+ (void *)key,
+ (void *)value,
+ hashCode,
+ keyComp,
+ plContext),
+ PKIX_PRIMHASHTABLEADDFAILED);
+
+ PKIX_INCREF(key);
+ PKIX_INCREF(value);
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ /*
+ * we don't call PKIX_PL_InvalidateCache here b/c we have
+ * not implemented toString or hashcode for this Object
+ */
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Remove (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Remove(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_PL_Object *origKey = NULL;
+ PKIX_PL_Object *value = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Remove");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_TWO(ht, key);
+#else
+ PKIX_NULLCHECK_ONE(key);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ /* Remove from primitive hashtable */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Remove
+ (ht->primHash,
+ (void *)key,
+ hashCode,
+ keyComp,
+ (void **)&origKey,
+ (void **)&value,
+ plContext),
+ PKIX_PRIMHASHTABLEREMOVEFAILED);
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_DECREF(origKey);
+ PKIX_DECREF(value);
+
+ /*
+ * we don't call PKIX_PL_InvalidateCache here b/c we have
+ * not implemented toString or hashcode for this Object
+ */
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Lookup (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Lookup(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object **pResult,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+ PKIX_PL_Object *result = NULL;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Lookup");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_THREE(ht, key, pResult);
+#else
+ PKIX_NULLCHECK_TWO(key, pResult);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ /* Lookup in primitive hashtable */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (ht->primHash,
+ (void *)key,
+ hashCode,
+ keyComp,
+ (void **)&result,
+ plContext),
+ PKIX_PRIMHASHTABLELOOKUPFAILED);
+
+ PKIX_INCREF(result);
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ *pResult = result;
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h
new file mode 100644
index 0000000000..479c623733
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h
@@ -0,0 +1,29 @@
+/* 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_pl_hashtable.h
+ *
+ * Hashtable Object Definition
+ *
+ */
+
+#ifndef _PKIX_PL_HASHTABLE_H
+#define _PKIX_PL_HASHTABLE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_HashTable_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_HASHTABLE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
new file mode 100644
index 0000000000..70ed25d729
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
@@ -0,0 +1,279 @@
+/* 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_pl_lifecycle.c
+ *
+ * Lifecycle Functions for the PKIX PL library.
+ *
+ */
+
+#include "pkix_pl_lifecycle.h"
+
+PKIX_Boolean pkix_pl_initialized = PKIX_FALSE;
+pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+PRLock *classTableLock;
+PRLogModuleInfo *pkixLog = NULL;
+
+/*
+ * PKIX_ALLOC_ERROR is a special error object hard-coded into the
+ * pkix_error.o object file. It is thrown if system memory cannot be
+ * allocated. PKIX_ALLOC_ERROR is immutable.
+ * IncRef, DecRef, and Settor functions cannot be called.
+ */
+
+/* Keep this structure definition here for its is used only once here */
+struct PKIX_Alloc_Error_ObjectStruct {
+ PKIX_PL_Object header;
+ PKIX_Error error;
+};
+typedef struct PKIX_Alloc_Error_ObjectStruct PKIX_Alloc_Error_Object;
+
+static const PKIX_Alloc_Error_Object pkix_Alloc_Error_Data = {
+ {
+ PKIX_MAGIC_HEADER, /* PRUint64 magicHeader */
+ (PKIX_UInt32)PKIX_ERROR_TYPE, /* PKIX_UInt32 type */
+ (PKIX_UInt32)1, /* PKIX_UInt32 references */
+ /* Warning! Cannot Ref Count with NULL lock */
+ (void *)0, /* PRLock *lock */
+ (PKIX_PL_String *)0, /* PKIX_PL_String *stringRep */
+ (PKIX_UInt32)0, /* PKIX_UInt32 hashcode */
+ (PKIX_Boolean)PKIX_FALSE, /* PKIX_Boolean hashcodeCached */
+ }, {
+ (PKIX_ERRORCODE)0, /* PKIX_ERRORCODE errCode; */
+ (PKIX_ERRORCLASS)PKIX_FATAL_ERROR,/* PKIX_ERRORCLASS errClass */
+ (PKIX_UInt32)SEC_ERROR_LIBPKIX_INTERNAL, /* default PL Error Code */
+ (PKIX_Error *)0, /* PKIX_Error *cause */
+ (PKIX_PL_Object *)0, /* PKIX_PL_Object *info */
+ }
+};
+
+PKIX_Error* PKIX_ALLOC_ERROR(void)
+{
+ return (PKIX_Error *)&pkix_Alloc_Error_Data.error;
+}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+SECStatus
+pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable)
+{
+ int typeCounter = 0;
+
+ for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
+ pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+
+ objCountTable[typeCounter] = entry->objCounter;
+ }
+
+ return SECSuccess;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+PKIX_UInt32
+pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable)
+{
+ unsigned int typeCounter = 0;
+ PKIX_UInt32 numObjects = 0;
+ char classNameBuff[128];
+ char *className = NULL;
+
+ for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
+ pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+ PKIX_UInt32 objCountDiff = entry->objCounter;
+
+ if (initObjCountTable) {
+ PKIX_UInt32 initialCount = initObjCountTable[typeCounter];
+ objCountDiff = (entry->objCounter > initialCount) ?
+ entry->objCounter - initialCount : 0;
+ }
+
+ numObjects += objCountDiff;
+
+ if (!pkixLog || !objCountDiff) {
+ continue;
+ }
+ className = entry->description;
+ if (!className) {
+ className = classNameBuff;
+ PR_snprintf(className, 128, "Unknown(ref %d)",
+ entry->objCounter);
+ }
+
+ PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of "
+ "size %d bytes, total = %d bytes\n", className,
+ objCountDiff, entry->typeObjectSize,
+ objCountDiff * entry->typeObjectSize));
+ }
+
+ return numObjects;
+}
+
+/*
+ * PKIX_PL_Initialize (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_Boolean useArenas,
+ void **pPlContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Initialize");
+
+ /*
+ * This function can only be called once. If it has already been
+ * called, we return a positive status.
+ */
+ if (pkix_pl_initialized) {
+ PKIX_RETURN(OBJECT);
+ }
+
+ classTableLock = PR_NewLock();
+ if (classTableLock == NULL) {
+ return PKIX_ALLOC_ERROR();
+ }
+
+ if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
+ pkixLog = PR_NewLogModule("pkix");
+ }
+ /*
+ * Register Object, it is the base object of all other objects.
+ */
+ pkix_pl_Object_RegisterSelf(plContext);
+
+ /*
+ * Register Error and String, since they will be needed if
+ * there is a problem in registering any other type.
+ */
+ pkix_Error_RegisterSelf(plContext);
+ pkix_pl_String_RegisterSelf(plContext);
+
+
+ /*
+ * We register all other system types
+ * (They don't need to be in order, but it's
+ * easier to keep track of what types are registered
+ * if we register them in the same order as their
+ * numbers, defined in pkixt.h.
+ */
+ pkix_pl_BigInt_RegisterSelf(plContext); /* 1-10 */
+ pkix_pl_ByteArray_RegisterSelf(plContext);
+ pkix_pl_HashTable_RegisterSelf(plContext);
+ pkix_List_RegisterSelf(plContext);
+ pkix_Logger_RegisterSelf(plContext);
+ pkix_pl_Mutex_RegisterSelf(plContext);
+ pkix_pl_OID_RegisterSelf(plContext);
+ pkix_pl_RWLock_RegisterSelf(plContext);
+
+ pkix_pl_CertBasicConstraints_RegisterSelf(plContext); /* 11-20 */
+ pkix_pl_Cert_RegisterSelf(plContext);
+ pkix_pl_CRL_RegisterSelf(plContext);
+ pkix_pl_CRLEntry_RegisterSelf(plContext);
+ pkix_pl_Date_RegisterSelf(plContext);
+ pkix_pl_GeneralName_RegisterSelf(plContext);
+ pkix_pl_CertNameConstraints_RegisterSelf(plContext);
+ pkix_pl_PublicKey_RegisterSelf(plContext);
+ pkix_TrustAnchor_RegisterSelf(plContext);
+
+ pkix_pl_X500Name_RegisterSelf(plContext); /* 21-30 */
+ pkix_pl_HttpCertStoreContext_RegisterSelf(plContext);
+ pkix_BuildResult_RegisterSelf(plContext);
+ pkix_ProcessingParams_RegisterSelf(plContext);
+ pkix_ValidateParams_RegisterSelf(plContext);
+ pkix_ValidateResult_RegisterSelf(plContext);
+ pkix_CertStore_RegisterSelf(plContext);
+ pkix_CertChainChecker_RegisterSelf(plContext);
+ pkix_RevocationChecker_RegisterSelf(plContext);
+ pkix_CertSelector_RegisterSelf(plContext);
+
+ pkix_ComCertSelParams_RegisterSelf(plContext); /* 31-40 */
+ pkix_CRLSelector_RegisterSelf(plContext);
+ pkix_ComCRLSelParams_RegisterSelf(plContext);
+ pkix_pl_CertPolicyInfo_RegisterSelf(plContext);
+ pkix_pl_CertPolicyQualifier_RegisterSelf(plContext);
+ pkix_pl_CertPolicyMap_RegisterSelf(plContext);
+ pkix_PolicyNode_RegisterSelf(plContext);
+ pkix_TargetCertCheckerState_RegisterSelf(plContext);
+ pkix_BasicConstraintsCheckerState_RegisterSelf(plContext);
+ pkix_PolicyCheckerState_RegisterSelf(plContext);
+
+ pkix_pl_CollectionCertStoreContext_RegisterSelf(plContext); /* 41-50 */
+ pkix_CrlChecker_RegisterSelf(plContext);
+ pkix_ForwardBuilderState_RegisterSelf(plContext);
+ pkix_SignatureCheckerState_RegisterSelf(plContext);
+ pkix_NameConstraintsCheckerState_RegisterSelf(plContext);
+#ifndef NSS_PKIX_NO_LDAP
+ pkix_pl_LdapRequest_RegisterSelf(plContext);
+ pkix_pl_LdapResponse_RegisterSelf(plContext);
+ pkix_pl_LdapDefaultClient_RegisterSelf(plContext);
+#endif
+ pkix_pl_Socket_RegisterSelf(plContext);
+
+ pkix_ResourceLimits_RegisterSelf(plContext); /* 51-59 */
+ pkix_pl_MonitorLock_RegisterSelf(plContext);
+ pkix_pl_InfoAccess_RegisterSelf(plContext);
+ pkix_pl_AIAMgr_RegisterSelf(plContext);
+ pkix_OcspChecker_RegisterSelf(plContext);
+ pkix_pl_OcspCertID_RegisterSelf(plContext);
+ pkix_pl_OcspRequest_RegisterSelf(plContext);
+ pkix_pl_OcspResponse_RegisterSelf(plContext);
+ pkix_pl_HttpDefaultClient_RegisterSelf(plContext);
+ pkix_VerifyNode_RegisterSelf(plContext);
+ pkix_EkuChecker_RegisterSelf(plContext);
+ pkix_pl_CrlDp_RegisterSelf(plContext);
+
+ if (pPlContext) {
+ PKIX_CHECK(PKIX_PL_NssContext_Create
+ (0, useArenas, NULL, &plContext),
+ PKIX_NSSCONTEXTCREATEFAILED);
+
+ *pPlContext = plContext;
+ }
+
+ pkix_pl_initialized = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * PKIX_PL_Shutdown (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Shutdown(void *plContext)
+{
+#ifdef DEBUG
+ PKIX_UInt32 numLeakedObjects = 0;
+#endif
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Shutdown");
+
+ if (!pkix_pl_initialized) {
+ /* The library was not initilized */
+ PKIX_RETURN(OBJECT);
+ }
+
+ PR_DestroyLock(classTableLock);
+
+ pkix_pl_HttpCertStore_Shutdown(plContext);
+
+#ifdef DEBUG
+ numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL);
+ if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
+ PORT_Assert(numLeakedObjects == 0);
+ }
+#else
+ pkix_pl_lifecycle_ObjectLeakCheck(NULL);
+#endif
+
+ if (plContext != NULL) {
+ PKIX_PL_NssContext_Destroy(plContext);
+ }
+
+ pkix_pl_initialized = PKIX_FALSE;
+
+ PKIX_RETURN(OBJECT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h
new file mode 100644
index 0000000000..9660af123d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h
@@ -0,0 +1,91 @@
+/* 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_pl_lifecycle.h
+ *
+ * Lifecycle Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_LIFECYCLE_H
+#define _PKIX_PL_LIFECYCLE_H
+
+#include "pkix_pl_common.h"
+#include "pkix_pl_oid.h"
+#include "pkix_pl_aiamgr.h"
+#include "pkix_pl_bigint.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_hashtable.h"
+#include "pkix_pl_mutex.h"
+#include "pkix_pl_rwlock.h"
+#include "pkix_pl_monitorlock.h"
+#include "pkix_pl_string.h"
+#include "pkix_pl_cert.h"
+#include "pkix_pl_x500name.h"
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_publickey.h"
+#include "pkix_pl_date.h"
+#include "pkix_pl_basicconstraints.h"
+#include "pkix_pl_certpolicyinfo.h"
+#include "pkix_pl_certpolicymap.h"
+#include "pkix_pl_certpolicyqualifier.h"
+#include "pkix_pl_crlentry.h"
+#include "pkix_pl_crl.h"
+#include "pkix_pl_colcertstore.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapcertstore.h"
+#include "pkix_pl_ldapdefaultclient.h"
+#include "pkix_pl_ldaprequest.h"
+#include "pkix_pl_ldapresponse.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_socket.h"
+#include "pkix_pl_infoaccess.h"
+#include "pkix_store.h"
+#include "pkix_error.h"
+#include "pkix_logger.h"
+#include "pkix_list.h"
+#include "pkix_trustanchor.h"
+#include "pkix_procparams.h"
+#include "pkix_valparams.h"
+#include "pkix_valresult.h"
+#include "pkix_verifynode.h"
+#include "pkix_resourcelimits.h"
+#include "pkix_certchainchecker.h"
+#include "pkix_revocationchecker.h"
+#include "pkix_certselector.h"
+#include "pkix_comcertselparams.h"
+#include "pkix_crlselector.h"
+#include "pkix_comcrlselparams.h"
+#include "pkix_targetcertchecker.h"
+#include "pkix_basicconstraintschecker.h"
+#include "pkix_policynode.h"
+#include "pkix_policychecker.h"
+#include "pkix_crlchecker.h"
+#include "pkix_signaturechecker.h"
+#include "pkix_buildresult.h"
+#include "pkix_build.h"
+#include "pkix_pl_nameconstraints.h"
+#include "pkix_nameconstraintschecker.h"
+#include "pkix_ocspchecker.h"
+#include "pkix_pl_ocspcertid.h"
+#include "pkix_pl_ocsprequest.h"
+#include "pkix_pl_ocspresponse.h"
+#include "pkix_pl_httpdefaultclient.h"
+#include "pkix_pl_httpcertstore.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_InitializeParamsStruct {
+ PKIX_List *loggers;
+ PKIX_UInt32 majorVersion;
+ PKIX_UInt32 minorVersion;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LIFECYCLE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c
new file mode 100644
index 0000000000..d75c0be26e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c
@@ -0,0 +1,168 @@
+/* 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_pl_mem.c
+ *
+ * Memory Management Functions
+ *
+ */
+
+#include "pkix_pl_mem.h"
+
+/*
+ * FUNCTION: PKIX_PL_Malloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Malloc(
+ PKIX_UInt32 size,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Malloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ if (size == 0){
+ *pMemory = NULL;
+ } else {
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ *pMemory = PORT_ArenaAlloc(nssContext->arena, size);
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Malloc.\n");
+ result = (void *) PR_Malloc(size);
+
+ if (result == NULL) {
+ PKIX_MEM_DEBUG("Fatal Error Occurred: "
+ "PR_Malloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ } else {
+ *pMemory = result;
+ }
+ }
+ }
+
+cleanup:
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Calloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Calloc(
+ PKIX_UInt32 nElem,
+ PKIX_UInt32 elSize,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Calloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ if ((nElem == 0) || (elSize == 0)){
+ *pMemory = NULL;
+ } else {
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ *pMemory = PORT_ArenaAlloc(nssContext->arena, elSize);
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Calloc.\n");
+ result = (void *) PR_Calloc(nElem, elSize);
+
+ if (result == NULL) {
+ PKIX_MEM_DEBUG("Fatal Error Occurred: "
+ "PR_Calloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ } else {
+ *pMemory = result;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Realloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Realloc(
+ void *ptr,
+ PKIX_UInt32 size,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Realloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ result = PORT_ArenaAlloc(nssContext->arena, size);
+
+ if (result){
+ PKIX_MEM_DEBUG("\tCalling PORT_Memcpy.\n");
+ PORT_Memcpy(result, ptr, size);
+ }
+ *pMemory = result;
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Realloc.\n");
+ result = (void *) PR_Realloc(ptr, size);
+
+ if (result == NULL) {
+ if (size == 0){
+ *pMemory = NULL;
+ } else {
+ PKIX_MEM_DEBUG
+ ("Fatal Error Occurred: "
+ "PR_Realloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ } else {
+ *pMemory = result;
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Free (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Free(
+ void *ptr,
+ /* ARGSUSED */ void *plContext)
+{
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Free");
+
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context == NULL || context->arena == NULL) {
+ PKIX_MEM_DEBUG("\tCalling PR_Free.\n");
+ (void) PR_Free(ptr);
+ }
+
+ PKIX_RETURN(MEM);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h
new file mode 100644
index 0000000000..eaec6246c9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h
@@ -0,0 +1,24 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_mem.h
+ *
+ * Memory Management Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_MEM_H
+#define _PKIX_PL_MEM_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MEM_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c
new file mode 100644
index 0000000000..a5d2fc9621
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c
@@ -0,0 +1,136 @@
+/* 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_pl_monitorlock.c
+ *
+ * Read/Write Lock Functions
+ *
+ */
+
+#include "pkix_pl_monitorlock.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+static PKIX_Error *
+pkix_pl_MonitorLock_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_MonitorLock* monitorLock = NULL;
+
+ PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_MONITORLOCK_TYPE, plContext),
+ PKIX_OBJECTNOTMONITORLOCK);
+
+ monitorLock = (PKIX_PL_MonitorLock*) object;
+
+ PKIX_MONITORLOCK_DEBUG("Calling PR_DestroyMonitor)\n");
+ PR_DestroyMonitor(monitorLock->lock);
+ monitorLock->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+/*
+ * FUNCTION: pkix_pl_MonitorLock_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_MONITORLOCK_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_pl_MonitorLock_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_RegisterSelf");
+
+ entry.description = "MonitorLock";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_MonitorLock);
+ entry.destructor = pkix_pl_MonitorLock_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_MONITORLOCK_TYPE] = entry;
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Create(
+ PKIX_PL_MonitorLock **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_MonitorLock *monitorLock = NULL;
+
+ PKIX_ENTER(MONITORLOCK, "PKIX_PL_MonitorLock_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_MONITORLOCK_TYPE,
+ sizeof (PKIX_PL_MonitorLock),
+ (PKIX_PL_Object **)&monitorLock,
+ plContext),
+ PKIX_ERRORALLOCATINGMONITORLOCK);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_NewMonitor)\n");
+ monitorLock->lock = PR_NewMonitor();
+
+ if (monitorLock->lock == NULL) {
+ PKIX_DECREF(monitorLock);
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pNewLock = monitorLock;
+
+cleanup:
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Enter(
+ PKIX_PL_MonitorLock *monitorLock,
+ void *plContext)
+{
+ PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Enter");
+ PKIX_NULLCHECK_ONE(monitorLock);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_EnterMonitor)\n");
+ (void) PR_EnterMonitor(monitorLock->lock);
+
+ PKIX_RETURN_NO_LOGGER(MONITORLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Exit(
+ PKIX_PL_MonitorLock *monitorLock,
+ void *plContext)
+{
+ PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Exit");
+ PKIX_NULLCHECK_ONE(monitorLock);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_ExitMonitor)\n");
+ PR_ExitMonitor(monitorLock->lock);
+
+ PKIX_RETURN_NO_LOGGER(MONITORLOCK);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h
new file mode 100644
index 0000000000..76ac539ad8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_monitorlock.h
+ *
+ * Read/Write Lock Definition
+ *
+ */
+
+#ifndef _PKIX_PL_MONITORLOCK_H
+#define _PKIX_PL_MONITORLOCK_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_MonitorLockStruct {
+ PRMonitor* lock;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_MonitorLock_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MONITORLOCK_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c
new file mode 100644
index 0000000000..07d13695b5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c
@@ -0,0 +1,163 @@
+/* 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_pl_mutex.c
+ *
+ * Mutual Exclusion (Lock) Object Functions
+ *
+ */
+
+#include "pkix_pl_mutex.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Mutex_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Mutex_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Mutex *mutex = NULL;
+
+ PKIX_ENTER(MUTEX, "pkix_pl_Mutex_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Sanity check: Test that "object" is a mutex */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_MUTEX_TYPE, plContext),
+ PKIX_OBJECTNOTMUTEX);
+
+ mutex = (PKIX_PL_Mutex*) object;
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_DestroyLock).\n");
+ PR_DestroyLock(mutex->lock);
+ mutex->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: pkix_pl_Mutex_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_MUTEX_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_pl_Mutex_RegisterSelf(
+ /* ARGSUSED */ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(MUTEX, "pkix_pl_Mutex_RegisterSelf");
+
+ entry.description = "Mutex";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Mutex);
+ entry.destructor = pkix_pl_Mutex_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_MUTEX_TYPE] = entry;
+
+ PKIX_RETURN(MUTEX);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Create(
+ PKIX_PL_Mutex **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_Mutex *mutex = NULL;
+
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_MUTEX_TYPE,
+ sizeof (PKIX_PL_Mutex),
+ (PKIX_PL_Object **)&mutex,
+ plContext),
+ PKIX_COULDNOTCREATELOCKOBJECT);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_NewLock).\n");
+ mutex->lock = PR_NewLock();
+
+ /* If an error occurred in NSPR, report it here */
+ if (mutex->lock == NULL) {
+ PKIX_DECREF(mutex);
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ *pNewLock = mutex;
+
+cleanup:
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Lock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Lock(
+ PKIX_PL_Mutex *mutex,
+ void *plContext)
+{
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Lock");
+ PKIX_NULLCHECK_ONE(mutex);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(mutex->lock);
+
+ PKIX_MUTEX_DEBUG_ARG("(Thread %u just acquired the lock)\n",
+ (PKIX_UInt32)PR_GetCurrentThread());
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Unlock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Unlock(
+ PKIX_PL_Mutex *mutex,
+ void *plContext)
+{
+ PRStatus result;
+
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Unlock");
+ PKIX_NULLCHECK_ONE(mutex);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_Unlock).\n");
+ result = PR_Unlock(mutex->lock);
+
+ PKIX_MUTEX_DEBUG_ARG("(Thread %u just released the lock)\n",
+ (PKIX_UInt32)PR_GetCurrentThread());
+
+ if (result == PR_FAILURE) {
+ PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGMUTEX);
+ }
+
+cleanup:
+ PKIX_RETURN(MUTEX);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h
new file mode 100644
index 0000000000..baf16fea92
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_mutex.h
+ *
+ * Mutual Exclusion (Lock) Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_MUTEX_H
+#define _PKIX_PL_MUTEX_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_MutexStruct {
+ PRLock* lock;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Mutex_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MUTEX_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
new file mode 100644
index 0000000000..7dafa0b204
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
@@ -0,0 +1,1440 @@
+/* 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_pl_object.c
+ *
+ * Object Construction, Destruction and Callback Functions
+ *
+ */
+
+#include "pkix_pl_object.h"
+
+#ifdef PKIX_USER_OBJECT_TYPE
+/* --Class-Table-Initializers------------------------------------ */
+
+/*
+ * Create storage space for 20 Class Table buckets.
+ * These are only for user-defined types. System types are registered
+ * separately by PKIX_PL_Initialize.
+ */
+
+static pkix_pl_HT_Elem*
+pkix_Raw_ClassTable_Buckets[] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/*
+ * Allocate static memory for a ClassTable.
+ * XXX This assumes the bucket pointer will fit into a PKIX_UInt32
+ */
+static pkix_pl_PrimHashTable pkix_Raw_ClassTable = {
+ (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */
+ 20 /* Number of Buckets */
+};
+static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable;
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Object_GetHeader
+ * DESCRIPTION:
+ *
+ * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
+ * stores the value at "pObjectHeader".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to shift. Must be non-NULL.
+ * "pObjectHeader"
+ * 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_pl_Object_GetHeader(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pObjectHeader,
+ void *plContext)
+{
+ PKIX_PL_Object *header = NULL;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader");
+ PKIX_NULLCHECK_TWO(object, pObjectHeader);
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+ header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object));
+
+ objType = header->type;
+
+ if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext),
+ PKIX_ERRORGETTINGCLASSTABLEENTRY);
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (ctEntry == NULL) {
+ PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE);
+ }
+#else
+ PORT_Assert(objType < PKIX_NUMTYPES);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ }
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ if ((header == NULL)||
+ (header->magicHeader != PKIX_MAGIC_HEADER)) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ *pObjectHeader = header;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_Destroy_Object
+ * DESCRIPTION:
+ *
+ * Destroys and deallocates Object pointed to by "object". The caller is
+ * assumed to hold the Object's lock, which is acquired in
+ * PKIX_PL_Object_DecRef().
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to destroy. 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_pl_Object_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#else
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* Attempt to delete an object still being used */
+ if (objectHeader->references != 0) {
+ PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
+ }
+
+ PKIX_DECREF(objectHeader->stringRep);
+
+ /* Destroy this object's lock */
+ PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
+ PR_DestroyLock(objectHeader->lock);
+ objectHeader->lock = NULL;
+ object = NULL;
+
+ objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
+#endif
+
+ PKIX_FREE(objectHeader);
+
+cleanup:
+#ifdef PKIX_OBJECT_LEAK_TEST
+fatal:
+#endif
+
+ PKIX_RETURN(OBJECT);
+}
+
+/* --Default-Callbacks-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Object_Equals_Default
+ * DESCRIPTION:
+ *
+ * Default Object_Equals callback: Compares the address of the Object pointed
+ * to by "firstObject" with the address of the Object pointed to by
+ * "secondObject" and stores the Boolean result at "pResult".
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of first Object to compare. Must be non-NULL.
+ * "secondObject"
+ * Address of second Object to compare. Must be non-NULL.
+ * "pResult"
+ * Address where Boolean result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_Equals_Default(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Just compare pointer values */
+ *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_ToString_Default
+ * DESCRIPTION:
+ *
+ * Default Object_ToString callback: Creates a string consisting of the
+ * typename and address of the Object pointed to by "object" and stores
+ * the result at "pString". The format for the string is
+ * "TypeName@Address: <address>", where the default typename is "Object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to convert to a string. Must be non-NULL.
+ * "pString"
+ * 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 Object 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_pl_Object_ToString_Default(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *descString = NULL;
+ char *format = "%s@Address: %x";
+ char *description = NULL;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext),
+ PKIX_OBJECTGETTYPEFAILED);
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if (ctEntry == NULL){
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY);
+ } else {
+ description = ctEntry->description;
+ if (description == NULL) {
+ description = "User Type Object";
+ }
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ description = systemClasses[objType].description;
+ }
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)description,
+ 0,
+ &descString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ formatString,
+ descString,
+ object),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(descString);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_Hashcode_Default
+ * DESCRIPTION:
+ *
+ * Default Object_Hashcode callback. Creates the a hashcode value using the
+ * address of the Object pointed to by "object" and stores the result at
+ * "pValue".
+ *
+ * XXX This isn't great since addresses are not uniformly distributed.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to compute hashcode for. Must be non-NULL.
+ * "pValue"
+ * Address where PKIX_UInt32 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_pl_Object_Hashcode_Default(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default");
+ PKIX_NULLCHECK_TWO(object, pValue);
+
+ *pValue = (PKIX_UInt32)((char *)object - (char *)NULL);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback
+ * DESCRIPTION:
+ *
+ * Retrieves Equals callback function of Object pointed to by "object and
+ * stores it at "pEqualsCallback". If the object's type is one of the system
+ * types, its callback function is retrieved from the systemClasses array;
+ * otherwise, its callback function is retrieve from the classTable hash
+ * table where user-defined types are stored.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose equals callback is desired. Must be non-NULL.
+ * "pEqualsCallback"
+ * Address where EqualsCallback function 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 Object 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_pl_Object_RetrieveEqualsCallback(
+ PKIX_PL_Object *object,
+ PKIX_PL_EqualsCallback *pEqualsCallback,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_EqualsCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback");
+ PKIX_NULLCHECK_TWO(object, pEqualsCallback);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = objectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
+ PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK);
+ } else {
+ *pEqualsCallback = ctEntry->equalsFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.equalsFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Equals_Default;
+ }
+ *pEqualsCallback = func;
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OBJECT_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_PL_Object should have all function pointes to be to NULL: they
+ * work as proxy function to a real objects.
+ *
+ */
+PKIX_Error *
+pkix_pl_Object_RegisterSelf(void *plContext)
+{
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf");
+
+ entry.description = "Object";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Object);
+ entry.destructor = NULL;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_OBJECT_TYPE] = entry;
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Alloc(
+ PKIX_TYPENUM objType,
+ PKIX_UInt32 size,
+ PKIX_PL_Object **pObject,
+ void *plContext)
+{
+ PKIX_PL_Object *object = NULL;
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc");
+ PKIX_NULLCHECK_ONE(pObject);
+
+ /*
+ * We need to ensure that user-defined types have been registered.
+ * All system types have already been registered by PKIX_PL_Initialize.
+ */
+
+ if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_Boolean typeRegistered;
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
+ }
+
+ typeRegistered = (ctEntry != NULL);
+
+ if (!typeRegistered) {
+ PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT);
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ ctEntry = &systemClasses[objType];
+ }
+
+ PORT_Assert(size == ctEntry->typeObjectSize);
+
+ /* Allocate space for the object header and the requested size */
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK(PKIX_PL_Calloc
+ (1,
+ ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+ (void **)&object,
+ plContext),
+ PKIX_MALLOCFAILED);
+#else
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+ (void **)&object,
+ plContext),
+ PKIX_MALLOCFAILED);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* Initialize all object fields */
+ object->magicHeader = PKIX_MAGIC_HEADER;
+ object->type = objType;
+ object->references = 1; /* Default to a single reference */
+ object->stringRep = NULL;
+ object->hashcode = 0;
+ object->hashcodeCached = 0;
+
+ /* Cannot use PKIX_PL_Mutex because it depends on Object */
+ /* Using NSPR Locks instead */
+ PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
+ object->lock = PR_NewLock();
+ if (object->lock == NULL) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+
+
+ /* Return a pointer to the user data. Need to offset by object size */
+ *pObject = object + 1;
+ object = NULL;
+
+ /* Atomically increment object counter */
+ PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter);
+
+cleanup:
+
+ PKIX_FREE(object);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_IsTypeRegistered(
+ PKIX_UInt32 objType,
+ PKIX_Boolean *pBool,
+ void *plContext)
+{
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+#endif
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered");
+ PKIX_NULLCHECK_ONE(pBool);
+
+ /* first, we handle the system types */
+ if (objType < PKIX_NUMTYPES) {
+ *pBool = PKIX_TRUE;
+ goto cleanup;
+ }
+
+#ifndef PKIX_USER_OBJECT_TYPE
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+#else
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
+ }
+
+ *pBool = (ctEntry != NULL);
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+#ifdef PKIX_USER_OBJECT_TYPE
+/*
+ * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_RegisterType(
+ PKIX_UInt32 objType,
+ char *description,
+ PKIX_PL_DestructorCallback destructor,
+ PKIX_PL_EqualsCallback equalsFunction,
+ PKIX_PL_HashcodeCallback hashcodeFunction,
+ PKIX_PL_ToStringCallback toStringFunction,
+ PKIX_PL_ComparatorCallback comparator,
+ PKIX_PL_DuplicateCallback duplicateFunction,
+ void *plContext)
+{
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ pkix_pl_Integer *key = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType");
+
+ /*
+ * System types are registered on startup by PKIX_PL_Initialize.
+ * These can not be overwritten.
+ */
+
+ if (objType < PKIX_NUMTYPES) { /* if this is a system type */
+ PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext),
+ PKIX_PRIMHASHTABLELOOKUPFAILED);
+
+ /* If the type is already registered, throw an error */
+ if (ctEntry) {
+ PKIX_ERROR(PKIX_TYPEALREADYREGISTERED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)),
+ (void **)&ctEntry,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* Set Default Values if none specified */
+
+ if (description == NULL){
+ description = "Object";
+ }
+
+ if (equalsFunction == NULL) {
+ equalsFunction = pkix_pl_Object_Equals_Default;
+ }
+
+ if (toStringFunction == NULL) {
+ toStringFunction = pkix_pl_Object_ToString_Default;
+ }
+
+ if (hashcodeFunction == NULL) {
+ hashcodeFunction = pkix_pl_Object_Hashcode_Default;
+ }
+
+ ctEntry->destructor = destructor;
+ ctEntry->equalsFunction = equalsFunction;
+ ctEntry->toStringFunction = toStringFunction;
+ ctEntry->hashcodeFunction = hashcodeFunction;
+ ctEntry->comparator = comparator;
+ ctEntry->duplicateFunction = duplicateFunction;
+ ctEntry->description = description;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (pkix_pl_Integer)),
+ (void **)&key,
+ plContext),
+ PKIX_COULDNOTMALLOCNEWKEY);
+
+ key->ht_int = objType;
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Add
+ (classTable,
+ (void *)key,
+ (void *)ctEntry,
+ objType,
+ NULL,
+ plContext),
+ PKIX_PRIMHASHTABLEADDFAILED);
+
+cleanup:
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ PKIX_RETURN(OBJECT);
+}
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+/*
+ * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_IncRef(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_NssContext *context = NULL;
+ PKIX_Int32 refCount = 0;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (plContext){
+ /*
+ * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
+ * have a header therefore we cannot verify its type before
+ * casting.
+ */
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context->arena != NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* This object should never have zero references */
+ refCount = PR_ATOMIC_INCREMENT(&objectHeader->references);
+
+ if (refCount <= 1) {
+ PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_DecRef(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Int32 refCount = 0;
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (plContext){
+ /*
+ * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
+ * have a header therefore we cannot verify its type before
+ * casting.
+ */
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context->arena != NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ refCount = PR_ATOMIC_DECREMENT(&objectHeader->references);
+
+ if (refCount == 0) {
+ PKIX_PL_DestructorCallback destructor = NULL;
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ PKIX_UInt32 objType = objectHeader->type;
+
+ /* first, special handling for system types */
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG
+ ("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORINGETTINGDESTRUCTOR);
+ }
+
+ if (ctEntry != NULL){
+ destructor = ctEntry->destructor;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ ctEntry = &systemClasses[objType];
+ destructor = ctEntry->destructor;
+ }
+
+ if (destructor != NULL){
+ /* Call destructor on user data if necessary */
+ pkixErrorResult = destructor(object, plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext);
+ pkixErrorResult = NULL;
+ }
+ }
+
+ /* Atomically decrement object counter */
+ PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter);
+
+ /* pkix_pl_Object_Destroy assumes the lock is held */
+ /* It will call unlock and destroy the object */
+ pkixErrorResult = pkix_pl_Object_Destroy(object, plContext);
+ goto cleanup;
+ }
+
+ if (refCount < 0) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+
+/*
+ * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_Object *secondObjectHeader = NULL;
+ PKIX_PL_EqualsCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (secondObject, &secondObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if hashcodes are cached but not equal, objects can't be equal */
+ if (firstObjectHeader->hashcodeCached &&
+ secondObjectHeader->hashcodeCached){
+ if (firstObjectHeader->hashcode !=
+ secondObjectHeader->hashcode){
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES) {
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&firstObjectHeader->type,
+ firstObjectHeader->type,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ } else {
+ func = ctEntry->equalsFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.equalsFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Equals_Default;
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Duplicate(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_DuplicateCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate");
+ PKIX_NULLCHECK_TWO(firstObject, pNewObject);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES) {
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ } else {
+ func = ctEntry->duplicateFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.duplicateFunction;
+ if (!func){
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION);
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, pNewObject, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_HashcodeCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objectHash;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pValue);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!objectHeader->hashcodeCached){
+
+ PKIX_UInt32 objType = objectHeader->type;
+
+ /* first, special handling for system types */
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) ||
+ (ctEntry->hashcodeFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ }
+
+ func = ctEntry->hashcodeFunction;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.hashcodeFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Hashcode_Default;
+ }
+ }
+
+ PKIX_CHECK(func(object, &objectHash, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+ if (!objectHeader->hashcodeCached){
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ if (!objectHeader->hashcodeCached){
+ /* save cached copy in case we need it again */
+ objectHeader->hashcode = objectHash;
+ objectHeader->hashcodeCached = PKIX_TRUE;
+ }
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+ }
+ }
+
+ *pValue = objectHeader->hashcode;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_ToStringCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_PL_String *objectString = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!objectHeader->stringRep){
+
+ PKIX_UInt32 objType = objectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) ||
+ (ctEntry->toStringFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ }
+
+ func = ctEntry->toStringFunction;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.toStringFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_ToString_Default;
+ }
+ }
+
+ PKIX_CHECK(func(object, &objectString, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+ if (!objectHeader->stringRep){
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ if (!objectHeader->stringRep){
+ /* save a cached copy */
+ objectHeader->stringRep = objectString;
+ objectString = NULL;
+ }
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+ }
+ }
+
+
+ *pString = objectHeader->stringRep;
+ objectHeader->stringRep = NULL;
+
+cleanup:
+ if (objectHeader) {
+ PKIX_DECREF(objectHeader->stringRep);
+ }
+ PKIX_DECREF(objectString);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_InvalidateCache(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ /* invalidate hashcode */
+ objectHeader->hashcode = 0;
+ objectHeader->hashcodeCached = PKIX_FALSE;
+
+ PKIX_DECREF(objectHeader->stringRep);
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Compare(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_Object *secondObjectHeader = NULL;
+ PKIX_PL_ComparatorCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (secondObject, &secondObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR);
+ }
+
+ func = ctEntry->comparator;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ /* special handling for system types */
+ entry = systemClasses[objType];
+ func = entry.comparator;
+ if (!func){
+ PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR);
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Lock(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_LOCKOBJECTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Unlock(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_UNLOCKOBJECTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_GetType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pType,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType");
+ PKIX_NULLCHECK_TWO(object, pType);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ *pType = objectHeader->type;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h
new file mode 100644
index 0000000000..0133c43eeb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h
@@ -0,0 +1,76 @@
+/* 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_pl_object.h
+ *
+ * Object Construction, Destruction and Callback Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OBJECT_H
+#define _PKIX_PL_OBJECT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Object Implementation Notes:
+ *
+ * Allocating a new object creates an object header and a block of
+ * uninitialized user data. A pointer to this uninitialized data is
+ * returned to the user. The structure looks as follows:
+ *
+ * +--------------------+
+ * | MAGIC HEADER |
+ * | (object header) |
+ * +--------------------+
+ * | user data | -- pointer returned from PKIX_PL_Object_Alloc
+ * +--------------------+
+ *
+ * Object operations receive a pointer to raw user data as an argument.
+ * The macro HEADER(object) returns a pointer to the object header.
+ * An assertion then verifies that the first field is the MAGIC_HEADER.
+ */
+
+/* PKIX_PL_Object Structure Definition */
+struct PKIX_PL_ObjectStruct {
+ PRUint64 magicHeader;
+ PKIX_UInt32 type;
+ PKIX_Int32 references;
+ PRLock *lock;
+ PKIX_PL_String *stringRep;
+ PKIX_UInt32 hashcode;
+ PKIX_Boolean hashcodeCached;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Object_RetrieveEqualsCallback(
+ PKIX_PL_Object *object,
+ PKIX_PL_EqualsCallback *equalsCallback,
+ void *plContext);
+
+extern PKIX_Boolean initializing;
+extern PKIX_Boolean initialized;
+
+#ifdef PKIX_USER_OBJECT_TYPE
+
+extern PRLock *classTableLock;
+
+#endif
+
+extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+
+PKIX_Error *
+pkix_pl_Object_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OBJECT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c
new file mode 100644
index 0000000000..a6e0503850
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c
@@ -0,0 +1,316 @@
+/* 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_pl_oid.c
+ *
+ * OID Object Functions
+ *
+ */
+
+#include "pkix_pl_oid.h"
+
+/* --Private-OID-Functions---------------------------------------- */
+
+ /*
+ * FUNCTION: pkix_pl_OID_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pRes,
+ void *plContext)
+{
+ PKIX_PL_OID *firstOID = NULL;
+ PKIX_PL_OID *secondOID = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pRes);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_OID_TYPE, plContext),
+ PKIX_ARGUMENTSNOTOIDS);
+
+ firstOID = (PKIX_PL_OID*)firstObject;
+ secondOID = (PKIX_PL_OID*)secondObject;
+
+ *pRes = (PKIX_Int32)SECITEM_CompareItem(&firstOID->derOid,
+ &secondOID->derOid);
+cleanup:
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+ oid = (PKIX_PL_OID*)object;
+ SECITEM_FreeItem(&oid->derOid, PR_FALSE);
+
+cleanup:
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_HashCode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+
+ oid = (PKIX_PL_OID *)object;
+
+ PKIX_CHECK(pkix_hash
+ ((unsigned char *)oid->derOid.data,
+ oid->derOid.len * sizeof (char),
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+cleanup:
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Int32 cmpResult;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_pl_OID_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_OIDCOMPARATORFAILED);
+
+ *pResult = (cmpResult == 0);
+cleanup:
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ * Use this function only for printing OIDs and not to make any
+ * critical security decision.
+ */
+static PKIX_Error *
+pkix_pl_OID_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+ char *oidString = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+ oid = (PKIX_PL_OID*)object;
+ oidString = CERT_GetOidString(&oid->derOid);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, oidString , 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+cleanup:
+ PR_smprintf_free(oidString);
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OID_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_pl_OID_RegisterSelf(
+ void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OID_TYPE];
+
+ PKIX_ENTER(OID, "pkix_pl_OID_RegisterSelf");
+
+ entry->description = "OID";
+ entry->typeObjectSize = sizeof(PKIX_PL_OID);
+ entry->destructor = pkix_pl_OID_Destroy;
+ entry->equalsFunction = pkix_pl_OID_Equals;
+ entry->hashcodeFunction = pkix_pl_OID_Hashcode;
+ entry->toStringFunction = pkix_pl_OID_ToString;
+ entry->comparator = pkix_pl_OID_Comparator;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_GetCriticalExtensionOIDs
+ * DESCRIPTION:
+ *
+ * Converts the extensions in "extensions" array that are critical to
+ * PKIX_PL_OID and returns the result as a PKIX_List in "pPidList".
+ * If there is no critical extension, an empty list is returned.
+ *
+ * PARAMETERS
+ * "extension"
+ * an array of extension pointers. May be NULL.
+ * "pOidsList"
+ * Address where the list of OIDs is returned. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL 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_pl_OID_GetCriticalExtensionOIDs(
+ CERTCertExtension **extensions,
+ PKIX_List **pOidsList,
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_ONE(pOidsList);
+
+ PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (extensions) {
+ while (*extensions) {
+ CERTCertExtension *extension = NULL;
+ SECItem *critical = NULL;
+ SECItem *oid = NULL;
+
+ extension = *extensions++;
+ /* extension is critical ? */
+ critical = &extension->critical;
+ if (critical->len == 0 || critical->data[0] == 0) {
+ continue;
+ }
+ oid = &extension->id;
+ PKIX_CHECK(
+ PKIX_PL_OID_CreateBySECItem(oid, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+ PKIX_CHECK(
+ PKIX_List_AppendItem(oidsList, (PKIX_PL_Object *)pkixOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(pkixOID);
+ }
+ }
+
+ *pOidsList = oidsList;
+ oidsList = NULL;
+
+cleanup:
+ PKIX_DECREF(oidsList);
+ PKIX_DECREF(pkixOID);
+ PKIX_RETURN(OID);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_OID_CreateBySECItem (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_OID_CreateBySECItem(
+ SECItem *derOid,
+ PKIX_PL_OID **pOID,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(OID, "PKIX_PL_OID_CreateBySECItem");
+ PKIX_NULLCHECK_TWO(pOID, derOid);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OID_TYPE,
+ sizeof (PKIX_PL_OID),
+ (PKIX_PL_Object **)&oid,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+ rv = SECITEM_CopyItem(NULL, &oid->derOid, derOid);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ *pOID = oid;
+ oid = NULL;
+
+cleanup:
+ PKIX_DECREF(oid);
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OID_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_OID_Create(
+ SECOidTag idtag,
+ PKIX_PL_OID **pOID,
+ void *plContext)
+{
+ SECOidData *oidData = NULL;
+
+ PKIX_ENTER(OID, "PKIX_PL_OID_Create");
+ PKIX_NULLCHECK_ONE(pOID);
+
+ oidData = SECOID_FindOIDByTag((SECOidTag)idtag);
+ if (!oidData) {
+ PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED);
+ }
+
+ pkixErrorResult =
+ PKIX_PL_OID_CreateBySECItem(&oidData->oid, pOID, plContext);
+cleanup:
+ PKIX_RETURN(OID);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h
new file mode 100644
index 0000000000..0229194d84
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h
@@ -0,0 +1,39 @@
+/* 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_pl_oid.h
+ *
+ * OID Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OID_H
+#define _PKIX_PL_OID_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OIDStruct {
+ SECItem derOid;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_OID_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_OID_GetCriticalExtensionOIDs(
+ CERTCertExtension **extensions,
+ PKIX_List **pOidsList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OID_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c
new file mode 100644
index 0000000000..c920533d37
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c
@@ -0,0 +1,584 @@
+/* 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_pl_primhash.c
+ *
+ * Primitive (non-object) Hashtable Functions
+ *
+ */
+
+#include "pkix_pl_primhash.h"
+
+/* --Private-Functions---------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_KeyComparator_Default
+ * DESCRIPTION:
+ *
+ * Compares the integer pointed to by "firstKey" with the integer pointed to
+ * by "secondKey" for equality and stores the Boolean result at "pResult".
+ * This default key comparator assumes each key is a PKIX_UInt32, and it
+ * simply tests them for equality.
+ *
+ * PARAMETERS:
+ * "firstKey"
+ * Address of the first integer key to compare. Must be non-NULL.
+ * The EqualsCallback for this Object will be called.
+ * "secondKey"
+ * Address of the second integer key to compare. Must be non-NULL.
+ * "pResult"
+ * 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 Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_KeyComparator_Default(
+ PKIX_UInt32 *firstKey,
+ PKIX_UInt32 *secondKey,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ /* Assume both keys are pointers to PKIX_UInt32 */
+ PKIX_UInt32 firstInt, secondInt;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_KeyComparator_Default");
+ PKIX_NULLCHECK_THREE(firstKey, secondKey, pResult);
+
+ firstInt = *firstKey;
+ secondInt = *secondKey;
+
+ *pResult = (firstInt == secondInt)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Create
+ * DESCRIPTION:
+ *
+ * Creates a new PrimHashtable object with a number of buckets equal to
+ * "numBuckets" and stores the result at "pResult".
+ *
+ * PARAMETERS:
+ * "numBuckets"
+ * The number of hash table buckets. Must be non-zero.
+ * "pResult"
+ * Address where PrimHashTable 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_pl_PrimHashTable_Create(
+ PKIX_UInt32 numBuckets,
+ pkix_pl_PrimHashTable **pResult,
+ void *plContext)
+{
+ pkix_pl_PrimHashTable *primHashTable = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Create");
+ PKIX_NULLCHECK_ONE(pResult);
+
+ if (numBuckets == 0) {
+ PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
+ }
+
+ /* Allocate a new hashtable */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (pkix_pl_PrimHashTable),
+ (void **)&primHashTable,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ primHashTable->size = numBuckets;
+
+ /* Allocate space for the buckets */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numBuckets * sizeof (pkix_pl_HT_Elem*),
+ (void **)&primHashTable->buckets,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < numBuckets; i++) {
+ primHashTable->buckets[i] = NULL;
+ }
+
+ *pResult = primHashTable;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(primHashTable);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Add
+ * DESCRIPTION:
+ *
+ * Adds the value pointed to by "value" to the PrimHashTable pointed to by
+ * "ht" using the key pointed to by "key" and the hashCode value equal to
+ * "hashCode", using the function pointed to by "keyComp" to compare keys.
+ * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value
+ * already exists in the hashtable, this function returns a non-fatal error.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to insert into. Must be non-NULL.
+ * "key"
+ * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "value"
+ * Address of Object to be added to PrimHashtable. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable 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_pl_PrimHashTable_Add(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ void *value,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void *plContext)
+{
+ pkix_pl_HT_Elem **elemPtr = NULL;
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Add");
+ PKIX_NULLCHECK_THREE(ht, key, value);
+
+ for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
+ element != NULL; elemPtr = &(element->next), element = *elemPtr) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ PKIX_CHECK(keyComp
+ ((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ /* Same key already exists in the table */
+ PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY);
+ }
+ }
+
+ /* Next Element should be NULL at this point */
+ if (element != NULL) {
+ PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET);
+ }
+
+ /* Create a new HT_Elem */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (pkix_pl_HT_Elem), (void **)elemPtr, plContext),
+ PKIX_MALLOCFAILED);
+
+ element = *elemPtr;
+
+ element->key = key;
+ element->value = value;
+ element->hashCode = hashCode;
+ element->next = NULL;
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Remove
+ * DESCRIPTION:
+ *
+ * Removes any objects with the key pointed to by "key" and hashCode value
+ * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
+ * function pointed to by "keyComp" to compare keys, and stores the object's
+ * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
+ * This function sets "pResult" to NULL if the key is not in the hashtable.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to remove object. Must be non-NULL.
+ * "key"
+ * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "value"
+ * Address of Object to be added to PrimHashtable. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "pResult"
+ * Address where value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable 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_pl_PrimHashTable_Remove(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pKey,
+ void **pValue,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ pkix_pl_HT_Elem *prior = NULL;
+ PKIX_Boolean compResult;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
+ PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue);
+
+ *pKey = NULL;
+ *pValue = NULL;
+
+ for (element = ht->buckets[hashCode%ht->size], prior = element;
+ (element != NULL);
+ prior = element, element = element->next) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ PKIX_CHECK(keyComp
+ ((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ if (element != prior) {
+ prior->next = element->next;
+ } else {
+ ht->buckets[hashCode%ht->size] = element->next;
+ }
+ *pKey = element->key;
+ *pValue = element->value;
+ element->key = NULL;
+ element->value = NULL;
+ element->next = NULL;
+ PKIX_FREE(element);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_HashTableLookup
+ * DESCRIPTION:
+ *
+ * Looks up object using the key pointed to by "key" and hashCode value
+ * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
+ * function pointed to by "keyComp" to compare keys, and stores the object's
+ * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
+ * This function sets "pResult" to NULL if the key is not in the hashtable.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to lookup object from. Must be non-NULL.
+ * "key"
+ * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pResult"
+ * Address where value 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.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Lookup(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pResult,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Lookup");
+ PKIX_NULLCHECK_THREE(ht, key, pResult);
+
+ *pResult = NULL;
+
+ for (element = (ht->buckets)[hashCode%ht->size];
+ (element != NULL) && (*pResult == NULL);
+ element = element->next) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ pkixErrorResult =
+ keyComp((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ pkixErrorCode = PKIX_COULDNOTTESTWHETHERKEYSEQUAL;
+ goto cleanup;
+ }
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ *pResult = element->value;
+ goto cleanup;
+ }
+ }
+
+ /* if we've reached here, specified key doesn't exist in hashtable */
+ *pResult = NULL;
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Destroy
+ *
+ * Destroys PrimHashTable pointed to by "ht".
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to free. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable 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_pl_PrimHashTable_Destroy(
+ pkix_pl_PrimHashTable *ht,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ pkix_pl_HT_Elem *temp = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Destroy");
+ PKIX_NULLCHECK_ONE(ht);
+
+ /* Free each element (list) */
+ for (i = 0; i < ht->size; i++) {
+ for (element = ht->buckets[i];
+ element != NULL;
+ element = temp) {
+ temp = element->next;
+ element->value = NULL;
+ element->key = NULL;
+ element->hashCode = 0;
+ element->next = NULL;
+ PKIX_FREE(element);
+ }
+ }
+
+ /* Free the pointer to the list array */
+ PKIX_FREE(ht->buckets);
+ ht->size = 0;
+
+ /* Free the table itself */
+ PKIX_FREE(ht);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize
+ * DESCRIPTION:
+ *
+ * Retruns number of entries in the bucket the "hashCode" is designated in
+ * the hashtable "ht" in the address "pBucketSize".
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to get entries count. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pBucketSize"
+ * Address that an PKIX_UInt32 is returned for number of entries in the
+ * bucket associated with the hashCode. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable 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_pl_PrimHashTable_GetBucketSize(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ PKIX_UInt32 *pBucketSize,
+ void *plContext)
+{
+ pkix_pl_HT_Elem **elemPtr = NULL;
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_UInt32 bucketSize = 0;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_GetBucketSize");
+ PKIX_NULLCHECK_TWO(ht, pBucketSize);
+
+ for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
+ element != NULL; elemPtr = &(element->next), element = *elemPtr) {
+ bucketSize++;
+ }
+
+ *pBucketSize = bucketSize;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
+ * DESCRIPTION:
+ *
+ * Remove the first entry in the bucket the "hashCode" is designated in
+ * the hashtable "ht". Since new entry is added at end of the link list
+ * the first one is the oldest (FI) therefore removed first (FO).
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to get entries count. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pKey"
+ * Address of key of the entry deleted. Must be non-NULL.
+ * "pValue"
+ * Address of Value of the entry deleted. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable 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_pl_PrimHashTable_RemoveFIFO(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ void **pKey,
+ void **pValue,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
+ PKIX_NULLCHECK_THREE(ht, pKey, pValue);
+
+ element = (ht->buckets)[hashCode%ht->size];
+
+ if (element != NULL) {
+
+ *pKey = element->key;
+ *pValue = element->value;
+ ht->buckets[hashCode%ht->size] = element->next;
+ element->key = NULL;
+ element->value = NULL;
+ element->next = NULL;
+ PKIX_FREE(element);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h
new file mode 100644
index 0000000000..b889e2e91e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h
@@ -0,0 +1,102 @@
+/* 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_pl_primhash.h
+ *
+ * Primitive Hashtable Definition
+ *
+ */
+
+#ifndef _PKIX_PL_PRIMHASH_H
+#define _PKIX_PL_PRIMHASH_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_pl_HT_Elem pkix_pl_HT_Elem;
+
+typedef struct pkix_pl_PrimHashTable pkix_pl_PrimHashTable;
+
+typedef struct pkix_pl_Integer pkix_pl_Integer;
+
+struct pkix_pl_Integer{
+ PKIX_UInt32 ht_int;
+};
+
+struct pkix_pl_HT_Elem {
+ void *key;
+ void *value;
+ PKIX_UInt32 hashCode;
+ pkix_pl_HT_Elem *next;
+};
+
+struct pkix_pl_PrimHashTable {
+ pkix_pl_HT_Elem **buckets;
+ PKIX_UInt32 size;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Create(
+ PKIX_UInt32 numBuckets,
+ pkix_pl_PrimHashTable **pResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Add(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ void *value,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Remove(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pKey,
+ void **pValue,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Lookup(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pResult,
+ void *plContext);
+
+PKIX_Error*
+pkix_pl_PrimHashTable_Destroy(
+ pkix_pl_PrimHashTable *ht,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_GetBucketSize(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ PKIX_UInt32 *pBucketSize,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_RemoveFIFO(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ void **pKey,
+ void **pValue,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PRIMHASH_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c
new file mode 100644
index 0000000000..662931e981
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c
@@ -0,0 +1,217 @@
+/* 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_pl_rwlock.c
+ *
+ * Read/Write Lock Functions
+ *
+ */
+
+#include "pkix_pl_rwlock.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+static PKIX_Error *
+pkix_pl_RWLock_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_RWLock* rwlock = NULL;
+
+ PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RWLOCK_TYPE, plContext),
+ PKIX_OBJECTNOTRWLOCK);
+
+ rwlock = (PKIX_PL_RWLock*) object;
+
+ PKIX_RWLOCK_DEBUG("Calling PR_DestroyRWLock)\n");
+ PR_DestroyRWLock(rwlock->lock);
+ rwlock->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+/*
+ * FUNCTION: pkix_pl_RWLock_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_RWLOCK_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_pl_RWLock_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_RegisterSelf");
+
+ entry.description = "RWLock";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_RWLock);
+ entry.destructor = pkix_pl_RWLock_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_RWLOCK_TYPE] = entry;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+PKIX_Error *
+PKIX_PL_RWLock_Create(
+ PKIX_PL_RWLock **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_RWLock *rwLock = NULL;
+
+ PKIX_ENTER(RWLOCK, "PKIX_PL_RWLock_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_RWLOCK_TYPE,
+ sizeof (PKIX_PL_RWLock),
+ (PKIX_PL_Object **)&rwLock,
+ plContext),
+ PKIX_ERRORALLOCATINGRWLOCK);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_NewRWLock)\n");
+ rwLock->lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "PKIX RWLock");
+
+ if (rwLock->lock == NULL) {
+ PKIX_DECREF(rwLock);
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ rwLock->readCount = 0;
+ rwLock->writeLocked = PKIX_FALSE;
+
+ *pNewLock = rwLock;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_AcquireReaderLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireReaderLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Rlock)\n");
+ (void) PR_RWLock_Rlock(lock->lock);
+
+ lock->readCount++;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_ReleaseReaderLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseReaderLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
+ (void) PR_RWLock_Unlock(lock->lock);
+
+ lock->readCount--;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_IsReaderLockHeld(
+ PKIX_PL_RWLock *lock,
+ PKIX_Boolean *pIsHeld,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_IsReaderLockHeld");
+ PKIX_NULLCHECK_TWO(lock, pIsHeld);
+
+ *pIsHeld = (lock->readCount > 0)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_AcquireWriterLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireWriterLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Wlock\n");
+ (void) PR_RWLock_Wlock(lock->lock);
+
+ if (lock->readCount > 0) {
+ PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
+ }
+
+ /* We should never acquire a write lock if the lock is held */
+ lock->writeLocked = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_ReleaseWriterLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseWriterLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ if (lock->readCount > 0) {
+ PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
+ }
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
+ (void) PR_RWLock_Unlock(lock->lock);
+
+ /* XXX Need to think about thread safety here */
+ /* There should be a single lock holder */
+ lock->writeLocked = PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_IsWriterLockHeld(
+ PKIX_PL_RWLock *lock,
+ PKIX_Boolean *pIsHeld,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_IsWriterLockHeld");
+ PKIX_NULLCHECK_TWO(lock, pIsHeld);
+
+ *pIsHeld = lock->writeLocked;
+
+ PKIX_RETURN(RWLOCK);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h
new file mode 100644
index 0000000000..fd64659506
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_rwlock.h
+ *
+ * Read/Write Lock Definition
+ *
+ */
+
+#ifndef _PKIX_PL_RWLOCK_H
+#define _PKIX_PL_RWLOCK_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_RWLockStruct {
+ PRRWLock* lock;
+ PKIX_UInt32 readCount;
+ PKIX_Boolean writeLocked;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_RWLock_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_RWLOCK_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c
new file mode 100644
index 0000000000..167382466e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c
@@ -0,0 +1,628 @@
+/* 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_pl_string.c
+ *
+ * String Object Functions
+ *
+ */
+
+#include "pkix_pl_string.h"
+
+/* --Private-String-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_String_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ *
+ * NOTE:
+ * This function is a utility function called by pkix_pl_String_Equals().
+ * It is not officially registered as a comparator.
+ */
+static PKIX_Error *
+pkix_pl_String_Comparator(
+ PKIX_PL_String *firstString,
+ PKIX_PL_String *secondString,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i;
+ PKIX_Int32 result;
+ unsigned char *p1 = NULL;
+ unsigned char *p2 = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Comparator");
+ PKIX_NULLCHECK_THREE(firstString, secondString, pResult);
+
+ result = 0;
+
+ p1 = (unsigned char*) firstString->utf16String;
+ p2 = (unsigned char*) secondString->utf16String;
+
+ /* Compare characters until you find a difference */
+ for (i = 0; ((i < firstString->utf16Length) &&
+ (i < secondString->utf16Length) &&
+ result == 0); i++, p1++, p2++) {
+ if (*p1 < *p2){
+ result = -1;
+ } else if (*p1 > *p2){
+ result = 1;
+ }
+ }
+
+ /* If two arrays are identical so far, the longer one is greater */
+ if (result == 0) {
+ if (firstString->utf16Length < secondString->utf16Length) {
+ result = -1;
+ } else if (firstString->utf16Length >
+ secondString->utf16Length) {
+ result = 1;
+ }
+ }
+
+ *pResult = result;
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_ARGUMENTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ /* XXX For debugging Destroy EscASCII String */
+ if (string->escAsciiString != NULL) {
+ PKIX_FREE(string->escAsciiString);
+ string->escAsciiString = NULL;
+ string->escAsciiLength = 0;
+ }
+
+ /* Destroy UTF16 String */
+ if (string->utf16String != NULL) {
+ PKIX_FREE(string->utf16String);
+ string->utf16String = NULL;
+ string->utf16Length = 0;
+ }
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_ARGUMENTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (string, PKIX_ESCASCII, (void **)&ascii, &length, plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, ascii, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ goto cleanup;
+
+cleanup:
+
+ PKIX_FREE(ascii);
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Sanity check: Test that "firstObject" is a Strings */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_STRING_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTSTRING);
+
+ /* "SecondObject" doesn't have to be a string */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ /* If types differ, then we will return false */
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_STRING_TYPE) goto cleanup;
+
+ /* It's safe to cast here */
+ PKIX_CHECK(pkix_pl_String_Comparator
+ ((PKIX_PL_String*)firstObject,
+ (PKIX_PL_String*)secondObject,
+ &cmpResult,
+ plContext),
+ PKIX_STRINGCOMPARATORFAILED);
+
+ /* Strings are equal iff Comparator Result is 0 */
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_OBJECTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)string->utf16String,
+ string->utf16Length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_STRING_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_pl_String_RegisterSelf(
+ void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_RegisterSelf");
+
+ entry.description = "String";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_String);
+ entry.destructor = pkix_pl_String_Destroy;
+ entry.equalsFunction = pkix_pl_String_Equals;
+ entry.hashcodeFunction = pkix_pl_String_Hashcode;
+ entry.toStringFunction = pkix_pl_String_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_STRING_TYPE] = entry;
+
+ PKIX_RETURN(STRING);
+}
+
+
+/* --Public-String-Functions----------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_String_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_String_Create(
+ PKIX_UInt32 fmtIndicator,
+ const void *stringRep,
+ PKIX_UInt32 stringLen,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+ unsigned char *utf16Char = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(STRING, "PKIX_PL_String_Create");
+ PKIX_NULLCHECK_TWO(pString, stringRep);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_STRING_TYPE,
+ sizeof (PKIX_PL_String),
+ (PKIX_PL_Object **)&string,
+ plContext),
+ PKIX_COULDNOTALLOCATENEWSTRINGOBJECT);
+
+ string->utf16String = NULL;
+ string->utf16Length = 0;
+
+ /* XXX For Debugging */
+ string->escAsciiString = NULL;
+ string->escAsciiLength = 0;
+
+ switch (fmtIndicator) {
+ case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG:
+ PKIX_STRING_DEBUG("\tCalling PL_strlen).\n");
+ string->escAsciiLength = PL_strlen(stringRep);
+
+ /* XXX Cache for Debugging */
+ PKIX_CHECK(PKIX_PL_Malloc
+ ((string->escAsciiLength)+1,
+ (void **)&string->escAsciiString,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ (void) PORT_Memcpy
+ (string->escAsciiString,
+ (void *)((char *)stringRep),
+ (string->escAsciiLength)+1);
+
+ /* Convert the EscASCII string to UTF16 */
+ PKIX_CHECK(pkix_EscASCII_to_UTF16
+ (string->escAsciiString,
+ string->escAsciiLength,
+ (fmtIndicator == PKIX_ESCASCII_DEBUG),
+ &string->utf16String,
+ &string->utf16Length,
+ plContext),
+ PKIX_ESCASCIITOUTF16FAILED);
+ break;
+ case PKIX_UTF8:
+ /* Convert the UTF8 string to UTF16 */
+ PKIX_CHECK(pkix_UTF8_to_UTF16
+ (stringRep,
+ stringLen,
+ &string->utf16String,
+ &string->utf16Length,
+ plContext),
+ PKIX_UTF8TOUTF16FAILED);
+ break;
+ case PKIX_UTF16:
+ /* UTF16 Strings must be even in length */
+ if (stringLen%2 == 1) {
+ PKIX_DECREF(string);
+ PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR);
+ }
+
+ utf16Char = (unsigned char *)stringRep;
+
+ /* Make sure this is a valid UTF-16 String */
+ for (i = 0; \
+ (i < stringLen) && (pkixErrorResult == NULL); \
+ i += 2) {
+ /* Check that surrogate pairs are valid */
+ if ((utf16Char[i] >= 0xD8)&&
+ (utf16Char[i] <= 0xDB)) {
+ if ((i+2) >= stringLen) {
+ PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR);
+ /* Second pair should be DC00-DFFF */
+ } else if (!((utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF))) {
+ PKIX_ERROR(PKIX_UTF16LOWZONEERROR);
+ } else {
+ /* Surrogate quartet is valid. */
+ i += 2;
+ }
+ }
+ }
+
+ /* Create UTF16 String */
+ string->utf16Length = stringLen;
+
+ /* Alloc space for string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (stringLen, &string->utf16String, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy
+ (string->utf16String, stringRep, stringLen);
+ break;
+
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNFORMAT);
+ }
+
+ *pString = string;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(string);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Sprintf (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Sprintf(
+ PKIX_PL_String **pOut,
+ void *plContext,
+ const PKIX_PL_String *fmt,
+ ...)
+{
+ PKIX_PL_String *tempString = NULL;
+ PKIX_UInt32 tempUInt = 0;
+ void *pArg = NULL;
+ char *asciiText = NULL;
+ char *asciiFormat = NULL;
+ char *convertedAsciiFormat = NULL;
+ char *convertedAsciiFormatBase = NULL;
+ va_list args;
+ PKIX_UInt32 length, i, j, dummyLen;
+
+ PKIX_ENTER(STRING, "PKIX_PL_Sprintf");
+ PKIX_NULLCHECK_TWO(pOut, fmt);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ ((PKIX_PL_String *)fmt,
+ PKIX_ESCASCII,
+ (void **)&asciiFormat,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PR_Malloc).\n");
+ convertedAsciiFormat = PR_Malloc(length + 1);
+ if (convertedAsciiFormat == NULL)
+ PKIX_ERROR_ALLOC_ERROR();
+
+ convertedAsciiFormatBase = convertedAsciiFormat;
+
+ PKIX_STRING_DEBUG("\tCalling va_start).\n");
+ va_start(args, fmt);
+
+ i = 0;
+ j = 0;
+ while (i < length) {
+ if ((asciiFormat[i] == '%')&&((i+1) < length)) {
+ switch (asciiFormat[i+1]) {
+ case 's':
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j] = '\0';
+
+ tempString = va_arg(args, PKIX_PL_String *);
+ if (tempString != NULL) {
+ PKIX_CHECK_NO_GOTO(
+ PKIX_PL_String_GetEncoded
+ ((PKIX_PL_String*)
+ tempString,
+ PKIX_ESCASCII,
+ &pArg,
+ &dummyLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ /* need to cleanup var args before
+ * we ditch out to cleanup. */
+ if (pkixErrorResult) {
+ va_end(args);
+ goto cleanup;
+ }
+ } else {
+ /* there may be a NULL in var_args */
+ pArg = NULL;
+ }
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat,
+ pArg);
+ } else {
+ asciiText = PR_smprintf
+ ((const char *)convertedAsciiFormat,
+ pArg);
+ }
+ if (pArg != NULL) {
+ PKIX_PL_Free(pArg, plContext);
+ pArg = NULL;
+ }
+ convertedAsciiFormat += j;
+ j = 0;
+ break;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j] = '\0';
+
+ tempUInt = va_arg(args, PKIX_UInt32);
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat,
+ tempUInt);
+ } else {
+ asciiText = PR_smprintf
+ ((const char *)convertedAsciiFormat,
+ tempUInt);
+ }
+ convertedAsciiFormat += j;
+ j = 0;
+ break;
+ default:
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ break;
+ }
+ } else {
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ }
+ }
+
+ /* for constant string value at end of fmt */
+ if (j > 0) {
+ convertedAsciiFormat[j] = '\0';
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat);
+ } else {
+ asciiText = PR_smprintf((const char *)convertedAsciiFormat);
+ }
+ }
+
+ va_end(args);
+
+ /* Copy temporary char * into a string object */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, (void *)asciiText, 0, pOut, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_FREE(asciiFormat);
+
+ if (convertedAsciiFormatBase){
+ PR_Free(convertedAsciiFormatBase);
+ }
+
+ if (asciiText){
+ PKIX_STRING_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(asciiText);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_GetString (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_GetString(
+ /* ARGSUSED */ PKIX_UInt32 stringID,
+ char *defaultString,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ENTER(STRING, "PKIX_PL_GetString");
+ PKIX_NULLCHECK_TWO(pString, defaultString);
+
+ /* XXX Optimization - use stringID for caching */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, defaultString, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_String_GetEncoded (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_String_GetEncoded(
+ PKIX_PL_String *string,
+ PKIX_UInt32 fmtIndicator,
+ void **pStringRep,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(STRING, "PKIX_PL_String_GetEncoded");
+ PKIX_NULLCHECK_THREE(string, pStringRep, pLength);
+
+ switch (fmtIndicator) {
+ case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG:
+ PKIX_CHECK(pkix_UTF16_to_EscASCII
+ (string->utf16String,
+ string->utf16Length,
+ (fmtIndicator == PKIX_ESCASCII_DEBUG),
+ (char **)pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOESCASCIIFAILED);
+ break;
+ case PKIX_UTF8:
+ PKIX_CHECK(pkix_UTF16_to_UTF8
+ (string->utf16String,
+ string->utf16Length,
+ PKIX_FALSE,
+ pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOUTF8FAILED);
+ break;
+ case PKIX_UTF8_NULL_TERM:
+ PKIX_CHECK(pkix_UTF16_to_UTF8
+ (string->utf16String,
+ string->utf16Length,
+ PKIX_TRUE,
+ pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOUTF8FAILED);
+ break;
+ case PKIX_UTF16:
+ *pLength = string->utf16Length;
+
+ PKIX_CHECK(PKIX_PL_Malloc(*pLength, pStringRep, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(*pStringRep, string->utf16String, *pLength);
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNFORMAT);
+ }
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h
new file mode 100644
index 0000000000..9270e4c567
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h
@@ -0,0 +1,37 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_string.h
+ *
+ * String Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_STRING_H
+#define _PKIX_PL_STRING_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_StringStruct {
+ void* utf16String;
+ PKIX_UInt32 utf16Length;
+ /* XXX For Debugging */
+ char* escAsciiString;
+ PKIX_UInt32 escAsciiLength;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_String_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_STRING_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp
new file mode 100644
index 0000000000..32daec93d6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixsystem',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_pl_bigint.c',
+ 'pkix_pl_bytearray.c',
+ 'pkix_pl_common.c',
+ 'pkix_pl_error.c',
+ 'pkix_pl_hashtable.c',
+ 'pkix_pl_lifecycle.c',
+ 'pkix_pl_mem.c',
+ 'pkix_pl_monitorlock.c',
+ 'pkix_pl_mutex.c',
+ 'pkix_pl_object.c',
+ 'pkix_pl_oid.c',
+ 'pkix_pl_primhash.c',
+ 'pkix_pl_rwlock.c',
+ 'pkix_pl_string.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file