/*********************************************************************
*
* Big Integer Library
* Library for Microchip TCP/IP Stack
* - Provides support for integers larger than 32 bits
*
*********************************************************************
* FileName: BigInt.c
* Dependencies: BigInt_helper.asm (PIC18), BigInt_helper.S
* (PIC24/dsPIC) or BigInt_helper_C32.S (PIC32)
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
* Compiler: Microchip C32 v1.05 or higher
* Microchip C30 v3.12 or higher
* Microchip C18 v3.30 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright (C) 2002-2009 Microchip Technology Inc. All rights
* reserved.
*
* Microchip licenses to you the right to use, modify, copy, and
* distribute:
* (i) the Software when embedded on a Microchip microcontroller or
* digital signal controller product ("Device") which is
* integrated into Licensee's product; or
* (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
* ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
* used in conjunction with a Microchip ethernet controller for
* the sole purpose of interfacing with the ethernet controller.
*
* You should refer to the license agreement accompanying this
* Software for additional information regarding your rights and
* obligations.
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Elliott Wood 6/20/07 Original
* Howard Schlunder 11/21/07 Converted to little endian
********************************************************************/
#define __BIGINT_C
#include "TCPIPConfig.h"
#include "HardwareProfile.h"
#if (defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_SSL_CLIENT)) && !defined(ENC100_INTERFACE_MODE)
#include "TCPIP Stack/TCPIP.h"
// External declarations for assembly helpers
#if defined(__C30__)
extern __attribute__((__near__)) BIGINT_DATA_TYPE *_iA, *_iB, *_xA, *_xB, *_iR, _wC;
#else
extern BIGINT_DATA_TYPE *_iA, *_iB, *_xA, *_xB, *_iR, _wC;
#endif
extern void _addBI(void);
extern void _subBI(void);
extern void _zeroBI(void);
extern void _msbBI(void);
extern void _mulBI(void);
extern void _copyBI(void);
extern void _sqrBI(void);
extern void _masBI(void);
extern void _addBIROM(void);
extern void _subBIROM(void);
extern void _mulBIROM(void);
extern void _masBIROM(void);
#if BIGINT_PROFILE
DWORD addBICounter = 0;
DWORD addBIROMCounter = 0;
DWORD subBICounter = 0;
DWORD subBIROMCounter = 0;
DWORD zeroBICounter = 0;
DWORD msbBICounter = 0;
DWORD mulBICounter = 0;
DWORD mulBIROMCounter = 0;
DWORD sqrBICounter = 0;
DWORD masBICounter = 0;
DWORD masBIROMCounter = 0;
DWORD copyBICounter = 0;
#define addBI() {addBICounter -= TickGet(); _addBI(); addBICounter += TickGet();}
#define addBIROM() {addBIROMCounter -= TickGet(); _addBIROM();addBIROMCounter += TickGet();}
#define subBI() {subBICounter -= TickGet(); _subBI(); subBICounter += TickGet();}
#define subBIROM() {subBIROMCounter -= TickGet(); _subBIROM(); subBIROMCounter += TickGet();}
#define zeroBI() {zeroBICounter -= TickGet(); _zeroBI(); zeroBICounter += TickGet();}
#define msbBI() {msbBICounter -= TickGet(); _msbBI(); msbBICounter += TickGet();}
#define mulBI() {mulBICounter -= TickGet(); _mulBI(); mulBICounter += TickGet();}
#define mulBIROM() {mulBIROMCounter -= TickGet(); _mulBIROM(); mulBIROMCounter += TickGet();}
#define sqrBI() {sqrBICounter -= TickGet(); _sqrBI(); sqrBICounter += TickGet();}
#define masBI() {masBICounter -= TickGet(); _masBI(); masBICounter += TickGet();}
#define masBIROM() {masBIROMCounter -= TickGet(); _masBIROM(); masBIROMCounter += TickGet();}
#define copyBI() {copyBICounter -= TickGet(); _copyBI(); copyBICounter += TickGet();}
#else
#define addBI() _addBI()
#define addBIROM() _addBIROM()
#define subBI() _subBI()
#define subBIROM() _subBIROM()
#define zeroBI() _zeroBI()
#define msbBI() _msbBI()
#define mulBI() _mulBI()
#define mulBIROM() _mulBIROM()
#define sqrBI() _sqrBI()
#define masBI() _masBI()
#define masBIROM() _masBIROM()
#define copyBI() _copyBI()
#endif
#if BIGINT_DEBUG
#if defined(__18CXX)
void BigIntPrint(const BIGINT *a)
{
BIGINT_DATA_TYPE *ptr;
for(ptr = a->ptrMSBMax; ptr >= a->ptrLSB; ptr--)
{
while(BusyUART());
putcUART(btohexa_high(*ptr));
while(BusyUART());
putcUART(btohexa_low(*ptr));
}
}
void BigIntPrintROM(BIGINT_ROM *a)
{
ROM BIGINT_DATA_TYPE *ptr;
for(ptr = a->ptrMSB; ptr >= a->ptrLSB; ptr--)
{
while(BusyUART());
putcUART(btohexa_high(*ptr));
while(BusyUART());
putcUART(btohexa_low(*ptr));
}
}
#elif defined(__C30__)
void BigIntPrint(const BIGINT *a)
{
WORD w;
BYTE v;
BIGINT_DATA_TYPE *ptr;
for(ptr = a->ptrMSBMax; ptr >= a->ptrLSB; ptr--)
{
WORD_VAL wv;
wv.Val = *ptr;
while(BusyUART());
putcUART(btohexa_high(wv.v[1]));
while(BusyUART());
putcUART(btohexa_low(wv.v[1]));
while(BusyUART());
putcUART(btohexa_high(wv.v[0]));
while(BusyUART());
putcUART(btohexa_low(wv.v[0]));
}
}
#endif
void putulhexUART(DWORD dw)
{
while(BusyUART());
putcUART('0');
while(BusyUART());
putcUART('x');
while(BusyUART());
putcUART(btohexa_high(((BYTE*)&dw)[3]));
while(BusyUART());
putcUART(btohexa_low(((BYTE*)&dw)[3]));
while(BusyUART());
putcUART(btohexa_high(((BYTE*)&dw)[2]));
while(BusyUART());
putcUART(btohexa_low(((BYTE*)&dw)[2]));
while(BusyUART());
putcUART(btohexa_high(((BYTE*)&dw)[1]));
while(BusyUART());
putcUART(btohexa_low(((BYTE*)&dw)[1]));
while(BusyUART());
putcUART(btohexa_high(((BYTE*)&dw)[0]));
while(BusyUART());
putcUART(btohexa_low(((BYTE*)&dw)[0]));
}
#endif
static BIGINT_DATA_TYPE* BigIntMSB(BIGINT *n);
/*********************************************************************
* Function: void BigInt(BIGINT *theInt, BIGINT_DATA_TYPE *data, WORD wWordLength)
*
* PreCondition: None
*
* Input: *theInt: the integer to create
* *data: a pointer to the data
* wWordLength: the number of words in the integer (a word is 1 byte on PIC18s, 2 bytes on PIC24/dsPIC)
*
* Output: The BIGINT is ready to use
*
* Side Effects: None
*
* Overview: Call BigInt() to correctly set up the pointers.
*
* Note: None
********************************************************************/
#if defined(BI_USE_CONSTRUCTOR)
void BigInt(BIGINT *theInt, BIGINT_DATA_TYPE *data, WORD wWordLength)
{
theInt->ptrLSB = data;
theInt->ptrMSB = data + wWordLength - 1;
theInt->ptrMSBMax = theInt->ptrMSB;
theInt->bMSBValid = 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_CONSTRUCTOR_ROM)
void BigIntROM(BIGINT_ROM *theInt, ROM BIGINT_DATA_TYPE *data, WORD wWordLength)
{
theInt->ptrLSB = data;
theInt->ptrMSB = data + wWordLength - 1;
// Find the MSB, which can never change
while(*theInt->ptrMSB == 0u)
theInt->ptrMSB--;
}
#endif
/*********************************************************************
* Function: void BigIntZero(BIGINT* theInt)
*
* PreCondition: None
*
* Input: *theInt: the integer to clear
*
* Output: theInt = 0
*
* Side Effects: None
*
* Overview: Call BigIntZero() zero all data bytes in the BigInt
*
* Note: None
********************************************************************/
#if defined(BI_USE_ZERO)
void BigIntZero(BIGINT *theInt)
{
_iA = theInt->ptrLSB;
_xA = theInt->ptrMSBMax;
zeroBI();
// Set up the new MSB pointer
theInt->ptrMSB = theInt->ptrLSB;
theInt->bMSBValid = 1;
}
#endif
/*********************************************************************
* Function: void BigIntMod(BIGINT *n, const BIGINT* m)
*
* PreCondition: None
*
* Input: *n: a pointer to the number
* *m: a pointer to the modulus
*
* Output: *n contains the modded number
* i.e: *n = *n % *m
*
* Side Effects: None
*
* Overview: Call BigIntMod() to calculate the modulus of two
* really big numbers.
*
* Note: Supports at least 2048 bits
********************************************************************/
#if defined(BI_USE_MOD)
void BigIntMod(BIGINT *n, BIGINT* m)
{
BIGINT_DATA_TYPE *ptrMSBn, MSBm;
BIGINT_DATA_TYPE_2 qHatInt;
union
{
BIGINT_DATA_TYPE v[2];
BIGINT_DATA_TYPE_2 Val;
} topTwoWords;
// Find the starting MSBs
ptrMSBn = BigIntMSB(n);
MSBm = *BigIntMSB(m);
// Set up assembly pointers for m
// _iB and _xB are limiters in the _mas function
_iB = m->ptrLSB;
_xB = BigIntMSB(m);
// Find out how many bytes we need to shift and move the LSB up
_iR = n->ptrLSB + (BigIntMagnitudeDifference(n, m) - 1);
// This loops while the order of magnitude (in words) of n > m
// Each iteration modulos off one word of magnitude from n
while(_iR >= n->ptrLSB)
{
// Find qHat = MSBn:MSBn-1/MSBm
topTwoWords.Val = *((BIGINT_DATA_TYPE_2*)(ptrMSBn - 1));
qHatInt = topTwoWords.Val / MSBm;
if(qHatInt > BIGINT_DATA_MAX)
qHatInt = BIGINT_DATA_MAX;
#if BIGINT_DEBUG
putrsUART("\r\n\r\n n = ");
BigIntPrint(n);
putrsUART("\r\n m = ");
BigIntPrint(m);
putrsUART("\r\n qHat (");
putulhexUART(qHatInt);
putrsUART(") = topTwo(");
putulhexUART(topTwoWords.Val);
putrsUART(") / (");
putulhexUART(MSBm);
putrsUART(") ");
#endif
// Once qHat is determined, we multiply M by qHat, shift it up
// as many bytes as possible, and subtract the result.
// In essence, qHat is a rough estimation of the quotient, divided
// by a power of 2^8 (PIC18) or 2^16 (PIC24/dsPIC) or 2^32 (PIC32)
// This implementation multiplies and subtracts in the same step
// using a _mas function which saves about 30% of clock cycles.
// Save the old MSB and set up the ASM pointers
_wC = (BIGINT_DATA_TYPE)qHatInt;
// Do the multiply and subtract
// Occassionally this results in underflow...this is solved below.
masBI();
// qHat may have been 1 or 2 greater than possible. If so,
// the new MSB will be greater than the old one, so we *add*
// M back to N in the shifted position until overflow occurs
// and this case corrects itself.
while(topTwoWords.v[1] < *BigIntMSB(n))
// while(((BIGINT_DATA_TYPE*)&topTwoWords)[1] < *BigIntMSB(n))
{
_iA = _iR;
_xA = BigIntMSB(n);
addBI();
}
// We should have modulated off a word (or two if we were lucky),
// so move our MSB and LSB pointers as applicable
while(*ptrMSBn == 0x0u)
{
_iR--;
n->ptrMSB--;
ptrMSBn--;
}
}
// Iteration of the _mas function can only handle full-byte orders
// of magnitude. The result may still be a little larger, so this
// cleans up the last few multiples with simple subtraction.
while(BigIntCompare(n, m) >= 0)
{
_iA = n->ptrLSB;
_xA = n->ptrMSB;
subBI();
// Invalidate MSB pointer
n->bMSBValid = 0;
}
}
#endif
#if defined(__18CXX) && defined(BI_USE_MOD_ROM)
void BigIntModROM(BIGINT *n, BIGINT_ROM* m)
{
BIGINT_DATA_TYPE *ptrMSBn, MSBm;
BIGINT_DATA_TYPE_2 qHatInt, topTwoWords;
// Find the starting MSBs
ptrMSBn = BigIntMSB(n);
MSBm = *m->ptrMSB;
// Set up assembly pointers for m
// _iBr and _xBr are limiters in the _masROM function
_iBr = m->ptrLSB;
_xBr = m->ptrMSB;
// Find out how many bytes we need to shift and move the LSB up
_iR = n->ptrLSB + (BigIntMagnitudeDifferenceROM(n, m) - 1);
// This loops while the order of magnitude (in words) of n > m
// Each iteration modulos off one word of magnitude from n
while(_iR >= n->ptrLSB)
{
// Find qHat = MSBn:MSBn-1/MSBm
topTwoWords = *((BIGINT_DATA_TYPE_2*)(ptrMSBn - 1));
qHatInt = topTwoWords / MSBm;
if(qHatInt > BIGINT_DATA_MAX)
qHatInt = BIGINT_DATA_MAX;
#if BIGINT_DEBUG
putrsUART("\r\n\r\n n = ");
BigIntPrint(n);
putrsUART("\r\n m = ");
BigIntPrintROM(m);
putrsUART("\r\n qHat (");
putulhexUART(qHatInt);
putrsUART(") = topTwo(");
putulhexUART(topTwoWords);
putrsUART(") / (");
putulhexUART(MSBm);
putrsUART(") ");
#endif
// Once qHat is determined, we multiply M by qHat, shift it up
// as many bytes as possible, and subtract the result.
// In essence, qHat is a rough estimation of the quotient, divided
// by a power of 2^8 (PIC18) or 2^16 (PIC24/dsPIC) or 2^32 (PIC32)
// This implementation multiplies and subtracts in the same step
// using a _mas function which saves about 30% of clock cycles.
// Save the old MSB and set up the ASM pointers
_wC = (BIGINT_DATA_TYPE)qHatInt;
// Do the multiply and subtract
// Occassionally this results in underflow...this is solved below.
masBIROM();
// qHat may have been 1 or 2 greater than possible. If so,
// the new MSB will be greater than the old one, so we *add*
// M back to N in the shifted position until overflow occurs
// and this case corrects itself.
while(((BIGINT_DATA_TYPE*)&topTwoWords)[1] < *BigIntMSB(n))
{
_iA = _iR;
_xA = BigIntMSB(n);
addBIROM();
}
// We should have modulated off a word (or two if we were lucky),
// so move our MSB and LSB pointers as applicable
while(*ptrMSBn == 0x0u)
{
_iR--;
n->ptrMSB--;
ptrMSBn--;
}
}
// Iteration of the _mas function can only handle full-byte orders
// of magnitude. The result may still be a little larger, so this
// cleans up the last few multiples with simple subtraction.
while(BigIntCompareROM(n, m) >= 0)
{
_iA = n->ptrLSB;
_xA = n->ptrMSB;
subBIROM();
// Invalidate MSB pointer
n->bMSBValid = 0;
}
}
#endif
/*********************************************************************
* Function: CHAR BigIntCompare(BIGINT *a, BIGINT *b)
*
* PreCondition: None
*
* Input: *a: a pointer to the first number
* *b: a pointer to the second number
*
* Output: 0 if a == b
* 1 if a > b
* -1 if a < b
*
* Side Effects: None
*
* Overview: Determines if a > b, a < b, or a == b
*
* Note: Supports at least 2048 bits.
*
********************************************************************/
#if defined(BI_USE_COMPARE)
CHAR BigIntCompare(BIGINT *a, BIGINT *b)
{
PTR_BASE magA, magB;
BIGINT_DATA_TYPE valA, valB;
BIGINT_DATA_TYPE *ptrA;
BIGINT_DATA_TYPE *ptrB;
magA = BigIntMSB(a) - a->ptrLSB;
magB = BigIntMSB(b) - b->ptrLSB;
#if BIGINT_DEBUG_COMPARE
putrsUART("\r\n Compared Magnitudes |a|:");
putulhexUART(w1);
putrsUART(" |b|:");
putulhexUART(w2);
putrsUART(" diff:");
putulhexUART(w1-w2);
#endif
if(magA > magB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a > b");
#endif
return 1;
}
else if(magA < magB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a < b");
#endif
return -1;
}
#if BIGINT_DEBUG_COMPARE
putrsUART(" Checking further bytes...");
#endif
// Loop through all words, looking for a non-equal word
ptrA = BigIntMSB(a);
ptrB = BigIntMSB(b);
while(ptrA >= a->ptrLSB) // Magnitude is same, no need to check ptrB bounds
{
valA = *ptrA--;
valB = *ptrB--;
if(valA > valB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a > b");
#endif
return 1;
}
else if(valA < valB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a < b");
#endif
return -1;
}
}
// All words were exactly identical, return match
return 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_COMPARE_ROM)
CHAR BigIntCompareROM(BIGINT *a, BIGINT_ROM *b)
{
PTR_BASE magA, magB;
BIGINT_DATA_TYPE valA, valB;
BIGINT_DATA_TYPE *ptrA;
ROM BIGINT_DATA_TYPE *ptrB;
magA = BigIntMSB(a) - a->ptrLSB;
magB = b->ptrMSB - b->ptrLSB;
#if BIGINT_DEBUG_COMPARE
putrsUART("\r\n Compared Magnitudes |a|:");
putulhexUART(w1);
putrsUART(" |b|:");
putulhexUART(w2);
putrsUART(" diff:");
putulhexUART(s);
#endif
if(magA > magB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a > b");
#endif
return 1;
}
else if(magA < magB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a < b");
#endif
return -1;
}
#if BIGINT_DEBUG_COMPARE
putrsUART(" Checking further bytes...");
#endif
// Loop through all words, looking for a non-equal word
ptrA = BigIntMSB(a);
ptrB = b->ptrMSB;
while(ptrA >= a->ptrLSB) // Magnitude is same, no need to check ptrB bounds
{
valA = *ptrA--;
valB = *ptrB--;
if(valA > valB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a > b");
#endif
return 1;
}
else if (valA < valB)
{
#if BIGINT_DEBUG_COMPARE
putrsUART(" a < b");
#endif
return -1;
}
}
// All words were exactly identical, return match
return 0;
}
#endif
/*********************************************************************
* Function: int BigIntMagnitudeDifference(const BIGINT *n)
*
* PreCondition: None
*
* Input: *a: a pointer to the first number
* *b: a pointer to the second number
*
* Output: Returns the magnitude of difference in zero-bytes
*
* Side Effects: None
*
* Overview: Helps to quickly determine a byte shift for operations
*
* Note: Supports at least 2048 bits
********************************************************************/
#if defined(BI_USE_MAG_DIFF)
int BigIntMagnitudeDifference(BIGINT *a, BIGINT *b)
{
return BigIntMagnitude(a) - BigIntMagnitude(b);
}
#endif
#if defined(__18CXX) && defined(BI_USE_MAG_DIFF_ROM)
int BigIntMagnitudeDifferenceROM(BIGINT *a, BIGINT_ROM *b)
{
return BigIntMagnitude(a) - BigIntMagnitudeROM(b);
}
#endif
/*********************************************************************
* Function: WORD BigIntMagnitude(BIGINT *n)
*
* PreCondition: None
*
* Input: *n: a pointer to the number
*
* Output: Returns the number of significant words in the data, less one (ex: 0x12, has zero magnitude)
*
* Side Effects: None
*
* Overview: Helps to quickly determine the magnitude of the number
*
* Note: Supports at least 2048 bits
********************************************************************/
#if defined(BI_USE_MAG)
WORD BigIntMagnitude(BIGINT *n)
{
return BigIntMSB(n) - n->ptrLSB;
}
#endif
#if defined(__18CXX) && defined(BI_USE_MAG_ROM)
WORD BigIntMagnitudeROM(BIGINT_ROM *n)
{
return n->ptrMSB - n->ptrLSB;
}
#endif
/*********************************************************************
* Function: static BIGINT_DATA_TYPE* BigIntMSB(const BIGINT *n)
*
* PreCondition: None
*
* Input: *n: a pointer to the number
*
* Output: n->ptrMSB points to the MSB of n
*
* Side Effects: None
*
* Overview: Updates the ptrMSB. Use after an operation in which
* the new MSB cannot be estimated.
*
* Note: Supports at least 2048 bits
********************************************************************/
#if defined(BI_USE_MSB)
static BIGINT_DATA_TYPE* BigIntMSB(BIGINT *n)
{
BIGINT_DATA_TYPE *iASave, *xASave;
// If cached value is valid, use it
if(n->bMSBValid)
return n->ptrMSB;
// Otherwise find a new MSB and save it
iASave = _iA;
xASave = _xA;
_iA = n->ptrLSB;
_xA = n->ptrMSBMax;
msbBI();
n->ptrMSB = _xA;
n->bMSBValid = 1;
_iA = iASave;
_xA = xASave;
return n->ptrMSB;
}
#endif
/*********************************************************************
* Function: void BigIntMultiply(const BIGINT *a, const BIGINT *b, BIGINT *res)
*
* PreCondition: res->ptrMSBMax - res->ptrLSB + 1 >= a->ptrMSBMax - a->ptrLSB + 1 + b->ptrMSBMax - b->ptrLSB + 1, &res != &[a|b]
*
* Input: *a: a pointer to the first number
* *b: a pointer to the second number
* *res: a pointer to memory to store the result
*
* Output: *res contains the result of a * b
*
* Side Effects: None
*
* Overview: Call BigIntMultiply() to multiply two really big numbers.
*
* Note: Supports at least 2048 result bits.
* This essentially implements elementary school long
* multiplication in base 256 (PIC18) or 65536 (PIC24/dsPIC).
* This is the fastest algorithm until you pass about
* 1024 bits. This is O(n^2).
* res CANNOT be A or B.
********************************************************************/
#if defined(BI_USE_MULTIPLY)
void BigIntMultiply(BIGINT *a, BIGINT *b, BIGINT *res)
{
// Clear out the result
BigIntZero(res);
// Load the start and stop pointers
_iA = a->ptrLSB;
_xA = BigIntMSB(a);
_iB = b->ptrLSB;
_xB = BigIntMSB(b);
_iR = res->ptrLSB;
// Perform the multiplication
mulBI();
// Invalidate the MSB ptr
res->bMSBValid = 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_MULTIPLY_ROM)
void BigIntMultiplyROM(BIGINT *a, BIGINT_ROM *b, BIGINT *res)
{
//clear out the result
BigIntZero(res);
// Load the start and stop pointers
_iA = a->ptrLSB;
_xA = BigIntMSB(a);
_iBr = b->ptrLSB;
_xBr = b->ptrMSB;
_iR = res->ptrLSB;
// Perform the multiplication
mulBIROM();
// Invalidate the MSB ptr
res->bMSBValid = 0;
}
#endif
/*********************************************************************
* Function: void BigIntSquare(const BIGINT *a, BIGINT *res)
*
* PreCondition: res->size >= 2 * a->size, &res != &a
*
* Input: *a: a pointer to the number
* *res: a pointer to memory to store the result
*
* Output: *res contains the result of a * a
*
* Side Effects: None
*
* Overview: Call BigIntSquare() to square two really big numbers.
*
* Note: Supports at least 2048 result bits.
* Functionally equivalent to BigIntMultiply, except
* an optimization is made for the case of square that
* allows us to skip ~1/2 the iterations.
* res CANNOT be A.
********************************************************************/
#if defined(BI_USE_SQUARE)
void BigIntSquare(BIGINT *a, BIGINT *res)
{
BigIntZero(res);
_iA = a->ptrLSB;
_xA = BigIntMSB(a);
_iR = res->ptrLSB;
sqrBI();
// Invalidate the MSB ptr
res->bMSBValid = 0;
}
#endif
/*********************************************************************
* Function: void BigIntAdd(BIGINT *a, const BIGINT *b)
*
* PreCondition: a->ptrMSBMax - a->ptrLSB must be >= b->ptrMSB - b->ptrLSB
*
* Input: *a: a pointer to the first number
* *b: a pointer to the second number
*
* Output: a = a + b
*
* Side Effects: None
*
* Overview: Call BigIntAdd() to add two really big numbers
*
* Note: Supports at least 2048 result bits.
********************************************************************/
#if defined(BI_USE_ADD)
void BigIntAdd(BIGINT *a, BIGINT *b)
{
_iA = a->ptrLSB;
_xA = a->ptrMSBMax;
_iB = b->ptrLSB;
_xB = BigIntMSB(b);
addBI();
// Invalidate MSB pointer
a->bMSBValid = 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_ADD_ROM)
// Note: This function is not required by either RSA operation
void BigIntAddROM(BIGINT *a, BIGINT_ROM *b)
{
_iA = a->ptrLSB;
_xA = a->ptrMSBMax;
_iBr = b->ptrLSB;
_xBr = b->ptrMSB;
addBIROM();
//invalidate MSB pointer
a->bMSBValid = 0;
}
#endif
/*********************************************************************
* Function: void BigIntSubtract(BIGINT *a, const BIGINT *b)
*
* PreCondition: a->ptrMSBMax - a->ptrLSB must be >= b->ptrMSB - b->ptrLSB
*
* Input: *a: a pointer to the first number
* *b: a pointer to the second number
*
* Output: a = a - b
*
* Side Effects: None
*
* Overview: Call BigIntSubtract() to subtract two really big numbers
*
* Note: Supports at least 2048 result bits.
********************************************************************/
#if defined(BI_USE_SUBTRACT)
void BigIntSubtract(BIGINT *a, BIGINT *b)
{
_iA = a->ptrLSB;
_xA = a->ptrMSBMax;
_iB = b->ptrLSB;
_xB = BigIntMSB(b);
subBI();
// Invalidate MSB pointer
a->bMSBValid = 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_SUBTRACT_ROM)
// Note: This function is not required by either RSA operation
void BigIntSubtractROM(BIGINT *a, BIGINT_ROM *b)
{
_iA = a->ptrLSB;
_xA = a->ptrMSBMax;
_iBr = b->ptrLSB;
_xBr = b->ptrMSB;
subBIROM();
//invalidate MSB pointer
a->bMSBValid = 0;
}
#endif
/*********************************************************************
* Function: void BigIntCopy(BIGINT *a, const BIGINT *b)
*
* PreCondition: None
*
* Input: *a: a pointer to a BIGINT to copy into
* *b: a pointer to the data
*
* Output: a = b
*
* Side Effects: None
*
* Overview: Call BigIntCopy() copy one BIGINT to another
*
* Note: Supports at least 2048 bits. Only data is copied, so
* if sizeof(b) > sizeof(a), only the least significant
* sizeof(a) bytes are copied.
********************************************************************/
#if defined(BI_USE_COPY)
void BigIntCopy(BIGINT *a, BIGINT *b)
{
_iA = a->ptrLSB;
_xA = a->ptrMSBMax;
_iB = b->ptrLSB;
_xB = b->ptrMSBMax;
copyBI();
// Invalidate MSB pointer
a->bMSBValid = 0;
}
#endif
#if defined(__18CXX) && defined(BI_USE_COPY_ROM)
void BigIntCopyROM(BIGINT *a, BIGINT_ROM *b)
{
BIGINT_DATA_TYPE *pa;
ROM BIGINT_DATA_TYPE *pb;
for(pa = a->ptrLSB, pb = b->ptrLSB; (pa <= a->ptrMSBMax) && (pb <= b->ptrMSB); pa++, pb++)
*pa = *pb;
// Zero fill remainder
while(pa <= a->ptrMSBMax)
{
*pa = 0;
pa++;
}
// Invalidate MSB pointer
a->bMSBValid = 0;
}
#endif //#if defined(__18CXX)
/*********************************************************************
* Function: void BigIntSwapEndianness(BIGINT *a)
*
* PreCondition: None
*
* Input: *a: a pointer to the BigInt
*
* Output: *a: same value, with endianness swapped
*
* Side Effects: None
*
* Overview: Converts a big-endian data array to little-endian,
* or a little-endian data array to big-endian.
*
* Note: None
********************************************************************/
void BigIntSwapEndianness(BIGINT *a)
{
BYTE temp, *front, *end;
// Set up the pointers
front = (BYTE*)a->ptrLSB;
end = (BYTE*)a->ptrMSBMax + (sizeof(BIGINT_DATA_TYPE) - 1);
// Swap all data elements
while(front < end)
{
temp = *front;
*front = *end;
*end = temp;
front++;
end--;
}
}
#endif // #if (defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_SSL_CLIENT)) && !defined(ENC100_INTERFACE_MODE)
|