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