From 562b6fcfd01d16f4268028a641ce95b4d8de2223 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 27 Apr 2011 16:19:57 -0700 Subject: [PATCH] Use OpenSSL's bignum library --- CMakeLists.txt | 3 + Sources/Plasma/CoreLibExe/CMakeLists.txt | 3 +- .../FeatureLib/pfAnimation/CMakeLists.txt | 5 - .../Plasma/FeatureLib/pfAudio/CMakeLists.txt | 1 - .../Plasma/FeatureLib/pfCamera/CMakeLists.txt | 2 - .../FeatureLib/pfCharacter/CMakeLists.txt | 2 - .../FeatureLib/pfConsole/CMakeLists.txt | 1 - .../pfConsoleCore/pfConsoleCommandsCore.cpp | 16 - .../FeatureLib/pfGameMgr/CMakeLists.txt | 2 - .../FeatureLib/pfJournalBook/CMakeLists.txt | 2 - .../Plasma/FeatureLib/pfPython/CMakeLists.txt | 1 - .../Plasma/NucleusLib/pnNetCli/pnNcCli.cpp | 9 +- .../Plasma/NucleusLib/pnUtils/CMakeLists.txt | 2 - .../NucleusLib/pnUtils/Private/pnUtBigNum.cpp | 1358 +---------------- .../NucleusLib/pnUtils/Private/pnUtBigNum.h | 201 ++- .../plAgeDescription/CMakeLists.txt | 2 - .../PubUtilLib/plAgeLoader/CMakeLists.txt | 2 - .../Plasma/PubUtilLib/plAvatar/CMakeLists.txt | 1 - .../PubUtilLib/plEncryption/CMakeLists.txt | 2 - .../Plasma/PubUtilLib/plGLight/CMakeLists.txt | 2 - .../PubUtilLib/plInputCore/CMakeLists.txt | 1 - .../PubUtilLib/plModifier/CMakeLists.txt | 1 - .../PubUtilLib/plNetClient/CMakeLists.txt | 2 - .../PubUtilLib/plNetClientComm/CMakeLists.txt | 2 - .../PubUtilLib/plNetTransport/CMakeLists.txt | 2 - .../Plasma/PubUtilLib/plPhysX/CMakeLists.txt | 1 - .../PubUtilLib/plStatGather/CMakeLists.txt | 2 - Sources/Tools/MaxMain/CMakeLists.txt | 1 - 28 files changed, 220 insertions(+), 1409 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9709e638..32e72045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,5 +82,8 @@ if(MSVC) add_definitions(-D_SCL_SECURE_NO_WARNINGS) endif(MSVC) +#TODO: Make the OpenSSL includes less promiscuous so this isn't needed +include_directories(${OPENSSL_INCLUDE_DIR}) + add_subdirectory(Sources/Plasma) add_subdirectory(Sources/Tools) diff --git a/Sources/Plasma/CoreLibExe/CMakeLists.txt b/Sources/Plasma/CoreLibExe/CMakeLists.txt index 9141605f..30caf2bf 100644 --- a/Sources/Plasma/CoreLibExe/CMakeLists.txt +++ b/Sources/Plasma/CoreLibExe/CMakeLists.txt @@ -1,6 +1,7 @@ -include_directories("../../Plasma/CoreLib") add_definitions(-D_LIB) +include_directories("../../Plasma/CoreLib") + set(CoreLibExe_SOURCES hsExeError.cpp hsExeMalloc.cpp diff --git a/Sources/Plasma/FeatureLib/pfAnimation/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfAnimation/CMakeLists.txt index 08d90741..36bcd4f3 100644 --- a/Sources/Plasma/FeatureLib/pfAnimation/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfAnimation/CMakeLists.txt @@ -3,11 +3,6 @@ include_directories("../../NucleusLib") include_directories("../../NucleusLib/inc") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - -# this is in the vcproj, but it seems silly for animation... -# find_package(OpenSSL REQUIRED) - set(pfAnimation_SOURCES pfObjectFlocker.cpp plAnimDebugList.cpp diff --git a/Sources/Plasma/FeatureLib/pfAudio/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfAudio/CMakeLists.txt index 31350f2f..a5f69bef 100644 --- a/Sources/Plasma/FeatureLib/pfAudio/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfAudio/CMakeLists.txt @@ -5,7 +5,6 @@ include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) #include_directories(../../PubUtilLib/inc) -include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) set(pfAudio_SOURCES diff --git a/Sources/Plasma/FeatureLib/pfCamera/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfCamera/CMakeLists.txt index d228365f..5b0c80f2 100644 --- a/Sources/Plasma/FeatureLib/pfCamera/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfCamera/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -include_directories(${OPENSSL_INCLUDE_DIR}) - set(pfCamera_SOURCES pfCameraProxy.cpp plCameraBrain.cpp diff --git a/Sources/Plasma/FeatureLib/pfCharacter/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfCharacter/CMakeLists.txt index 8a4535e7..3f6fd895 100644 --- a/Sources/Plasma/FeatureLib/pfCharacter/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfCharacter/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -include_directories(${OPENSSL_INCLUDE_DIR}) - set(pfCharacter_SOURCES pfMarkerInfo.cpp pfMarkerMgr.cpp diff --git a/Sources/Plasma/FeatureLib/pfConsole/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfConsole/CMakeLists.txt index b44a8b9b..e8b2c3dd 100644 --- a/Sources/Plasma/FeatureLib/pfConsole/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfConsole/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) include_directories(${PYTHON_INCLUDE_DIR}) diff --git a/Sources/Plasma/FeatureLib/pfConsoleCore/pfConsoleCommandsCore.cpp b/Sources/Plasma/FeatureLib/pfConsoleCore/pfConsoleCommandsCore.cpp index 644d089a..52c6f00d 100644 --- a/Sources/Plasma/FeatureLib/pfConsoleCore/pfConsoleCommandsCore.cpp +++ b/Sources/Plasma/FeatureLib/pfConsoleCore/pfConsoleCommandsCore.cpp @@ -61,14 +61,6 @@ void PrintStringF(void pfun(const char *),const char * fmt, ...) * ***/ -//TODO: Fix Plasma to use OpenSSL's byte order (or better yet, to use OpenSSL), -// so this hack isn't needed -static void swap_key_bytes(byte keyData[]) -{ - for (size_t i = 0; i < (kNetDiffieHellmanKeyBits / 16); ++i) - std::swap(keyData[i], keyData[ (kNetDiffieHellmanKeyBits / 8) - i - 1 ]); -} - //============================================================================ // Server group PF_CONSOLE_GROUP(Server) @@ -159,7 +151,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kAuthDhNData); - swap_key_bytes(kAuthDhNData); } //============================================================================ @@ -178,7 +169,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kAuthDhXData); - swap_key_bytes(kAuthDhXData); } @@ -214,7 +204,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kCsrDhNData); - swap_key_bytes(kCsrDhNData); } //============================================================================ @@ -233,7 +222,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kCsrDhXData); - swap_key_bytes(kCsrDhXData); } @@ -257,7 +245,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kGameDhNData); - swap_key_bytes(kGameDhNData); } //============================================================================ @@ -276,7 +263,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kGameDhXData); - swap_key_bytes(kGameDhXData); } @@ -312,7 +298,6 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kGateKeeperDhNData); - swap_key_bytes(kGateKeeperDhNData); } //============================================================================ @@ -331,5 +316,4 @@ PF_CONSOLE_CMD( Base64Decode(hsStrlen((const char *)params[0]), (const char *)params[0], kNetDiffieHellmanKeyBits / 8, kGateKeeperDhXData); - swap_key_bytes(kGateKeeperDhXData); } diff --git a/Sources/Plasma/FeatureLib/pfGameMgr/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfGameMgr/CMakeLists.txt index c3652c6d..90834319 100644 --- a/Sources/Plasma/FeatureLib/pfGameMgr/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfGameMgr/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -include_directories(${OPENSSL_INCLUDE_DIR}) - set(pfGameMgr_SOURCES pfGameMgr.cpp BlueSpiral/pfGmBlueSpiral.cpp diff --git a/Sources/Plasma/FeatureLib/pfJournalBook/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfJournalBook/CMakeLists.txt index 965e36da..c780ad21 100644 --- a/Sources/Plasma/FeatureLib/pfJournalBook/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfJournalBook/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -include_directories(${OPENSSL_INCLUDE_DIR}) - set(pfJournalBook_SOURCES pfJournalBook.cpp ) diff --git a/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt index 56cee3c8..c005002c 100644 --- a/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt @@ -7,7 +7,6 @@ include_directories(../../) include_directories(${PYTHON_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) -include_directories(${OPENSSL_INCLUDE_DIR}) set(pfPython_SOURCES cyAccountManagement.cpp diff --git a/Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp b/Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp index 847887f0..2b0056d8 100644 --- a/Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp +++ b/Sources/Plasma/NucleusLib/pnNetCli/pnNcCli.cpp @@ -589,20 +589,22 @@ static void ClientConnect (NetCli * cli) { { ZERO(cli->seed); unsigned bytes; - const void * data = clientSeed.GetData(&bytes); + unsigned char * data = clientSeed.GetData_LE(&bytes); MemCopy(cli->seed, data, min(bytes, sizeof(cli->seed))); + delete [] data; } // Send server seed if (cli->sock) { unsigned bytes; NetCli_Cli2Srv_Connect msg; - const void * data = serverSeed.GetData(&bytes); + unsigned char * data = serverSeed.GetData_LE(&bytes); ASSERTMSG(bytes <= sizeof(msg.dh_y_data), "4"); msg.message = kNetCliCli2SrvConnect; msg.length = (byte) (sizeof(msg) - sizeof(msg.dh_y_data) + bytes); MemCopy(msg.dh_y_data, data, bytes); AsyncSocketSend(cli->sock, &msg, msg.length); + delete [] data; } } @@ -643,8 +645,9 @@ static bool ServerRecvConnect ( ZERO(clientSeed); unsigned bytes; - const void * data = clientSeedValue.GetData(&bytes); + unsigned char * data = clientSeedValue.GetData_LE(&bytes); MemCopy(clientSeed, data, min(bytes, sizeof(clientSeed))); + delete [] data; } // Create the symmetric key from a combination diff --git a/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt b/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt index 65263bf4..7caf3e34 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt +++ b/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt @@ -1,8 +1,6 @@ include_directories("../../CoreLib") include_directories("../../NucleusLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(pnUtils_HEADERS Intern.h Pch.h diff --git a/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.cpp b/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.cpp index 46d35263..785e3f19 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.cpp +++ b/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.cpp @@ -32,57 +32,15 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../Pch.h" #pragma hdrstop +#include +#include -/**************************************************************************** -* -* Constants and macros -* -***/ - -const unsigned VAL_BITS = 8 * sizeof(BigNum::Val); -const BigNum::DVal VAL_RANGE = ((BigNum::DVal)1) << VAL_BITS; - -#define LOW(dval) ((Val)(dval)) -#define HIGH(dval) ((Val)((dval) / VAL_RANGE)) -#define PACK(low, high) ((DVal)((high) * VAL_RANGE + (low))) - -#define ALLOC_TEMP(struct, count) \ - (struct).UseTempAlloc((Val *)_alloca((count) * sizeof(Val)), count) - - -/**************************************************************************** -* -* BigNum private methods -* -***/ - -//=========================================================================== -void BigNum::SetVal (unsigned index, Val value) { - ARRAY(Val)::operator[](index) = value; -} - -//=========================================================================== -void BigNum::SetVal (unsigned index, DVal value, Val * carry) { - ARRAY(Val)::operator[](index) = LOW(value); - *carry = HIGH(value); -} - -//=========================================================================== -void BigNum::Trim (unsigned count) { - ASSERT(count <= Count()); - while (count && !ARRAY(Val)::operator[](count - 1)) - --count; - SetCountFewer(count); -} - -//=========================================================================== -BigNum * BigNum::UseTempAlloc (Val * ptr, unsigned count) { - m_isTemp = true; - AttachTemp(ptr, count); - return this; +static inline void byteswap(size_t size, unsigned char * data) +{ + for (size_t i = 0; i < (size / 2); ++i) + std::swap(data[i], data[size - i - 1]); } - /**************************************************************************** * * BigNum public methods @@ -90,1296 +48,98 @@ BigNum * BigNum::UseTempAlloc (Val * ptr, unsigned count) { ***/ //=========================================================================== -BigNum::BigNum () : - m_isTemp(false) +BigNum::BigNum () : m_context(nil) { + BN_init(&m_number); } //=========================================================================== -BigNum::BigNum (const BigNum & a) : - m_isTemp(false) +BigNum::BigNum (const BigNum & a) : m_context(nil) { - Set(a); + BN_init(&m_number); + BN_copy(&m_number, &a.m_number); } //=========================================================================== -BigNum::BigNum (unsigned a) : - m_isTemp(false) +BigNum::BigNum (unsigned a) : m_context(nil) { - Set(a); + BN_init(&m_number); + BN_set_word(&m_number, a); } //=========================================================================== -BigNum::BigNum (unsigned bytes, const void * data) : - m_isTemp(false) +BigNum::BigNum (unsigned bytes, const void * data, bool le) : m_context(nil) { - FromData(bytes, data); + BN_init(&m_number); + if (le) + FromData_LE(bytes, data); + else + FromData_BE(bytes, data); } //=========================================================================== -BigNum::BigNum (const wchar str[], Val radix) : - m_isTemp(false) +BigNum::~BigNum () { - FromStr(str, radix); -} - -//=========================================================================== -BigNum::~BigNum () { - if (m_isTemp) - Detach(); -} - -//=========================================================================== -void BigNum::Add (const BigNum & a, Val b) { - // this = a + b - - const unsigned count = a.Count(); - GrowToCount(count + 1, true); - unsigned index = 0; - Val carry = b; - for (; index < count; ++index) - SetVal(index, (DVal)((DVal)a[index] + (DVal)carry), &carry); - if (carry) - SetVal(index++, carry); - Trim(index); - -} - -//=========================================================================== -void BigNum::Add (const BigNum & a, const BigNum & b) { - // this = a + b - - const unsigned aCount = a.Count(); - const unsigned bCount = b.Count(); - const unsigned count = aCount + bCount; - GrowToCount(count + 1, true); - unsigned index = 0; - Val carry = 0; - for (; index < count; ++index) { - Val aVal = (index < aCount) ? a[index] : (Val)0; - Val bVal = (index < bCount) ? b[index] : (Val)0; - SetVal(index, (DVal)((DVal)aVal + (DVal)bVal + (DVal)carry), &carry); - } - if (carry) - SetVal(index++, carry); - Trim(index); - -} - -//=========================================================================== -int BigNum::Compare (Val a) const { - // -1 if (this < a) - // 0 if (this == a) - // 1 if (this > a) - - // Handle the case where this number has more digits than the comparand - const unsigned count = Count(); - ASSERT(!count || (*this)[count - 1]); - if (count > 1) - return 1; - - // Handle the case where this number has fewer digits than the comparand - if (!count) - return a ? -1 : 0; - - // Handle the case where both numbers share the same number of digits - Val thisVal = (*this)[0]; - return (thisVal > a) ? 1 : (thisVal < a) ? -1 : 0; - + if (m_context) + BN_CTX_free(m_context); + BN_free(&m_number); } //=========================================================================== -int BigNum::Compare (const BigNum & a) const { +int BigNum::Compare (dword a) const { // -1 if (this < a) // 0 if (this == a) // 1 if (this > a) - // Handle the case where this number has more digits than the comparand - const unsigned thisCount = Count(); - const unsigned compCount = a.Count(); - ASSERT(!thisCount || (*this)[thisCount - 1]); - ASSERT(!compCount || a[compCount - 1]); - if (thisCount > compCount) - return 1; + if (BN_is_word(&m_number, a)) + return 0; - // Handle the case where this number has fewer digits than the comparand - if (thisCount < compCount) + // This returns 0xFFFFFFFFL if the number is bigger than one word, so + // it doesn't need any size check + if (BN_get_word(&m_number) < a) return -1; - // Handle the case where both numbers share the same number of digits - for (unsigned index = thisCount; index--; ) { - Val thisVal = (*this)[index]; - Val compVal = a[index]; - if (thisVal == compVal) - continue; - return (thisVal > compVal) ? 1 : -1; - } - return 0; - -} - -//=========================================================================== -void BigNum::Div (const BigNum & a, Val b, Val * remainder) { - // this = a / b, remainder = a % b - - const unsigned count = a.Count(); - SetCount(count); - *remainder = 0; - for (unsigned index = count; index--; ) { - DVal value = PACK(a[index], *remainder); - SetVal(index, (Val)(value / b)); - *remainder = (Val)(value % b); - } - Trim(count); - -} - -//=========================================================================== -void BigNum::Div (const BigNum & a, const BigNum & b, BigNum * remainder) { - // this = a / b, remainder = a % b - // either this or remainder may be nil - - ASSERT(this != remainder); - - // Check for division by zero - ASSERT(b.Count() && b[b.Count() - 1]); - - // Normalize the operands so that the highest bit is set in the most - // significant word of the denominator - const unsigned shift = 8 * sizeof(Val) - MathHighBitPos(b[b.Count() - 1]) - 1; - BigNum aaBuffer; - BigNum bbBuffer; - BigNum * aa = shift ? ALLOC_TEMP(aaBuffer, a.Count() + 1) : (BigNum *)&a; - BigNum * bb = shift ? ALLOC_TEMP(bbBuffer, b.Count() + 1) : (BigNum *)&b; - if (shift) { - aa->Shl(a, shift); - bb->Shl(b, shift); - } - - // Perform the division - DivNormalized(*aa, *bb, remainder); - - // Denormalize the remainder - if (remainder) - remainder->Shr(*remainder, shift); - -} - -//=========================================================================== -void BigNum::DivNormalized (const BigNum & a, const BigNum & b, BigNum * remainder) { - // this = a / b, remainder = a % b - // either this or remainder may be nil - // high bit of b must be set - - ASSERT(this != remainder); - - // Check for division by zero - ASSERT(b.Count() && b[b.Count() - 1]); - - // Verify that the operands are normalized - ASSERT(MathHighBitPos(b[b.Count() - 1]) == 8 * sizeof(Val) - 1); - - // Handle the case where the denominator is greater than the numerator - if ((b.Count() > a.Count()) || (b.Compare(a) > 0)) { - if (remainder && (remainder != &a)) - remainder->Set(a); - if (this) - ZeroCount(); - return; - } - - // Create a distinct buffer for the denominator if necessary - BigNum denomTemp; - BigNum * denom = ((&b != this) && (&b != remainder)) ? (BigNum *)&b : ALLOC_TEMP(denomTemp, b.Count()); - denom->Set(b); - - // Store the numerator into the remainder buffer - BigNum numerTemp; - BigNum * numer = remainder ? remainder : ALLOC_TEMP(numerTemp, a.Count()); - numer->Set(a); - - // Prepare the destination buffer - const unsigned numerCount = numer->Count(); - const unsigned denomCount = denom->Count(); - if (this) - this->SetCount(numerCount + 1 - denomCount); - - // Calculate the quotient one word at a time - DVal t = (DVal)((DVal)(*denom)[denomCount - 1] + (DVal)1); - for (unsigned quotientIndex = numerCount + 1 - denomCount; quotientIndex--; ) { - - // Calculate the approximate value of the next quotient word, - // erring on the side of underestimation - Val low = (*numer)[quotientIndex + denomCount - 1]; - Val high = (quotientIndex + denomCount < numerCount) ? (*numer)[quotientIndex + denomCount] : (Val)0; - ASSERT(high < t); - Val quotient = (Val)(PACK(low, high) / t); - - // Calculate the product of the denominator and this quotient word - // (using zero for all lower quotient words) and subtract the product - // from the current numerator - if (quotient) { - Val borrow = 0; - Val carry = 0; - unsigned denomIndex; - for (denomIndex = 0; denomIndex != denomCount; ++denomIndex) { - DVal product = (DVal)(Mul((*denom)[denomIndex], quotient) + carry); - carry = HIGH(product); - numer->SetVal(quotientIndex + denomIndex, (DVal)((DVal)(*numer)[quotientIndex + denomIndex] - (DVal)LOW(product) - (DVal)borrow), &borrow); - borrow = (Val)((Val)0 - (Val)borrow); - } - if (quotientIndex + denomCount != numerCount) { - numer->SetVal(quotientIndex + denomCount, (DVal)((DVal)(*numer)[quotientIndex + denomIndex] - (DVal)carry - (DVal)borrow), &borrow); - carry = 0; - } - ASSERT(!carry); - ASSERT(!borrow); - } - - // Check whether we underestimated the quotient word, and adjust - // it if necessary - for (;;) { - - // Test whether the current numerator is still greater than or - // equal to the denominator - if ((quotientIndex + denomCount == numerCount) || !(*numer)[quotientIndex + denomCount]) { - bool numerLess = false; - for (unsigned denomIndex = denomCount; !numerLess && denomIndex--; ) { - Val numerVal = (*numer)[quotientIndex + denomIndex]; - Val denomVal = (*denom)[denomIndex]; - numerLess = (numerVal < denomVal); - if (numerVal != denomVal) - break; - } - if (numerLess) - break; - } - - // Increment the quotient by one, and correct the current - // numerator for this adjustment by subtracting the denominator - ++quotient; - Val borrow = 0; - for (unsigned denomIndex = 0; denomIndex != denomCount; ++denomIndex) { - numer->SetVal(quotientIndex + denomIndex, (DVal)((DVal)(*numer)[quotientIndex + denomIndex] - (DVal)(*denom)[denomIndex] - (DVal)borrow), &borrow); - borrow = (Val)((Val)0 - (Val)borrow); - } - if (borrow) - numer->SetVal(quotientIndex + denomCount, (DVal)((DVal)(*numer)[quotientIndex + denomCount] - (DVal)borrow), &borrow); - ASSERT(!borrow); - - } - ASSERT((quotientIndex + denomCount == numerCount) || !(*numer)[quotientIndex + denomCount]); - - // Store the final quotient word - if (this) - this->SetVal(quotientIndex, quotient); - - } - - // The final remainder is the remaining portion of the numerator - if (remainder) { - ASSERT(remainder == numer); - remainder->Trim(denomCount); - } - - // Trim the result - if (this) - this->Trim(numerCount + 1 - denomCount); - + // Not less or equal, must be greater + return 1; } //=========================================================================== -void BigNum::FromData (unsigned bytes, const void * data) { - ASSERT(data || !bytes); - - // Calculate the number of words required to hold the data - unsigned count = (bytes + sizeof(Val) - 1) / sizeof(Val); - SetCount(count); - - // Fill in whole words - unsigned index = 0; - unsigned offset = 0; - for (; offset + sizeof(Val) <= bytes; ++index, offset += sizeof(Val)) - SetVal(index, *(const Val *)((const byte *)data + offset)); - - // Fill in the final partial word - if (offset < bytes) { - Val value = 0; - MemCopy(&value, (const byte *)data + offset, bytes - offset); - SetVal(index, value); - } - -} - -//=========================================================================== -void BigNum::FromStr (const wchar str[], Val radix) { - ASSERT(str); - - // Decode the prefix - if (str[0] == L'0') { - if ((str[1] == L'x') || (str[1] == L'X')) { - str += 2; - if (!radix) - radix = 16; - } - else if ((str[1] >= L'0') && (str[1] <= L'9')) { - str += 1; - if (!radix) - radix = 8; - } - else if (!radix) { - ZeroCount(); - return; - } - } - else if (!radix) - radix = 10; - - // Decode the number - ZeroCount(); - for (; *str; ++str) { - - // Decode the next character - Val value; - if ((*str >= L'0') && (*str <= '9')) - value = (Val)(*str - L'0'); - else if ((*str >= L'a') && (*str <= L'z')) - value = (Val)(*str + 10 - L'a'); - else if ((*str >= L'A') && (*str <= L'Z')) - value = (Val)(*str + 10 - L'A'); - else - break; - if (value >= radix) - break; - - // Apply it to the result - Mul(*this, radix); - Add(*this, value); - - } - -} - -//=========================================================================== -void BigNum::Gcd (const BigNum & a, const BigNum & b) { - - // Allocate working copies of a and b - BigNum aa; - BigNum bb; - unsigned maxCount = max(a.Count(), b.Count()); - ALLOC_TEMP(aa, maxCount + 1); - ALLOC_TEMP(bb, maxCount + 1); - aa.Set(a); - bb.Set(b); - - // Find the greatest common denominator using Euclid's algorithm - Set(bb); - while (aa.Count()) { - Set(aa); - aa.Mod(bb, aa); - bb.Set(*this); - } - -} - -//=========================================================================== -const void * BigNum::GetData (unsigned * bytes) const { - if (bytes) - *bytes = Bytes(); - return Ptr(); -} - -//=========================================================================== -unsigned BigNum::HighBitPos () const { - // returns the position of the highest set bit, or -1 if no bits are set - - for (unsigned index = Count(); index--; ) { - Val val = (*this)[index]; - if (!val) - continue; - return index * 8 * sizeof(Val) + MathHighBitPos(val); - } - - return (unsigned)-1; -} - -//=========================================================================== -bool BigNum::InverseMod (const BigNum & a, const BigNum & b) { - // finds value for this such that (a ^ -1) == (this mod b) - // returns false if a has no inverse modulo b - - // Verify that a and b are nonzero - ASSERT(a.Count()); - ASSERT(b.Count()); - - // Verify that a is less than b - ASSERT(a.Compare(b) < 0); - - // Verify that either a or b is odd. If both are even then they cannot - // possibly be relatively prime, so there cannot be a solution. - if (!(a.IsOdd() || b.IsOdd())) - return false; - - // Allocate buffers for intermediate values - BigNum uArray[3]; - BigNum tArray[3]; - BigNum * u = uArray; - BigNum * t = tArray; - - // Find the inverse using the extended Euclidean algorithm - u[0].SetOne(); - u[1].SetZero(); - u[2].Set(b); - t[0].Set(a); - t[1].Sub(b, 1); - t[2].Set(a); - do { - do { - if (!u[2].IsOdd()) { - if (u[0].IsOdd() || u[1].IsOdd()) { - u[0].Add(u[0], a); - u[1].Add(u[1], b); - } - u[0].Shr(u[0], 1); - u[1].Shr(u[1], 1); - u[2].Shr(u[2], 1); - } - if (!t[2].IsOdd() || (u[2].Compare(t[2]) < 0)) - SWAP(u, t); - } while (!u[2].IsOdd()); - - while ((u[0].Compare(t[0]) < 0) || (u[1].Compare(t[1]) < 0)) { - u[0].Add(u[0], a); - u[1].Add(u[1], b); - } - - u[0].Sub(u[0], t[0]); - u[1].Sub(u[1], t[1]); - u[2].Sub(u[2], t[2]); - } while (t[2].Count()); - - while ((u[0].Compare(a) >= 0) && (u[1].Compare(b) >= 0)) { - u[0].Sub(u[0], a); - u[1].Sub(u[1], b); - } - - // If the greatest common denominator is not one then there is no - // solution - if (u[2].Compare(1)) - return false; - - // Return the solution - Sub(b, u[1]); - return true; - -} - -//=========================================================================== -bool BigNum::IsMultiple (Val a) const { - // returns true if (this % a) == 0 - - DVal remainder = 0; - for (unsigned index = Count(); index--; ) - remainder = (DVal)(PACK((*this)[index], remainder) % a); - - return !remainder; -} - -//=========================================================================== -bool BigNum::IsOdd () const { - // returns true if this is an odd number - - return Count() ? (*this)[0] & 1 : false; -} - -//=========================================================================== -bool BigNum::IsPrime () const { - // returns true if there is a strong likelihood that this is prime - - // Verify that the number is odd, or is exactly equal to two - if (!Count() || (!((*this)[0] & 1) && ((Count() > 1) || ((*this)[0] > 2)))) - return false; - - // Verify that the number is not evenly divisible by a small prime - static const Val smallPrimes[] = {3, 5, 7, 11}; - unsigned loop; - for (loop = 0; loop != arrsize(smallPrimes); ++loop) - if (IsMultiple(smallPrimes[loop])) - return false; - if (Compare(smallPrimes[arrsize(smallPrimes)-1]) <= 0) - return true; - - // Rabin-Miller Test - - // Calculate b, where b is the number of times 2 divides (this - 1) - BigNum this_1; - ALLOC_TEMP(this_1, Count()); - this_1.Sub(*this, 1); - const unsigned b = this_1.LowBitPos(); - - // Calculate m, such that this == 1 + 2 ^ b * m - BigNum m; - ALLOC_TEMP(m, Count()); - m.Shr(this_1, b); - - // For a number of witnesses, test whether the witness demonstrates this - // number to be composite via Fermat's Little Theorem, or has a - // nontrivial square root mod n - static const Val witnesses[] = {3, 5, 7}; - BigNum z; - ALLOC_TEMP(z, 2 * (Count() + 1)); - for (loop = 0; loop != arrsize(witnesses); ++loop) { - - // Initialize z to (witness ^ m % this) - z.PowMod(witnesses[loop], m, *this); - - // This passes the test if (z == 1) - if (!z.Compare(1)) - continue; - - for (unsigned j = 0; z.Compare(this_1); ) { - - // This fails the test if we reach b iterations. - ++j; - if (j == b) - return false; - - // Square z. This fails the test if z mod this equals 1. - z.MulMod(z, z, *this); - if (!z.Compare(1)) - return false; - - } - - } - - return true; -} - -//=========================================================================== -unsigned BigNum::LowBitPos () const { - // returns the position of the lowest set bit, or -1 if no bits are set - - for (unsigned index = 0, count = Count(); index < count; ++index) { - Val val = (*this)[index]; - if (!val) - continue; - for (unsigned bit = 0; ; ++bit) - if (val & (1 << bit)) - return index * 8 * sizeof(Val) + bit; - } - - return (unsigned)-1; -} - -//=========================================================================== -void BigNum::Mod (const BigNum & a, const BigNum & b) { - // this = a % b - - ((BigNum *)nil)->Div(a, b, this); -} - -//=========================================================================== -void BigNum::ModNormalized (const BigNum & a, const BigNum & b) { - // this = a % b - // high bit of b must be set - - ((BigNum *)nil)->DivNormalized(a, b, this); -} - -//=========================================================================== -BigNum::DVal BigNum::Mul (BigNum::Val a, BigNum::Val b) { - // returns a * b - - return (DVal)a * (DVal)b; -} - -//=========================================================================== -void BigNum::Mul (const BigNum & a, Val b) { - // this = a * b - - const unsigned count = a.Count(); - GrowToCount(count + 1, true); - unsigned index = 0; - Val carry = 0; - for (; index < count; ++index) - SetVal(index, (DVal)(Mul(a[index], b) + carry), &carry); - if (carry) - SetVal(index++, carry); - Trim(index); - -} - -//=========================================================================== -void BigNum::Mul (const BigNum & a, const BigNum & b) { - // this = a * b - - const unsigned aCount = a.Count(); - const unsigned bCount = b.Count(); - const unsigned count = aCount + bCount; - SetCount(count); - if (!count) - return; - - // We perform the multiplication from left to right, so that we don't - // overwrite any operand words before they're used in the case that - // the destination is not distinct from either of the operands - SetVal(count - 1, 0); - for (unsigned index = count - 1; index--; ) { - - // Iterate every combination of aIndex + bIndex that adds up to - // index, and sum the products of those words - DVal value = 0; - const unsigned aStart = (index < bCount) ? 0 : (index + 1 - bCount); - const unsigned aTerm = min(index + 1, aCount); - for (unsigned aIndex = aStart; aIndex != aTerm; ++aIndex) { - - // Accumulate the product of this pair of words - value = (DVal)(Mul(a[aIndex], b[index - aIndex]) + value); - - // If the product exceeds the word size, apply carry - Val carry = HIGH(value); - for (unsigned carryIndex = index + 1; carry; ++carryIndex) - SetVal(carryIndex, (DVal)((DVal)(*this)[carryIndex] + (DVal)carry), &carry); - value = LOW(value); - - } - - // Store the sum of products as the final value for index - SetVal(index, LOW(value)); - - } - - Trim(count); - -} - -//=========================================================================== -void BigNum::MulMod (const BigNum & a, const BigNum & b, const BigNum & c) { - // this = a * b % c - - if (this != &c) { - Mul(a, b); - Mod(*this, c); - } - else { - BigNum temp; - ALLOC_TEMP(temp, a.Count() + b.Count()); - temp.Mul(a, b); - Mod(temp, c); - } - -} - -//=========================================================================== -void BigNum::PowMod (Val a, const BigNum & b, const BigNum & c) { - // this = a ^ b % c - - // Verify that b is distinct from this - BigNum bbBuffer; - const BigNum & bb = (&b != this) ? b : bbBuffer; - if (&bb != &b) { - ALLOC_TEMP(bbBuffer, b.Count()); - bbBuffer.Set(b); - } - - // Generate a table which may allow us to process two bits at once - Val aMult[4] = { - 1, - a, - (Val)(a * a), - (Val)(a * a * a) - }; - bool overflow = (aMult[2] < a) || (aMult[3] < a) || (c.Compare(aMult[3]) <= 0); - - // Normalize the denominator so that the high bit is set. The result - // will be built shifted an equivalent amount. - const unsigned shift = 8 * sizeof(Val) - MathHighBitPos(c[c.Count() - 1]) - 1; - BigNum cc; - ALLOC_TEMP(cc, c.Count() + 1); - cc.Shl(c, shift); - - // Perform the exponentiation from left to right two bits at a time - if (!overflow) { - SetBits(shift, 1); - bool anySet = false; - for (unsigned index = bb.Count(); index--; ) - for (unsigned bit = 8 * sizeof(Val); bit; ) { - bit -= 2; - - if (anySet) { - Square(*this); - Shr(*this, shift); - ModNormalized(*this, cc); - Square(*this); - Shr(*this, shift); - ModNormalized(*this, cc); - } - - unsigned entry = (bb[index] >> bit) & 3; - if (entry) { - Mul(*this, aMult[entry]); - ModNormalized(*this, cc); - anySet = true; - } - - } - } - - // Perform the exponentiation from left to right a single bit at a time - else { - SetBits(shift, 1); - bool anySet = false; - for (unsigned index = bb.Count(); index--; ) - for (unsigned bit = 8 * sizeof(Val); bit--; ) { - - if (anySet) { - Square(*this); - ModNormalized(*this, cc); - } - - if (bb[index] & (1 << bit)) { - Mul(*this, a); - ModNormalized(*this, cc); - anySet = true; - } - - } - } - - // Denormalize the result - Shr(*this, shift); - +void BigNum::FromData_LE (unsigned bytes, const void * data) +{ + unsigned char * buffer = TRACKED_NEW unsigned char[bytes]; + memcpy(buffer, data, bytes); + byteswap(bytes, buffer); + BN_bin2bn(buffer, bytes, &m_number); + delete [] buffer; } //=========================================================================== -void BigNum::PowMod (const BigNum & a, const BigNum & b, const BigNum & c) { - // this = a ^ b % c - - // Verify that a and b are distinct from this - BigNum distinctTemp; - const BigNum & aa = (&a != this) ? a : distinctTemp; - const BigNum & bb = (&b != this) ? b : distinctTemp; - if ((&aa != &a) || (&bb != &b)) { - ALLOC_TEMP(distinctTemp, Count()); - distinctTemp.Set(*this); - } - - // Generate a table which will allow us to process two bits at once - BigNum a2; - BigNum a3; - ALLOC_TEMP(a2, 2 * aa.Count() + 1); - ALLOC_TEMP(a3, 3 * aa.Count() + 1); - a2.Mul(aa, aa); - a2.Mod(a2, c); - a3.Mul(aa, a2); - a3.Mod(a3, c); - const BigNum * aMult[] = { - nil, - &aa, - &a2, - &a3 - }; - - // Normalize the denominator so that the high bit is set. The result - // will be built shifted an equivalent amount. - const unsigned shift = 8 * sizeof(Val) - MathHighBitPos(c[c.Count() - 1]) - 1; - BigNum cc; - ALLOC_TEMP(cc, c.Count() + 1); - cc.Shl(c, shift); - - // Perform the exponentiation from left to right two bits at a time - SetBits(shift, 1); - bool anySet = false; - for (unsigned index = bb.Count(); index--; ) - for (unsigned bit = 8 * sizeof(Val); bit; ) { - bit -= 2; - - if (anySet) { - Square(*this); - Shr(*this, shift); - ModNormalized(*this, cc); - Square(*this); - Shr(*this, shift); - ModNormalized(*this, cc); - } - - unsigned entry = (bb[index] >> bit) & 3; - if (entry) { - Mul(*this, *aMult[entry]); - ModNormalized(*this, cc); - anySet = true; - } - - } - - // Denormalize the result - Shr(*this, shift); - +unsigned char * BigNum::GetData_BE (unsigned * bytes) const +{ + *bytes = BN_num_bytes(&m_number); + unsigned char * data = TRACKED_NEW unsigned char[*bytes]; + BN_bn2bin(&m_number, data); + return data; } //=========================================================================== -void BigNum::Rand (const BigNum & a, BigNum * seed) { - // this = random number less than a - - ASSERT(seed != &a); - ASSERT(seed != this); - - // Verify that a is distinct from this - BigNum distinctTemp; - const BigNum & aa = (&a != this) ? a : distinctTemp; - if (&aa != &a) { - ALLOC_TEMP(distinctTemp, a.Count()); - distinctTemp.Set(a); - } - - // Count the number of bits in a - unsigned bits = aa.HighBitPos() + 1; - - for (;;) { - - // Generate a random number with the same number of bits as a - Rand(bits, seed); - - // Check whether the number is less than a - if (Compare(aa) < 0) - break; - - } - +unsigned char * BigNum::GetData_LE (unsigned * bytes) const +{ + *bytes = BN_num_bytes(&m_number); + unsigned char * data = TRACKED_NEW unsigned char[*bytes]; + BN_bn2bin(&m_number, data); + byteswap(*bytes, data); + return data; } //=========================================================================== -void BigNum::Rand (unsigned bits, BigNum * seed) { +void BigNum::Rand (unsigned bits, BigNum * seed) +{ // this = random number with bits or fewer bits - ASSERT(seed != this); - - // Prepare the output buffer - const unsigned count = (bits + 8 * sizeof(Val) - 1) / (8 * sizeof(Val)); - SetCount(count); - if (!count) - return; - - // Prepare the seed - unsigned seedCount = seed->Count(); - if (!seedCount) - seed->SetCount(++seedCount); - unsigned seedIndex = 0; - - // Produce a random number with the correct number of words - for (unsigned index = 0; index < count; ++index) { - - // Read the next word of the seed - dword randValue = (*seed)[seedIndex] ^ ((index == seedIndex) ? 0x075bd924 : 0); - - // Produce one word of randomness, 16 bits at a time - Val value = 0; - for (unsigned bit = 0; bit < 8 * sizeof(Val); bit += 16) { - const dword A = 0xbc8f; - const dword Q = 0xadc8; - const dword R = 0x0d47; - - dword div = randValue / Q; - randValue = A * (randValue - Q * div) - R * div; - randValue &= 0x7fffffff; - - value |= (randValue & 0xffff) << bit; - } - - // Store the random word - SetVal(index, value); - - // Update the seed and move to the seed next word - seed->SetVal(seedIndex, (Val)randValue); - if (++seedIndex >= seedCount) - seedIndex = 0; - - } - - // Mask the final word to contain the correct number of bits - Val mask = (Val)((Val)-1 >> (count * 8 * sizeof(Val) - bits)); - SetVal(count - 1, (Val)((*this)[count - 1] & mask)); - - // Trim the result - Trim(count); - - // Rotate the seed so the next unused seed word will be the first seed - // word used in the next random operation - if (seedIndex) { - BigNum saved; - ALLOC_TEMP(saved, seedCount); - saved.Set(*seed); - - for (unsigned index = 0; index < seedCount; ++index) - (*seed)[index] = saved[(index + seedIndex) % seedCount]; - } - -} - -//=========================================================================== -void BigNum::RandPrime (unsigned bits, BigNum * seed) { - - // Calculate the required number of words to hold the generated number - unsigned count = (bits + 8 * sizeof(Val) - 1) / (8 * sizeof(Val)); - - // For large bit counts, calculate the prime number as 2 * q * n + 1, - // where q is a random prime with fewer bits, and n is a random number - // chosen as follows: - // n >= (2 ^ (bits - 1) - 1) / (2 * q) - // n < (2 ^ bits - 1) / (2 * q) - if (bits > 128) { - - // Choose a prime number q, and multiply it by 2 - BigNum q_2; - ALLOC_TEMP(q_2, count / 2 + 2); - q_2.RandPrime(bits / 2, seed); - q_2.Mul(q_2, 2); - - // Calculate the lower bound - BigNum lowerBound; - ALLOC_TEMP(lowerBound, count + 1); - lowerBound.SetBits(0, bits - 1); - lowerBound.Div(lowerBound, q_2, nil); - - // Calculate the upper bound - BigNum upperBound; - ALLOC_TEMP(upperBound, count + 1); - upperBound.SetBits(0, bits); - upperBound.Div(upperBound, q_2, nil); - - // Calculate the number of bits in the upper bound - unsigned upperBoundBits = upperBound.HighBitPos() + 1; - - for (;;) { - - // Choose a random number between the lower and upper bounds - Rand(upperBoundBits, seed); - if (Compare(upperBound) >= 0) - continue; - if (Compare(lowerBound) < 0) - continue; - - // Calculate 2 * q * n + 1 - Mul(*this, q_2); - Add(*this, 1); - - // Test whether the result is prime - if (IsPrime()) - break; - - } - - } - - // For small bit counts, choose a random number with the requested - // number of bits, then keep incrementing it until we find a prime - else { - - // Define the upper bound for a number with the requested number - // of bits - BigNum bound; - ALLOC_TEMP(bound, count + 1); - bound.SetBits(bits, 1); - - for (;;) { - - // Choose a random number with (bits - 1) bits - Rand(bits - 1, seed); - - // Subtract it from the upper bound to generate a number with - // the high bit set - Sub(bound, *this); - - // Keep incrementing the number until we find a prime - if (!IsOdd()) - Add(*this, 1); - while (!IsPrime()) - Add(*this, 2); - - // If the number reached or exceeded the upper bound, try again - if (Compare(bound) < 0) - break; - - } - - } - -} - -//=========================================================================== -void BigNum::Set (const BigNum & a) { - // this = a - - if (&a == this) - return; - - const unsigned count = a.Count(); - SetCount(count); - for (unsigned index = count; index--; ) - SetVal(index, a[index]); - -} - -//=========================================================================== -void BigNum::Set (unsigned a) { - // this = a - - ZeroCount(); - if (a) - for (unsigned index = 0; ; ++index) { - SetCount(index + 1); - SetVal(index, LOW(a)); - if (a < VAL_RANGE) - break; - a = (unsigned)(a / VAL_RANGE); - } - -} - -//=========================================================================== -void BigNum::SetBits (unsigned setBitsOffset, unsigned setBitsCount) { - // this = binary [1...][0...], where 'setBitsOffset' is the number of - // zero bits and 'setBitsCount' is the number of one bits - - if (!setBitsCount) { - ZeroCount(); - return; - } - - const unsigned setBitsTerm = setBitsOffset + setBitsCount - 1; - const unsigned bitsPerWord = 8 * sizeof(Val); - const unsigned firstSetWord = setBitsOffset / bitsPerWord; - const unsigned lastSetWord = (setBitsOffset + setBitsCount - 1) / bitsPerWord; - Val firstSetMask = (Val)((Val)-1 << (setBitsOffset % bitsPerWord)); - Val lastSetMask = (Val)((Val)-1 >> (bitsPerWord - setBitsTerm % bitsPerWord - 1)); - if (firstSetWord == lastSetWord) - firstSetMask = lastSetMask = (Val)(firstSetMask & lastSetMask); - - SetCount(lastSetWord + 1); - unsigned index = 0; - for (; index < firstSetWord; ++index) - SetVal(index, 0); - SetVal(index++, firstSetMask); - if (firstSetWord == lastSetWord) - return; - for (; index < lastSetWord; ++index) - SetVal(index, (Val)-1); - SetVal(index, lastSetMask); - -} - -//=========================================================================== -void BigNum::SetOne () { - // this = 1 - - SetCount(1); - SetVal(0, 1); -} - -//=========================================================================== -void BigNum::SetZero () { - // this = 0 - - ZeroCount(); -} - -//=========================================================================== -void BigNum::Shl (const BigNum & a, unsigned b) { - // this = a << b - - ASSERT(b < 8 * sizeof(Val)); - if (!b) { - Set(a); - return; - } - const unsigned bInv = 8 * sizeof(Val) - b; - - const unsigned count = a.Count(); - SetCount(count + 1); - Val curr = 0; - for (unsigned index = count; index >= 1; --index) { - Val next = a[index - 1]; - SetVal(index, (Val)((next >> bInv) | (curr << b))); - curr = next; - } - SetVal(0, (Val)(curr << b)); - Trim(count + 1); - -} - -//=========================================================================== -void BigNum::Shr (const BigNum & a, unsigned b) { - // this = a >> b - - ASSERT(b < 8 * sizeof(Val)); - if (!b) { - Set(a); - return; - } - const unsigned bInv = 8 * sizeof(Val) - b; - - const unsigned count = a.Count(); - SetCount(count); - if (!count) - return; - - Val curr = a[0]; - for (unsigned index = 0; index + 1 < count; ++index) { - Val next = a[index + 1]; - SetVal(index, (Val)((next << bInv) | (curr >> b))); - curr = next; - } - SetVal(count - 1, (Val)(curr >> b)); - Trim(count); - -} - -//=========================================================================== -void BigNum::Square (const BigNum & a) { - // this = a * a - - const unsigned aCount = a.Count(); - const unsigned count = 2 * aCount; - SetCount(count); - if (!count) - return; - - // We perform the multiplication from left to right, so that we don't - // overwrite any operand words before they're used in the case that - // the destination is not distinct from the operand - SetVal(count - 1, 0); - for (unsigned index = count - 1; index--; ) { - - // Iterate every combination of source indices that adds up to - // index, and sum the products of those words - DVal value = 0; - unsigned aIndex = (index < aCount) ? 0 : (index + 1 - aCount); - unsigned bIndex; - for (; (int)((bIndex = index - aIndex) - aIndex) >= 0; ++aIndex) { - - // Calculate the product of this pair of words - DVal product = Mul(a[aIndex], a[bIndex]); - - // Add the product to the sum. If it exceeds the word size, - // apply carry. - value = (DVal)(value + product); - Val carry = HIGH(value); - unsigned carryIndex; - for (carryIndex = index + 1; carry; ++carryIndex) - SetVal(carryIndex, (DVal)((DVal)(*this)[carryIndex] + (DVal)carry), &carry); - value = LOW(value); - - // If this pair of words should be multiplied twice, add the - // product again. - if (aIndex == bIndex) - continue; - value = (DVal)(value + product); - carry = HIGH(value); - for (carryIndex = index + 1; carry; ++carryIndex) - SetVal(carryIndex, (DVal)((DVal)(*this)[carryIndex] + (DVal)carry), &carry); - value = LOW(value); - - } - - // Store the sum of products as the final value for index - SetVal(index, LOW(value)); - - } - - Trim(count); - -} - -//=========================================================================== -void BigNum::Sub (const BigNum & a, Val b) { - // this = a - b - - const unsigned count = a.Count(); - SetCount(count); - Val borrow = b; - unsigned index; - for (index = 0; index < count; ++index) { - SetVal(index, (DVal)((DVal)a[index] - (DVal)borrow), &borrow); - borrow = (Val)((Val)0 - (Val)borrow); - } - ASSERT(!borrow); - Trim(index); - -} - -//=========================================================================== -void BigNum::Sub (const BigNum & a, const BigNum & b) { - // this = a - b - - const unsigned count = a.Count(); - const unsigned bCount = b.Count(); - GrowToCount(count, true); - Val borrow = 0; - unsigned index; - for (index = 0; index < count; ++index) { - Val bVal = (index < bCount) ? b[index] : (Val)0; - SetVal(index, (DVal)((DVal)a[index] - (DVal)bVal - (DVal)borrow), &borrow); - borrow = (Val)((Val)0 - (Val)borrow); - } - ASSERT(!borrow); - Trim(index); - -} - -//=========================================================================== -void BigNum::ToStr (BigNum * buffer, Val radix) const { - ASSERT(this != buffer); - - // Calculate the number of characters in the prefix - unsigned prefixChars; - if (radix == 16) - prefixChars = 2; - else if (radix == 8) - prefixChars = 1; - else - prefixChars = 0; - - // Preallocate space for the output string - unsigned charsPerVal = 0; - for (Val testVal = (Val)-1; testVal; testVal = (Val)(testVal / radix)) - ++charsPerVal; - const unsigned charsTotal = max(1, Count()) * charsPerVal + prefixChars + 1; - buffer->SetCount((charsTotal * sizeof(wchar) + sizeof(Val) - 1) / sizeof(Val)); - - // Build the prefix - wchar * prefix = (wchar *)buffer->Ptr(); - if (prefixChars) { - prefix[0] = L'0'; - if (radix == 16) - prefix[1] = L'x'; - else - ASSERT(prefixChars == 1); - } - - // Build the number starting with the least significant digit - wchar * start = prefix + prefixChars; - wchar * curr = start; - BigNum work; - ALLOC_TEMP(work, Count()); - work.Set(*this); - do { - - // Extract the next value - Val remainder; - work.Div(work, radix, &remainder); - - // Encode it as a character in the output string - if (remainder >= 10) - *curr++ = (wchar)(L'a' + (unsigned)remainder - 10); - else - *curr++ = (wchar)(L'0' + (unsigned)remainder); - - } while (work.Count()); - *curr = 0; - - // Reverse the order of the output string - for (wchar * left = start, * right = curr - 1; left < right; ++left, --right) - SWAP(*left, *right); - + unsigned seedBytes; + unsigned char * seedData = seed->GetData_BE(&seedBytes); + RAND_seed(seedData, seedBytes); + BN_rand(&m_number, bits, 0, 0); + delete [] seedData; } diff --git a/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h b/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h index 06d231de..b56d7df2 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h +++ b/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.h @@ -41,70 +41,169 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com * ***/ -class BigNum : private ARRAY(dword) { -public: - typedef dword Val; // must match base array - typedef qword DVal; // must be twice as large as Val +#include +class BigNum { private: - bool m_isTemp; - - void DivNormalized (const BigNum & a, const BigNum & b, BigNum * remainder); - void ModNormalized (const BigNum & a, const BigNum & b); - - inline static DVal Mul (Val a, Val b); + BIGNUM m_number; + mutable BN_CTX * m_context; - inline void SetVal (unsigned index, Val value); - inline void SetVal (unsigned index, DVal value, Val * carry); - inline void Trim (unsigned count); - inline BigNum * UseTempAlloc (Val * ptr, unsigned count); + BN_CTX * GetContext () const + { + if (!m_context) + m_context = BN_CTX_new(); + return m_context; + } public: BigNum (); BigNum (const BigNum & a); BigNum (unsigned a); - BigNum (unsigned bytes, const void * data); - BigNum (const wchar str[], Val radix); + BigNum (unsigned bytes, const void * data, bool le=false); ~BigNum (); + BigNum & operator= (const BigNum & a) + { + BN_copy(&m_number, &a.m_number); + return *this; + } + // Constant parameters need not be distinct from the destination or from // each other - void Add (const BigNum & a, Val b); - void Add (const BigNum & a, const BigNum & b); - int Compare (Val a) const; - int Compare (const BigNum & a) const; - void Div (const BigNum & a, Val b, Val * remainder); - void Div (const BigNum & a, const BigNum & b, BigNum * remainder); - void FromData (unsigned bytes, const void * data); - void FromStr (const wchar str[], Val radix); - void Gcd (const BigNum & a, const BigNum & b); - const void * GetData (unsigned * bytes) const; - unsigned HighBitPos () const; - bool InverseMod (const BigNum & a, const BigNum & b); - bool IsMultiple (Val a) const; - bool IsOdd () const; - bool IsPrime () const; - unsigned LowBitPos () const; - void Mod (const BigNum & a, const BigNum & b); - void Mul (const BigNum & a, Val b); - void Mul (const BigNum & a, const BigNum & b); - void MulMod (const BigNum & a, const BigNum & b, const BigNum & c); - void PowMod (Val a, const BigNum & b, const BigNum & c); - void PowMod (const BigNum & a, const BigNum & b, const BigNum & c); - void Rand (const BigNum & a, BigNum * seed); + void Add (const BigNum & a, dword b) + { + // this = a + b + BN_copy(&m_number, &a.m_number); + BN_add_word(&m_number, b); + } + + void Add (const BigNum & a, const BigNum & b) + { + // this = a + b + BN_add(&m_number, &a.m_number, &b.m_number); + } + + int Compare (dword a) const; + int Compare (const BigNum & a) const + { + return BN_cmp(&m_number, &a.m_number); + } + + void Div (const BigNum & a, dword b, dword * remainder) + { + // this = a / b, remainder = a % b + BN_copy(&m_number, &a.m_number); + *remainder = (dword)BN_div_word(&m_number, b); + } + + void Div (const BigNum & a, const BigNum & b, BigNum * remainder) + { + // this = a / b, remainder = a % b + // either this or remainder may be nil + BN_div(this ? &m_number : nil, remainder ? &remainder->m_number : nil, + &a.m_number, &b.m_number, GetContext()); + } + + void FromData_BE (unsigned bytes, const void * data) + { + BN_bin2bn((const unsigned char *)data, bytes, &m_number); + } + + void FromData_LE (unsigned bytes, const void * data); + + unsigned char * GetData_BE (unsigned * bytes) const; + unsigned char * GetData_LE (unsigned * bytes) const; + + bool IsPrime () const + { + // Cyan's code uses 3 checks, so we'll follow suit. + // This provides an accurate answer to p < 0.015625 + return BN_is_prime_fasttest(&m_number, 3, nil, GetContext(), nil, 1) > 0; + } + + void Mod (const BigNum & a, const BigNum & b) + { + // this = a % b + BN_div(nil, &m_number, &a.m_number, &b.m_number, GetContext()); + } + + void Mul (const BigNum & a, dword b) + { + // this = a * b + BN_copy(&m_number, &a.m_number); + BN_mul_word(&m_number, b); + } + + void Mul (const BigNum & a, const BigNum & b) + { + // this = a * b + BN_mul(&m_number, &a.m_number, &b.m_number, GetContext()); + } + + void PowMod (dword a, const BigNum & b, const BigNum & c) + { + // this = a ^ b % c + PowMod(BigNum(a), b, c); + } + + void PowMod (const BigNum & a, const BigNum & b, const BigNum & c) + { + // this = a ^ b % c + BN_mod_exp(&m_number, &a.m_number, &b.m_number, &c.m_number, GetContext()); + } + + void Rand (const BigNum & a, BigNum * seed) + { + // this = random number less than a + unsigned bits = BN_num_bits(&a.m_number); + do + Rand(bits, seed); + while (Compare(a) >= 0); + } + void Rand (unsigned bits, BigNum * seed); - void RandPrime (unsigned bits, BigNum * seed); - void Set (const BigNum & a); - void Set (unsigned a); - void SetBits (unsigned setBitsOffset, unsigned setBitsCount); - void SetOne (); - void SetZero (); - void Shl (const BigNum & a, unsigned b); - void Shr (const BigNum & a, unsigned b); - void Square (const BigNum & a); - void Sub (const BigNum & a, Val b); - void Sub (const BigNum & a, const BigNum & b); - void ToStr (BigNum * buffer, Val radix) const; + void RandPrime (unsigned bits, BigNum * seed) + { + BN_generate_prime(&m_number, bits, 1, nil, nil, nil, nil); + } + + void Set (const BigNum & a) + { + BN_copy(&m_number, &a.m_number); + } + + void Set (unsigned a) + { + BN_set_word(&m_number, a); + } + + void SetOne () { Set(1); } + void SetZero () { Set(0); } + + void Shl (const BigNum & a, unsigned b) + { + // this = a << b + BN_lshift(&m_number, &a.m_number, b); + } + + void Shr (const BigNum & a, unsigned b) + { + // this = a >> b + BN_rshift(&m_number, &a.m_number, b); + } + + void Sub (const BigNum & a, dword b) + { + // this = a - b + BN_copy(&m_number, &a.m_number); + BN_sub_word(&m_number, b); + } + + void Sub (const BigNum & a, const BigNum & b) + { + // this = a - b + BN_sub(&m_number, &a.m_number, &b.m_number); + } }; diff --git a/Sources/Plasma/PubUtilLib/plAgeDescription/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plAgeDescription/CMakeLists.txt index 956d2f05..1666bfad 100644 --- a/Sources/Plasma/PubUtilLib/plAgeDescription/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plAgeDescription/CMakeLists.txt @@ -3,8 +3,6 @@ include_directories("../../FeatureLib") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plAgeDescription_SOURCES plAgeDescription.cpp plAgeManifest.cpp diff --git a/Sources/Plasma/PubUtilLib/plAgeLoader/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plAgeLoader/CMakeLists.txt index 39a7f095..bab47702 100644 --- a/Sources/Plasma/PubUtilLib/plAgeLoader/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plAgeLoader/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plAgeLoader_SOURCES plAgeLoader.cpp plAgeLoaderPaging.cpp diff --git a/Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt index bc9fe9cf..c8b82c78 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plAvatar/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) set(plAvatar_SOURCES diff --git a/Sources/Plasma/PubUtilLib/plEncryption/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plEncryption/CMakeLists.txt index 605f698e..7acf42ef 100644 --- a/Sources/Plasma/PubUtilLib/plEncryption/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plEncryption/CMakeLists.txt @@ -2,8 +2,6 @@ include_directories("../../CoreLib") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plEncryption_SOURCES plChecksum.cpp ) diff --git a/Sources/Plasma/PubUtilLib/plGLight/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plGLight/CMakeLists.txt index 0fa8d498..91cffd48 100644 --- a/Sources/Plasma/PubUtilLib/plGLight/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plGLight/CMakeLists.txt @@ -3,8 +3,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plGLight_SOURCES plDirectShadowMaster.cpp plLightInfo.cpp diff --git a/Sources/Plasma/PubUtilLib/plInputCore/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plInputCore/CMakeLists.txt index 89692688..27f7f818 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plInputCore/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories("../../NucleusLib") include_directories("../../PubUtilLib") include_directories(${DirectX_INCLUDE_DIR}) -include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) set(plInputCore_SOURCES diff --git a/Sources/Plasma/PubUtilLib/plModifier/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plModifier/CMakeLists.txt index 2bf814e7..988029bd 100644 --- a/Sources/Plasma/PubUtilLib/plModifier/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plModifier/CMakeLists.txt @@ -6,7 +6,6 @@ include_directories("../../PubUtilLib") include_directories(${PHYSX_INCLUDE_DIRS}) include_directories(${OPENAL_INCLUDE_DIR}) -include_directories(${OPENSSL_INCLUDE_DIR}) set(plModifier_SOURCES plAnimEventModifier.cpp diff --git a/Sources/Plasma/PubUtilLib/plNetClient/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plNetClient/CMakeLists.txt index 32a13e09..3b4947ab 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plNetClient/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plNetClient_SOURCES plLinkEffectsMgr.cpp plNetCliAgeJoiner.cpp diff --git a/Sources/Plasma/PubUtilLib/plNetClientComm/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plNetClientComm/CMakeLists.txt index 42dc6531..186c1860 100644 --- a/Sources/Plasma/PubUtilLib/plNetClientComm/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plNetClientComm/CMakeLists.txt @@ -4,8 +4,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plNetClientComm_SOURCES plNetClientComm.cpp ) diff --git a/Sources/Plasma/PubUtilLib/plNetTransport/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plNetTransport/CMakeLists.txt index 5d987ff3..a59601ae 100644 --- a/Sources/Plasma/PubUtilLib/plNetTransport/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plNetTransport/CMakeLists.txt @@ -3,8 +3,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plNetTransport_SOURCES plNetTransport.cpp plNetTransportMember.cpp diff --git a/Sources/Plasma/PubUtilLib/plPhysX/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plPhysX/CMakeLists.txt index 0fdbbba9..8f2a18ae 100644 --- a/Sources/Plasma/PubUtilLib/plPhysX/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plPhysX/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories("../../NucleusLib") include_directories("../../PubUtilLib") include_directories(${PHYSX_INCLUDE_DIRS}) -include_directories(${OPENSSL_INCLUDE_DIR}) set(plPhysX_SOURCES plLOSDispatch.cpp diff --git a/Sources/Plasma/PubUtilLib/plStatGather/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plStatGather/CMakeLists.txt index 2fb6e70f..eb1868f4 100644 --- a/Sources/Plasma/PubUtilLib/plStatGather/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plStatGather/CMakeLists.txt @@ -3,8 +3,6 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(plStatGather_SOURCES plAutoProfile.cpp plCalculatedProfiles.cpp diff --git a/Sources/Tools/MaxMain/CMakeLists.txt b/Sources/Tools/MaxMain/CMakeLists.txt index daeb663e..dfd469e9 100644 --- a/Sources/Tools/MaxMain/CMakeLists.txt +++ b/Sources/Tools/MaxMain/CMakeLists.txt @@ -7,7 +7,6 @@ include_directories("../../Plasma/NucleusLib/inc") include_directories("../../Plasma/PubUtilLib") include_directories("../../Plasma/PubUtilLib/inc") include_directories(${3dsm_INCLUDE_DIR}) -include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENAL_INCLUDE_DIR}) include_directories(${PHYSX_INCLUDE_DIRS}) include_directories(${PYTHON_INCLUDE_DIR})