mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
DirtySDK (EA's Dirty Sockets library) will be used for the LiveAPI implementation, and depends on: EABase, EAThread.
1376 lines
41 KiB
C
1376 lines
41 KiB
C
/*H*************************************************************************************/
|
|
/*!
|
|
\File cryptbn.c
|
|
|
|
\Description
|
|
This module is implements big integer math needed for our cryptography
|
|
|
|
\Copyright
|
|
Copyright (c) Electronic Arts 2017. ALL RIGHTS RESERVED.
|
|
|
|
\Version 01/18/2017 (eesponda) First version split from CryptRSA
|
|
*/
|
|
/*************************************************************************************H*/
|
|
|
|
/*** Include files *********************************************************************/
|
|
|
|
#include <string.h>
|
|
|
|
#include "DirtySDK/dirtysock/dirtylib.h"
|
|
#include "DirtySDK/crypt/cryptbn.h"
|
|
|
|
/*** Private Functions *****************************************************************/
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnLzCnt
|
|
|
|
\Description
|
|
Implements the function to find the MSB
|
|
|
|
\Input uValue - the input we are finding the msb for
|
|
|
|
\Output
|
|
int32_t - the index of the MSB
|
|
|
|
\Notes
|
|
Uses BitScanReverse on PC as some processors that completely support
|
|
the lzcnt instruction.
|
|
|
|
Durango supports the lzcnt instruction so it can be used.
|
|
|
|
The remaining platforms use the builtin as it has been supported by gcc
|
|
for some time.
|
|
|
|
\Version 03/06/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static int32_t _CryptBnLzCnt(ucrypt_t uValue)
|
|
{
|
|
#if defined(DIRTYCODE_PC)
|
|
unsigned long uResult;
|
|
|
|
#if UCRYPT_SIZE == 4
|
|
_BitScanReverse(&uResult, uValue);
|
|
#else
|
|
_BitScanReverse64(&uResult, uValue);
|
|
#endif
|
|
return(uResult + 1);
|
|
#elif defined(DIRTYCODE_XBOXONE) || defined(DIRTYCODE_GDK)
|
|
#if UCRYPT_SIZE == 4
|
|
return(UCRYPT_BITSIZE - __lzcnt(uValue));
|
|
#else
|
|
return(UCRYPT_BITSIZE - __lzcnt64(uValue));
|
|
#endif
|
|
#else
|
|
#if UCRYPT_SIZE == 4
|
|
return(UCRYPT_BITSIZE - __builtin_clz(uValue));
|
|
#elif DIRTYCODE_64BITPTR == 1
|
|
return(UCRYPT_BITSIZE - __builtin_clzl(uValue));
|
|
#else
|
|
return(UCRYPT_BITSIZE - __builtin_clzll(uValue));
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnExpand
|
|
|
|
\Description
|
|
Expands the width of the big number by one prepending an entry
|
|
|
|
\Input *pState - the big number
|
|
\Input uNewEntry - the entry we are adding
|
|
|
|
\Version 02/27/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static void _CryptBnExpand(CryptBnT *pState, ucrypt_t uNewEntry)
|
|
{
|
|
if (pState->iWidth < CRYPTBN_MAX_WIDTH)
|
|
{
|
|
pState->aData[pState->iWidth++] = uNewEntry;
|
|
}
|
|
else
|
|
{
|
|
NetPrintf(("cryptbn: tried to increase the size of number's width past the max\n"));
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnShrink
|
|
|
|
\Description
|
|
Shrink until you find a non-zero entry or the width is one
|
|
|
|
\Input *pState - the big number
|
|
|
|
\Version 02/27/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static void _CryptBnShrink(CryptBnT *pState)
|
|
{
|
|
int32_t iWidth = pState->iWidth;
|
|
|
|
while ((iWidth > 1) && (pState->aData[iWidth-1] == 0))
|
|
{
|
|
iWidth -= 1;
|
|
}
|
|
pState->iWidth = iWidth;
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnSet
|
|
|
|
\Description
|
|
Set an entry from the big number
|
|
|
|
\Input *pState - the big number
|
|
\Input iIndex - the index of the entry
|
|
\Input uValue - the entry value
|
|
|
|
\Notes
|
|
This helps us safely retrieve entries when the index is outside our bounds
|
|
|
|
\Version 02/27/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static void _CryptBnSet(CryptBnT *pState, int32_t iIndex, ucrypt_t uValue)
|
|
{
|
|
if (iIndex < pState->iWidth)
|
|
{
|
|
pState->aData[iIndex] = uValue;
|
|
}
|
|
else if (iIndex < CRYPTBN_MAX_WIDTH)
|
|
{
|
|
pState->aData[iIndex] = uValue;
|
|
pState->iWidth = iIndex + 1;
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnIsZero
|
|
|
|
\Description
|
|
Checks if a big number is zero
|
|
|
|
\Input *pState - the big number
|
|
|
|
\Output
|
|
uint8_t - TRUE if zero, FALSE otherwise
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static uint8_t _CryptBnIsZero(const CryptBnT *pState)
|
|
{
|
|
int32_t iWidth;
|
|
|
|
for (iWidth = pState->iWidth; iWidth > 0; iWidth -= 1)
|
|
{
|
|
if (pState->aData[iWidth-1] != 0)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnIsEven
|
|
|
|
\Description
|
|
Checks if a big number is even
|
|
|
|
\Input *pState - the big number
|
|
|
|
\Output
|
|
uint8_t - TRUE if even, FALSE if odd
|
|
|
|
\Version 02/07/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static uint8_t _CryptBnIsEven(const CryptBnT *pState)
|
|
{
|
|
// we only check the bottom limb
|
|
return((pState->aData[0] & 1) == 0);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnAdd
|
|
|
|
\Description
|
|
Adds two big numbers together
|
|
|
|
\Input *pState - the result of the operation
|
|
\Input *pAdd1 - the left side
|
|
\Input *pAdd2 - the right side
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static void _CryptBnAdd(CryptBnT *pState, const CryptBnT *pAdd1, const CryptBnT *pAdd2)
|
|
{
|
|
ucrypt_t uAccum;
|
|
int32_t iWidth = DS_MAX(pAdd1->iWidth, pAdd2->iWidth), iCount;
|
|
|
|
// do the add
|
|
for (uAccum = 0, iCount = 0; iCount < iWidth; iCount += 1)
|
|
{
|
|
ucrypt_t uResult = uAccum, uLhs = pAdd1->aData[iCount], uRhs = pAdd2->aData[iCount];
|
|
// do the math, setting carry on overflow
|
|
uAccum = ((uResult += uLhs) < uLhs);
|
|
uAccum |= ((uResult += uRhs) < uRhs);
|
|
// set the value
|
|
_CryptBnSet(pState, iCount, uResult);
|
|
}
|
|
|
|
if (uAccum != 0)
|
|
{
|
|
_CryptBnExpand(pState, uAccum);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function _CryptBnSubtract
|
|
|
|
\Description
|
|
Subtracts two big numbers
|
|
|
|
\Input *pState - result of subtraction
|
|
\Input *pSub1 - the left hand side of the equation
|
|
\Input *pSub2 - the right hand side of the equation
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
static void _CryptBnSubtract(CryptBnT *pState, const CryptBnT *pSub1, const CryptBnT *pSub2)
|
|
{
|
|
ucrypt_t uAccum;
|
|
int32_t iWidth = DS_MAX(pSub1->iWidth, pSub2->iWidth), iCount;
|
|
|
|
for (uAccum = 0, iCount = 0; iCount < iWidth; iCount += 1)
|
|
{
|
|
ucrypt_t uResult, uFinalResult;
|
|
ucrypt_t uLhs = pSub1->aData[iCount], uRhs = pSub2->aData[iCount];
|
|
|
|
// calculate the result without borrow
|
|
uResult = uLhs - uRhs;
|
|
// calculate the result after borrow
|
|
uFinalResult = uResult - uAccum;
|
|
|
|
// calculate the new borrow if first or second calculation resulted in overflow
|
|
uAccum = (uResult > uLhs) | (uFinalResult > uResult);
|
|
|
|
// save result
|
|
_CryptBnSet(pState, iCount, uFinalResult);
|
|
}
|
|
}
|
|
|
|
/*** Public functions ******************************************************************/
|
|
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnInit
|
|
|
|
\Description
|
|
Initializes the large number with zero at a given width
|
|
|
|
\Input *pState - pointer to output large number array of ucrypt_t units
|
|
\Input iWidth - width of output
|
|
|
|
\Version 01/18/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnInit(CryptBnT *pState, int32_t iWidth)
|
|
{
|
|
ds_memclr(pState, sizeof(*pState));
|
|
pState->iWidth = iWidth;
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnInitSet
|
|
|
|
\Description
|
|
Initializes the large number with a number
|
|
|
|
\Input *pState - pointer to output large number array of ucrypt_t units
|
|
\Input uValue - value we are initializing the big number with
|
|
|
|
\Version 01/18/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnInitSet(CryptBnT *pState, uint32_t uValue)
|
|
{
|
|
ds_memclr(pState, sizeof(*pState));
|
|
pState->iWidth = 1;
|
|
pState->aData[0] = uValue;
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnInitFrom
|
|
|
|
\Description
|
|
Convert from msb bytes to int32_t number format
|
|
|
|
\Input *pState - pointer to output large number array of ucrypt_t units
|
|
\Input iWidth - width of output - if negative, auto-calculate width
|
|
\Input *pSource - pointer to input large number array of bytes
|
|
\Input iLength - length of input in bytes
|
|
|
|
\Output
|
|
int32_t - width in ucrypt_t units
|
|
|
|
\Version 03/08/2002 (gschaefer)
|
|
\Version 03/03/2004 (sbevan) Handle odd iLength
|
|
*/
|
|
/*************************************************************************************H*/
|
|
int32_t CryptBnInitFrom(CryptBnT *pState, int32_t iWidth, const uint8_t *pSource, int32_t iLength)
|
|
{
|
|
ucrypt_t *pResult = pState->aData;
|
|
int32_t iFullWordCount = iLength/sizeof(*pResult);
|
|
int32_t iWordCount = (iLength+sizeof(*pResult)-1)/sizeof(*pResult);
|
|
|
|
// clear the contents
|
|
ds_memclr(pState, sizeof(*pState));
|
|
|
|
if (iWidth < 0)
|
|
{
|
|
iWidth = iWordCount;
|
|
}
|
|
pState->iWidth = iWidth;
|
|
|
|
if (iFullWordCount != iWordCount)
|
|
{
|
|
/* calculate how many bytes we need to write and
|
|
generate a left shift amount based on that */
|
|
int32_t iDiff = iLength - (iFullWordCount * UCRYPT_SIZE);
|
|
int32_t iLeftShiftAmount = (iDiff - 1) * 8;
|
|
|
|
// encode the bytes into the buffer until there is nothing left
|
|
while (iLeftShiftAmount >= 0)
|
|
{
|
|
pResult[iWidth - 1] |= ((ucrypt_t)*pSource++ << iLeftShiftAmount);
|
|
iLeftShiftAmount -= 8;
|
|
}
|
|
iWidth -= 1;
|
|
}
|
|
for (; iWidth > 0; iWidth -= 1)
|
|
{
|
|
#if (UCRYPT_SIZE == 4)
|
|
pResult[iWidth-1] = (pSource[0] << 24) | (pSource[1] << 16) | (pSource[2] << 8) | (pSource[3] << 0);
|
|
#else
|
|
pResult[iWidth-1] = ((ucrypt_t)pSource[0] << 56) | ((ucrypt_t)pSource[1] << 48) | ((ucrypt_t)pSource[2] << 40) | ((ucrypt_t)pSource[3] << 32) |
|
|
((ucrypt_t)pSource[4] << 24) | ((ucrypt_t)pSource[5] << 16) | ((ucrypt_t)pSource[6] << 8) | ((ucrypt_t)pSource[7] << 0);
|
|
#endif
|
|
pSource += UCRYPT_SIZE;
|
|
}
|
|
return(iWordCount);
|
|
}
|
|
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnInitLeFrom
|
|
|
|
\Description
|
|
Convert the bytes into a big number in little-endian form
|
|
|
|
\Input *pState - pointer to output large number array of ucrypt_t units
|
|
\Input *pSource - pointer to input large number array of bytes
|
|
\Input iLength - length of input in bytes
|
|
|
|
\Output
|
|
int32_t - width in ucrypt_t units
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
int32_t CryptBnInitLeFrom(CryptBnT *pState, const uint8_t *pSource, int32_t iLength)
|
|
{
|
|
//int32_t iWidth;
|
|
ucrypt_t *pResult = pState->aData;
|
|
int32_t iWordCount = (iLength+sizeof(*pResult)-1)/sizeof(*pResult);
|
|
|
|
// clear the contents and init
|
|
ds_memclr(pState, sizeof(*pState));
|
|
pState->iWidth = iWordCount;
|
|
ds_memcpy_s(pState->aData, pState->iWidth*sizeof(*pState->aData), pSource, iLength);
|
|
|
|
return(iWordCount);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnLeftShift
|
|
|
|
\Description
|
|
Left shifts a large number by a bit
|
|
|
|
\Input *pState - pointer to input and output large number array
|
|
|
|
\Notes
|
|
pState:iWidth <-- pState:iWidth << 1
|
|
|
|
\Version 10/11/2011 (mdonais)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnLeftShift(CryptBnT *pState)
|
|
{
|
|
ucrypt_t uAccum;
|
|
int32_t iWidth, iCount;
|
|
|
|
// do the shift
|
|
for (uAccum = 0, iCount = 0, iWidth = pState->iWidth; iCount < iWidth; iCount += 1)
|
|
{
|
|
ucrypt_t uResult, uFinalResult, uVal;
|
|
|
|
uVal = pState->aData[iCount];
|
|
uResult = uVal << 1;
|
|
uFinalResult = uResult + uAccum;
|
|
uAccum = (uResult < uVal);
|
|
pState->aData[iCount] = uFinalResult;
|
|
}
|
|
|
|
// expand if necessary
|
|
if (uAccum != 0)
|
|
{
|
|
_CryptBnExpand(pState, uAccum);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnLeftShift2
|
|
|
|
\Description
|
|
Left shifts a large number by a number of bits
|
|
|
|
\Input *pState - pointer to input and output large number array
|
|
\Input iBits - the number of bits to shift
|
|
|
|
\Notes
|
|
pState:iWidth <-- pState:iWidth << iBits
|
|
|
|
\Version 4/14/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnLeftShift2(CryptBnT *pState, int32_t iBits)
|
|
{
|
|
int32_t iOffset, iIndex;
|
|
const int32_t iBitLen = CryptBnBitLen(pState) + iBits;
|
|
|
|
/* make sure this shift would not exceed the width of the number
|
|
normally I would just set to zero but I need to indicate to the caller
|
|
that the output might not be what they expected */
|
|
if (iBitLen > CRYPTBN_MAX_BITS)
|
|
{
|
|
NetPrintf(("cryptbn: tried to left shift past the max width which will truncate all the data\n"));
|
|
return;
|
|
}
|
|
|
|
/* if we are trying to shift up one ucrypt_t unit or more
|
|
then calculate the number of ucrypt_t units and the number
|
|
of leftover bits we need to calculate */
|
|
if (iBits >= UCRYPT_BITSIZE)
|
|
{
|
|
iOffset = iBits / UCRYPT_BITSIZE;
|
|
iBits %= UCRYPT_BITSIZE;
|
|
|
|
/* shift the array to the right (left shift) the number of full ucrypt_t units (UCRYPT_BITSIZE)
|
|
clear the lower ucrypt_t units
|
|
update the width */
|
|
memmove(pState->aData+iOffset, pState->aData, pState->iWidth * sizeof(*pState->aData));
|
|
ds_memclr(pState->aData, iOffset * sizeof(*pState->aData));
|
|
pState->iWidth += iOffset;
|
|
|
|
// if there are no left over bits then we have nothing left to do
|
|
if (iBits == 0)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// check if we past a ucrypt_t boundary and need to expand
|
|
if (iBitLen > pState->iWidth*UCRYPT_BITSIZE)
|
|
{
|
|
pState->iWidth += 1;
|
|
}
|
|
|
|
// shift the items in the array over manually
|
|
for (iIndex = pState->iWidth-1; iIndex > 0; iIndex -= 1)
|
|
{
|
|
pState->aData[iIndex] = (pState->aData[iIndex] << iBits) | (pState->aData[iIndex - 1] >> (UCRYPT_BITSIZE - iBits));
|
|
}
|
|
pState->aData[0] <<= iBits;
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnRightShift2
|
|
|
|
\Description
|
|
Right shifts a large number by a number of bits
|
|
|
|
\Input *pState - pointer to input and output large number array
|
|
\Input iBits - the number of bits to shift
|
|
|
|
\Notes
|
|
pState:iWidth <-- pState:iWidth >> iBits
|
|
|
|
\Version 4/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnRightShift2(CryptBnT *pState, int32_t iBits)
|
|
{
|
|
int32_t iIndex;
|
|
|
|
/* if shifting right more than the bit length is the same
|
|
as setting to zero */
|
|
if (CryptBnBitLen(pState) <= iBits)
|
|
{
|
|
CryptBnInitSet(pState, 0);
|
|
return;
|
|
}
|
|
|
|
/* if we are trying to shift up one ucrypt_t unit or more
|
|
then calculate the number of ucrypt_t units and the number
|
|
of leftover bits we need to calculate */
|
|
if (iBits >= UCRYPT_BITSIZE)
|
|
{
|
|
int32_t iOffset = iBits / UCRYPT_BITSIZE;
|
|
iBits %= UCRYPT_BITSIZE;
|
|
|
|
/* shift the array to the left (right shift) the number of full ucrypt_t units (UCRYPT_BITSIZE)
|
|
update the width
|
|
clear the upper ucrypt_t units */
|
|
memmove(pState->aData, pState->aData+iOffset, (pState->iWidth-iOffset)*sizeof(*pState->aData));
|
|
pState->iWidth -= iOffset;
|
|
ds_memclr(pState->aData+pState->iWidth, iOffset*sizeof(*pState->aData));
|
|
|
|
// if there are no left over bits then we have nothing left to do
|
|
if (iBits == 0)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// shift the items in the array over manually
|
|
for (iIndex = 0; iIndex < pState->iWidth-1; iIndex += 1)
|
|
{
|
|
pState->aData[iIndex] = (pState->aData[iIndex] >> iBits) | (pState->aData[iIndex + 1] << (UCRYPT_BITSIZE - iBits));
|
|
}
|
|
pState->aData[iIndex] >>= iBits;
|
|
|
|
/* check if we past a ucrypt_t boundary and need to shrink
|
|
if the number of bits is at or under the next boundary then shrink to there
|
|
we do not shrink under 1, as that is handled at the top of the function */
|
|
if ((pState->iWidth > 1) && (CryptBnBitLen(pState) <= ((pState->iWidth-1)*UCRYPT_BITSIZE)))
|
|
{
|
|
pState->iWidth -= 1;
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnBitTest
|
|
|
|
\Description
|
|
Check to see if a particular bit is set within a large bit vector
|
|
|
|
\Input *pState - pointer to input bit vector
|
|
\Input iBit - bit number to test (zero-relative)
|
|
|
|
\Output
|
|
uint8_t - TRUE if set, else FALSE
|
|
|
|
\Notes
|
|
uResult <-- pValue:iWidth & (1 << iBit)
|
|
|
|
\Version 03/08/2002 (gschaefer)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
uint8_t CryptBnBitTest(const CryptBnT *pState, int32_t iBit)
|
|
{
|
|
int32_t iBitOff = iBit & (UCRYPT_BITSIZE-1);
|
|
int32_t iOffset = iBit / UCRYPT_BITSIZE;
|
|
return((pState->aData[iOffset] & ((ucrypt_t)1 << iBitOff)) != 0);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnBitSet
|
|
|
|
\Description
|
|
Set a particular bit in the big number
|
|
|
|
\Input *pState - pointer to input bit vector
|
|
\Input iBit - bit number to set (zero-relative)
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnBitSet(CryptBnT *pState, int32_t iBit)
|
|
{
|
|
int32_t iBitOff, iOffset;
|
|
|
|
while (pState->iWidth*UCRYPT_BITSIZE <= iBit)
|
|
{
|
|
_CryptBnExpand(pState, 0);
|
|
}
|
|
iBitOff = iBit & (UCRYPT_BITSIZE - 1);
|
|
iOffset = iBit / UCRYPT_BITSIZE;
|
|
pState->aData[iOffset] |= ((ucrypt_t)1 << iBitOff);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnBitAnd
|
|
|
|
\Description
|
|
Performs bitwise and on two big numbers
|
|
|
|
\Input *pState - [out] output of the result of the operation
|
|
\Input *pLhs - big number on left hand side of operation
|
|
\Input *pRhs - big number on right hand side of operation
|
|
|
|
\Version 04/06/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnBitAnd(CryptBnT *pState, const CryptBnT *pLhs, const CryptBnT *pRhs)
|
|
{
|
|
int32_t iWidth = DS_MAX(pLhs->iWidth, pRhs->iWidth), iCount;
|
|
for (iCount = 0; iCount < iWidth; iCount += 1)
|
|
{
|
|
_CryptBnSet(pState, iCount, pLhs->aData[iCount] & pRhs->aData[iCount]);
|
|
}
|
|
|
|
// compact the big number in the case the operation zeroed out the upper limps
|
|
_CryptBnShrink(pState);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnBitXor
|
|
|
|
\Description
|
|
Performs bitwise xor on two big numbers
|
|
|
|
\Input *pState - [out] output of the result of the operation
|
|
\Input *pLhs - big number on left hand side of operation
|
|
\Input *pRhs - big number on right hand side of operation
|
|
|
|
\Version 04/06/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnBitXor(CryptBnT *pState, const CryptBnT *pLhs, const CryptBnT *pRhs)
|
|
{
|
|
int32_t iWidth = DS_MAX(pLhs->iWidth, pRhs->iWidth), iCount;
|
|
for (iCount = 0; iCount < iWidth; iCount += 1)
|
|
{
|
|
_CryptBnSet(pState, iCount, pLhs->aData[iCount] ^ pRhs->aData[iCount]);
|
|
}
|
|
|
|
// compact the big number in the case the operation zeroed out the upper limps
|
|
_CryptBnShrink(pState);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnBitLen
|
|
|
|
\Description
|
|
Figures out the bit length of big number
|
|
|
|
\Input *pState - big number state
|
|
|
|
\Output
|
|
int32_t - the number of bits in the big number
|
|
|
|
\Version 03/02/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
int32_t CryptBnBitLen(const CryptBnT *pState)
|
|
{
|
|
int32_t iResult, iIndex;
|
|
for (iResult = 0, iIndex = pState->iWidth - 1; iIndex >= 0; iIndex -= 1)
|
|
{
|
|
if (pState->aData[iIndex] != 0)
|
|
{
|
|
iResult = _CryptBnLzCnt(pState->aData[iIndex]);
|
|
break;
|
|
}
|
|
}
|
|
return(iResult > 0 ? iResult + (UCRYPT_BITSIZE * iIndex) : 0);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnByteLen
|
|
|
|
\Description
|
|
Figures out the byte length of big number
|
|
|
|
\Input *pState - big number state
|
|
|
|
\Output
|
|
int32_t - the number of bytes in the big number
|
|
|
|
\Version 03/13/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
int32_t CryptBnByteLen(const CryptBnT *pState)
|
|
{
|
|
return(pState->iWidth * (signed)sizeof(*pState->aData));
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnModAdd
|
|
|
|
\Description
|
|
Adds to big numbers over a modulus
|
|
|
|
\Input *pState - big number state
|
|
\Input *pAdd1 - first big number to add
|
|
\Input *pAdd2 - second big number to add
|
|
\Input *pMod - modulus we are adding over
|
|
|
|
\Notes
|
|
This function does the redunction in a very simple way and isn't meant for
|
|
numbers very large over the modulus. We needed to make sure that if we use
|
|
the output for modulus multiply it would work under those constraints.
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnModAdd(CryptBnT *pState, const CryptBnT *pAdd1, const CryptBnT *pAdd2, const CryptBnT *pMod)
|
|
{
|
|
// do the addition
|
|
_CryptBnAdd(pState, pAdd1, pAdd2);
|
|
|
|
// reduce?
|
|
if (CryptBnCompare(pState, pMod) > 0)
|
|
{
|
|
CryptBnSubtract(pState, pState, pMod);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnAccumulate
|
|
|
|
\Description
|
|
Accumulate one large number into another
|
|
|
|
\Input *pState - pointer to large number accumulation buffer
|
|
\Input *pAdd - pointer to large number to accumulate to accumulation buffer
|
|
|
|
\Notes
|
|
pState:iWidth <-- pState:iWidth + pAdd:iWidth
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnAccumulate(CryptBnT *pState, const CryptBnT *pAdd)
|
|
{
|
|
if (pState->uSign == 0)
|
|
{
|
|
_CryptBnAdd(pState, pState, pAdd);
|
|
}
|
|
else
|
|
{
|
|
pState->uSign = 0;
|
|
CryptBnSubtract(pState, pAdd, pState);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnIncrement
|
|
|
|
\Description
|
|
Increment a large number by 1
|
|
|
|
\Input *pState - pointer to large number accumulation buffer
|
|
|
|
\Version 02/21/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnIncrement(CryptBnT *pState)
|
|
{
|
|
ucrypt_t uAccum;
|
|
int32_t iCount, iWidth;
|
|
|
|
// do the add
|
|
for (uAccum = 1, iCount = 0, iWidth = pState->iWidth; iCount < iWidth; iCount += 1)
|
|
{
|
|
ucrypt_t uResult = uAccum, uVal = pState->aData[iCount];
|
|
|
|
uAccum = ((uResult += uVal) < uVal);
|
|
pState->aData[iCount] = uResult;
|
|
|
|
// if we have nothing to carry over we are done
|
|
if (uAccum == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (uAccum != 0)
|
|
{
|
|
_CryptBnExpand(pState, uAccum);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnSubtract
|
|
|
|
\Description
|
|
Subtract two large numbers
|
|
|
|
\Input *pState - pointer to output large number array
|
|
\Input *pSub1 - pointer to large number to subtract pSub2 from.
|
|
\Input *pSub2 - pointer to second large number
|
|
|
|
\Notes
|
|
pState:iWidth <-- pSub1:iWidth - pSub2:iWidth
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnSubtract(CryptBnT *pState, const CryptBnT *pSub1, const CryptBnT *pSub2)
|
|
{
|
|
// if sub1 - (-sub2) or -sub1 - (sub2) then sub1 + sub2, sign depends on which side is negative
|
|
if (pSub1->uSign ^ pSub2->uSign)
|
|
{
|
|
// add
|
|
_CryptBnAdd(pState, pSub1, pSub2);
|
|
// set sign
|
|
pState->uSign = pSub1->uSign;
|
|
}
|
|
// if -sub1 - (-sub2) or sub1 - sub2
|
|
else
|
|
{
|
|
const int32_t iCompare = CryptBnCompare(pSub1, pSub2);
|
|
|
|
// if sub1 > sub2
|
|
if (iCompare > 0)
|
|
{
|
|
// sub1 - sub2
|
|
_CryptBnSubtract(pState, pSub1, pSub2);
|
|
// set sign
|
|
pState->uSign = pSub1->uSign;
|
|
}
|
|
// else if sub1 < sub2
|
|
else if (iCompare < 0)
|
|
{
|
|
// sub2 - sub1
|
|
_CryptBnSubtract(pState, pSub2, pSub1);
|
|
// set sign
|
|
pState->uSign = ~pSub1->uSign;
|
|
}
|
|
// else they are the same so it is zero
|
|
else
|
|
{
|
|
CryptBnInitSet(pState, 0);
|
|
}
|
|
}
|
|
|
|
_CryptBnShrink(pState);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnDecrement
|
|
|
|
\Description
|
|
Decrement a large number by 1
|
|
|
|
\Input *pState - pointer to output large number array
|
|
|
|
\Version 02/21/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnDecrement(CryptBnT *pState)
|
|
{
|
|
ucrypt_t uAccum;
|
|
int32_t iWidth, iCount;
|
|
|
|
for (uAccum = 1, iCount = 0, iWidth = pState->iWidth; iCount < iWidth; iCount += 1)
|
|
{
|
|
ucrypt_t uResult, uVal = pState->aData[iCount];
|
|
|
|
// calculate the result after borrow
|
|
uResult = uVal - uAccum;
|
|
// calculate the new borrow if first or second calculation resulted in overflow
|
|
uAccum = (uResult > uVal);
|
|
// save result
|
|
_CryptBnSet(pState, iCount, uResult);
|
|
|
|
// if nothing left to borrow we are done
|
|
if (uAccum == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnModMultiply
|
|
|
|
\Description
|
|
Modular multiply using the classical algorithm
|
|
|
|
\Input *pState - pointer to output large number array
|
|
\Input *pMul1 - pointer to large number to multiply with pMul2
|
|
\Input *pMul2 - pointer to second large number
|
|
\Input *pMod - pointer to modulous large number
|
|
|
|
\Notes
|
|
pState:iWidth <-- pMul1:iWidth * pMul2:iWidth % pMod:iWidth
|
|
|
|
\Version 02/27/2002 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnModMultiply(CryptBnT *pState, const CryptBnT *pMul1, const CryptBnT *pMul2, const CryptBnT *pMod)
|
|
{
|
|
int32_t iCount;
|
|
CryptBnT Temp1;
|
|
CryptBnT *pCur = &Temp1;
|
|
uint32_t uSign = pMul2->uSign ^ pMul1->uSign;
|
|
|
|
CryptBnInit(pCur, pMul1->iWidth);
|
|
|
|
// do all the bits
|
|
for (iCount = CryptBnBitLen(pMul1) - 1; iCount >= 0; iCount -= 1)
|
|
{
|
|
// left shift the result
|
|
CryptBnLeftShift(pCur);
|
|
|
|
// do modulus reduction?
|
|
if (CryptBnCompare(pCur, pMod) > 0)
|
|
{
|
|
CryptBnSubtract(pCur, pCur, pMod);
|
|
}
|
|
|
|
// see if we need to add in multiplicand
|
|
if (CryptBnBitTest(pMul1, iCount))
|
|
{
|
|
// add it in
|
|
CryptBnAccumulate(pCur, pMul2);
|
|
|
|
// do modulus reduction?
|
|
if (CryptBnCompare(pCur, pMod) > 0)
|
|
{
|
|
CryptBnSubtract(pCur, pCur, pMod);
|
|
}
|
|
}
|
|
}
|
|
|
|
// deal with going negative
|
|
if (uSign != 0)
|
|
{
|
|
CryptBnSubtract(pCur, pMod, pCur);
|
|
}
|
|
|
|
// copy over the result
|
|
CryptBnClone(pState, pCur);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnMultiply
|
|
|
|
\Description
|
|
Performs multiplication of two big numbers using the classical method
|
|
|
|
\Input *pState - pointer to output large number array
|
|
\Input *pMul1 - pointer to large number to multiply with pMul2
|
|
\Input *pMul2 - pointer to second large number
|
|
|
|
\Notes
|
|
pState:iWidth <-- pMul1:iWidth * pMul2:iWidth
|
|
|
|
\Version 02/28/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnMultiply(CryptBnT *pState, const CryptBnT *pMul1, const CryptBnT *pMul2)
|
|
{
|
|
int32_t iCount;
|
|
CryptBnT Temp1;
|
|
CryptBnT *pCur = &Temp1;
|
|
|
|
CryptBnInit(pCur, pMul1->iWidth);
|
|
|
|
// do all the bits
|
|
for (iCount = CryptBnBitLen(pMul1) - 1; iCount >= 0; iCount -= 1)
|
|
{
|
|
// left shift the result
|
|
CryptBnLeftShift(pCur);
|
|
|
|
// see if we need to add in multiplicand
|
|
if (CryptBnBitTest(pMul1, iCount))
|
|
{
|
|
// add it in
|
|
CryptBnAccumulate(pCur, pMul2);
|
|
}
|
|
}
|
|
|
|
pCur->uSign = pMul1->uSign ^ pMul2->uSign;
|
|
|
|
// copy over the result
|
|
CryptBnClone(pState, pCur);
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnMod
|
|
|
|
\Description
|
|
Performs modulo / divison of dividend by divisor
|
|
|
|
\Input *pDividend - the dividend in the equation
|
|
\Input *pDivisor - the divisor in the equation
|
|
\Input *pRemainder - [out] the result of the modulo operation can be NULL
|
|
\Input *pQuotient - [out] the result of the division operation can be NULL
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnMod(const CryptBnT *pDividend, const CryptBnT *pDivisor, CryptBnT *pRemainder, CryptBnT *pQuotient)
|
|
{
|
|
int32_t iCount;
|
|
CryptBnT Result, Quotient;
|
|
|
|
/* if the dividend is less than the divisor means the result of
|
|
the modulus is the dividend and the quotient is zero */
|
|
const int32_t iCompare = CryptBnCompare(pDividend, pDivisor);
|
|
if (iCompare < 0)
|
|
{
|
|
CryptBnClone(&Result, pDividend);
|
|
CryptBnInitSet(&Quotient, 0);
|
|
}
|
|
else if (iCompare > 0)
|
|
{
|
|
CryptBnInitSet(&Result, 0);
|
|
CryptBnInitSet(&Quotient, 0);
|
|
|
|
/* since we don't need to perform the other operations until we increment
|
|
past zero, lets do this in a loop before we move onto the normal flow */
|
|
for (iCount = CryptBnBitLen(pDividend) - 1; iCount >= 0; iCount -= 1)
|
|
{
|
|
if (CryptBnBitTest(pDividend, iCount))
|
|
{
|
|
CryptBnIncrement(&Result);
|
|
CryptBnLeftShift(&Result);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (iCount = iCount - 1; iCount >= 0; iCount -= 1)
|
|
{
|
|
if (CryptBnBitTest(pDividend, iCount))
|
|
{
|
|
CryptBnIncrement(&Result);
|
|
}
|
|
|
|
// check if we need to reduce, we can bypass when the limbs don't match
|
|
if ((Result.iWidth >= pDivisor->iWidth) && (CryptBnCompare(&Result, pDivisor) >= 0))
|
|
{
|
|
CryptBnSubtract(&Result, &Result, pDivisor);
|
|
CryptBnBitSet(&Quotient, iCount);
|
|
}
|
|
|
|
if (iCount > 0)
|
|
{
|
|
CryptBnLeftShift(&Result);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CryptBnInitSet(&Result, 0);
|
|
CryptBnInitSet(&Quotient, 1);
|
|
}
|
|
|
|
if ((pDividend->uSign != 0) && (CryptBnBitLen(&Result) != 0))
|
|
{
|
|
Result.uSign = 0;
|
|
CryptBnSubtract(&Result, pDivisor, &Result);
|
|
}
|
|
if (pRemainder != NULL)
|
|
{
|
|
CryptBnClone(pRemainder, &Result);
|
|
}
|
|
if (pQuotient != NULL)
|
|
{
|
|
CryptBnClone(pQuotient, &Quotient);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnInverseMod
|
|
|
|
\Description
|
|
Calculates the modular multiplicative inverse using binary extended gcd
|
|
|
|
\Input *pState - the big number state
|
|
\Input *pMod - the modulus
|
|
|
|
\Notes
|
|
See Handbook of Applied Cryptography Chapter 14.4.3 (14.61)
|
|
http://cacr.uwaterloo.ca/hac/about/chap14.pdf
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnInverseMod(CryptBnT *pState, const CryptBnT *pMod)
|
|
{
|
|
int32_t iShift;
|
|
CryptBnT U, V, A, B, C, D;
|
|
|
|
// if the number is negative then switch the sign and subtract the result from mod
|
|
if (pState->uSign != 0)
|
|
{
|
|
pState->uSign = 0;
|
|
CryptBnInverseMod(pState, pMod);
|
|
CryptBnSubtract(pState, pMod, pState);
|
|
return;
|
|
}
|
|
|
|
CryptBnClone(&U, pState);
|
|
CryptBnClone(&V, pMod);
|
|
CryptBnInitSet(&A, 1);
|
|
CryptBnInitSet(&B, 0);
|
|
CryptBnInitSet(&C, 0);
|
|
CryptBnInitSet(&D, 1);
|
|
|
|
// while u and v are even divide by zero, accounting for the number of shifts
|
|
for (iShift = 0; (_CryptBnIsEven(&U) && _CryptBnIsEven(&V)); iShift += 1)
|
|
{
|
|
CryptBnRightShift(&U);
|
|
CryptBnRightShift(&V);
|
|
}
|
|
|
|
// quit out when u is zero
|
|
while (!_CryptBnIsZero(&U))
|
|
{
|
|
// while u is even
|
|
while (_CryptBnIsEven(&U))
|
|
{
|
|
// u <- u/2
|
|
CryptBnRightShift(&U);
|
|
|
|
/* if a congruent to b congruent to 0 mod 2 (they are both even)
|
|
then a <- a/2 and b <- b/2 */
|
|
if (_CryptBnIsEven(&A) && _CryptBnIsEven(&B))
|
|
{
|
|
CryptBnRightShift(&A);
|
|
CryptBnRightShift(&B);
|
|
}
|
|
// else a <- (a+y)/2 and b <- (b-x)/2
|
|
else
|
|
{
|
|
CryptBnAccumulate(&A, pMod);
|
|
CryptBnRightShift(&A);
|
|
CryptBnSubtract(&B, &B, pState);
|
|
CryptBnRightShift(&B);
|
|
}
|
|
}
|
|
|
|
|
|
// while v is even
|
|
while (_CryptBnIsEven(&V))
|
|
{
|
|
// v <- v/2
|
|
CryptBnRightShift(&V);
|
|
|
|
/* if c congruent to d congruent to 0 mod 2 (they are both even)
|
|
then c <- c/2 and d <- d/2 */
|
|
if (_CryptBnIsEven(&C) && _CryptBnIsEven(&D))
|
|
{
|
|
CryptBnRightShift(&C);
|
|
CryptBnRightShift(&D);
|
|
}
|
|
// else c <- (c+y)/2 and d <- (d-x)/2
|
|
else
|
|
{
|
|
CryptBnAccumulate(&C, pMod);
|
|
CryptBnRightShift(&C);
|
|
CryptBnSubtract(&D, &D, pState);
|
|
CryptBnRightShift(&D);
|
|
}
|
|
}
|
|
|
|
// if u > v then u <- u-v, a <- a-c and b <- b-d
|
|
if (CryptBnCompare(&U, &V) >= 0)
|
|
{
|
|
CryptBnSubtract(&U, &U, &V);
|
|
CryptBnSubtract(&A, &A, &C);
|
|
CryptBnSubtract(&B, &B, &D);
|
|
}
|
|
// else v <- v-u, c <- c-a and d <- d-b
|
|
else
|
|
{
|
|
CryptBnSubtract(&V, &V, &U);
|
|
CryptBnSubtract(&C, &C, &A);
|
|
CryptBnSubtract(&D, &D, &B);
|
|
}
|
|
}
|
|
|
|
// a <- C, b <- D but we only need a for the inverse so return that
|
|
CryptBnClone(pState, &C);
|
|
|
|
/* note: if you needed to return v, you would need to left shift by iShift
|
|
but since we don't we don't do anything else */
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnFinal
|
|
|
|
\Description
|
|
Convert from ucrypt_t units back to big-endian bytes
|
|
|
|
\Input *pState - the ucrypt_t units to convert
|
|
\Input *pResult - where to write the 8-bit result.
|
|
\Input iLength - size of the result array in bytes.
|
|
|
|
\Version 03/08/2002 (gschaefer)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnFinal(const CryptBnT *pState, uint8_t *pResult, int32_t iLength)
|
|
{
|
|
const ucrypt_t *pSource = pState->aData;
|
|
|
|
// make the length in terms of words
|
|
iLength /= sizeof(*pSource);
|
|
|
|
// word to byte conversion
|
|
for (; iLength > 0; iLength -= 1)
|
|
{
|
|
#if UCRYPT_SIZE > 4
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 56);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 48);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 40);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 32);
|
|
#endif
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 24);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 16);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1] >> 8);
|
|
*pResult++ = (uint8_t)(pSource[iLength-1]);
|
|
}
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnFinalLe
|
|
|
|
\Description
|
|
Convert from ucrypt_t units back to little-endian bytes
|
|
|
|
\Input *pState - the ucrypt_t units to convert
|
|
\Input *pResult - where to write the 8-bit result.
|
|
\Input iLength - size of the result array in bytes.
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnFinalLe(const CryptBnT *pState, uint8_t *pResult, int32_t iLength)
|
|
{
|
|
ds_memcpy_s(pResult, iLength, pState->aData, CryptBnByteLen(pState));
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnClone
|
|
|
|
\Description
|
|
Copies a big number's contents
|
|
|
|
\Input *pDst - where we are copying to
|
|
\Input *pSrc - where we are copying from
|
|
|
|
\Version 02/27/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnClone(CryptBnT *pDst, const CryptBnT *pSrc)
|
|
{
|
|
ds_memcpy(pDst, pSrc, sizeof(*pDst));
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnPrint
|
|
|
|
\Description
|
|
Prints the contents of a big number
|
|
|
|
\Input *pState - the big number we are printing
|
|
\Input *pTitle - title of the big number
|
|
|
|
\Version 02/06/2018 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
void CryptBnPrint(const CryptBnT *pState, const char *pTitle)
|
|
{
|
|
#if DIRTYCODE_LOGGING
|
|
int32_t iIndex, iOffset;
|
|
char strNumber[16*CRYPTBN_MAX_WIDTH];
|
|
const char *pPrefix = (pState->uSign == 0) ? "0x" : "-0x";
|
|
|
|
for (iIndex = pState->iWidth, iOffset = 0; iIndex > 0; iIndex -= 1)
|
|
{
|
|
iOffset += ds_snzprintf(strNumber+iOffset, sizeof(strNumber)-iOffset, "%016llx", pState->aData[iIndex - 1]);
|
|
}
|
|
NetPrintf(("cryptbn: %s %s%s (%d)\n", pTitle, pPrefix, strNumber, CryptBnBitLen(pState)));
|
|
#endif
|
|
}
|
|
|
|
/*F*************************************************************************************/
|
|
/*!
|
|
\Function CryptBnCompare
|
|
|
|
\Description
|
|
Compare two big numbers together
|
|
|
|
\Input *pLhs - the left side
|
|
\Input *pRhs - the right side
|
|
|
|
\Output
|
|
int32_t - 0=equal, >0=left side larger, <0=right side larger
|
|
|
|
\Version 02/17/2017 (eesponda)
|
|
*/
|
|
/*************************************************************************************H*/
|
|
int32_t CryptBnCompare(const CryptBnT *pLhs, const CryptBnT *pRhs)
|
|
{
|
|
int32_t iWidth;
|
|
|
|
for (iWidth = DS_MAX(pLhs->iWidth, pRhs->iWidth); iWidth > 0; iWidth -= 1)
|
|
{
|
|
ucrypt_t uLhs = pLhs->aData[iWidth - 1], uRhs = pRhs->aData[iWidth - 1];
|
|
if (uLhs == uRhs)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return((uLhs > uRhs) ? 1 : -1);
|
|
}
|
|
return(0);
|
|
}
|