From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../nss/lib/libpkix/pkix_pl_nss/system/Makefile | 47 + .../nss/lib/libpkix/pkix_pl_nss/system/exports.gyp | 37 + .../nss/lib/libpkix/pkix_pl_nss/system/manifest.mn | 43 + .../libpkix/pkix_pl_nss/system/pkix_pl_bigint.c | 398 ++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_bigint.h | 40 + .../libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c | 504 +++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h | 40 + .../libpkix/pkix_pl_nss/system/pkix_pl_common.c | 1073 +++++++++++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_common.h | 159 +++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c | 26 + .../libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c | 383 ++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h | 29 + .../libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c | 279 ++++ .../libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h | 91 ++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c | 168 +++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h | 24 + .../pkix_pl_nss/system/pkix_pl_monitorlock.c | 136 ++ .../pkix_pl_nss/system/pkix_pl_monitorlock.h | 33 + .../lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c | 163 +++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h | 33 + .../libpkix/pkix_pl_nss/system/pkix_pl_object.c | 1440 ++++++++++++++++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_object.h | 76 ++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c | 316 +++++ .../lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h | 39 + .../libpkix/pkix_pl_nss/system/pkix_pl_primhash.c | 584 ++++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_primhash.h | 102 ++ .../libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c | 217 +++ .../libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h | 35 + .../libpkix/pkix_pl_nss/system/pkix_pl_string.c | 628 +++++++++ .../libpkix/pkix_pl_nss/system/pkix_pl_string.h | 37 + .../nss/lib/libpkix/pkix_pl_nss/system/system.gyp | 36 + 31 files changed, 7216 insertions(+) create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/Makefile create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h create mode 100644 security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp (limited to 'security/nss/lib/libpkix/pkix_pl_nss/system') 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 & */ + 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, "&") == + escAsciiString+i) { + /* Convert EscAscii "&" 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 & */ + if (pkix_isPlaintext(escAsciiString[i], debug)) { + *destPtr++ = 0x00; + *destPtr++ = escAsciiString[i++]; + } else if (PL_strstr(escAsciiString+i, "&") == + escAsciiString+i) { + /* Convert EscAscii "&" 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:
", 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 -- cgit v1.2.3