diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c')
-rwxr-xr-x | security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c | 504 |
1 files changed, 504 insertions, 0 deletions
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 100755 index 000000000..0a2e9c08f --- /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); +} |