📄 gmpwrap.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "mpint.h"
#include "gmpwrap.h"
#include "gmp.h"
#include "errorctx.h"
int GMPWrapCreateMpInt (
Pointer mpIntCtx,
VoltMpInt **newInt
)
{
int status;
#if VOLT_ALIGNMENT != 1
unsigned int pad;
#endif
unsigned int bufferSize, offset;
unsigned char *buffer = (unsigned char *)0;
VoltMpIntCtx *mpCtx = (VoltMpIntCtx *)mpIntCtx;
VoltLibCtx *libCtx = (VoltLibCtx *)(mpCtx->voltObject.libraryCtx);
VoltMpInt *mpInt;
VOLT_DECLARE_FNCT_LINE (fnctLine)
do
{
/* Allocate space for the VoltMpInt and mpz_t.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_MEMORY;
bufferSize = sizeof (VoltMpInt) + sizeof (mpz_t);
#if VOLT_ALIGNMENT != 1
/* If the alignment is 1, there's no need to pad. If not, compute
* the pad length.
*/
VOLT_COMPUTE_ALIGN_PAD (VOLT_ALIGNMENT, sizeof (VoltMpInt), pad)
bufferSize += pad;
#endif
buffer = (unsigned char *)Z2Malloc (bufferSize, VOLT_MEMORY_SENSITIVE);
if (buffer == (unsigned char *)0)
break;
Z2Memset (buffer, 0, bufferSize);
/* Position the pointers.
*/
mpInt = (VoltMpInt *)buffer;
offset = sizeof (VoltMpInt);
#if VOLT_ALIGNMENT != 1
offset += pad;
#endif
mpInt->mpInt = (Pointer)(buffer + offset);
mpInt->mpCtx = (VtMpIntCtx)mpCtx;
mpz_init ((mpz_ptr)(mpInt->mpInt));
*newInt = (VoltMpInt *)mpInt;
status = 0;
} while (0);
/* If successful, just return.
*/
if (status == 0)
return (0);
/* If error, free memory.
*/
if (buffer != (unsigned char *)0)
Z2Free (buffer);
VOLT_LOG_ERROR (
libCtx, status, VT_ERROR_TYPE_PRIMARY, fnctLine,
"GMPWrapCreateMpInt", (char *)0)
return (status);
}
int GMPWrapDestroyMpInt (
VoltMpInt **theInt
)
{
VoltMpIntCtx *mpCtx;
VoltLibCtx *libCtx;
/* Call the clear function for the mpz, then free up the MpInt's
* memory.
*/
if (theInt == (VoltMpInt **)0)
return (0);
if (*theInt == (VoltMpInt *)0)
return (0);
mpz_clear ((mpz_ptr)((*theInt)->mpInt));
mpCtx = (VoltMpIntCtx *)((*theInt)->mpCtx);
libCtx = (VoltLibCtx *)(mpCtx->voltObject.libraryCtx);
Z2Free (*theInt);
*theInt = (VoltMpInt *)0;
return (0);
}
int GMPWrapOctetStringToMpInt (
unsigned int sign,
unsigned char *sourceOctetString,
unsigned int sourceOctetStringLen,
VoltMpInt *destInt
)
{
int status;
unsigned int index, bitSize;
mpz_ptr mpzTarget;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* If NULL, we can't log an error, no libCtx.
*/
if (destInt == (VoltMpInt *)0)
return (VT_ERROR_NULL_ARG);
do
{
/* Check the arguments.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_NULL_ARG;
if (sourceOctetString == (unsigned char *)0)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_INVALID_INPUT_LENGTH;
if (sourceOctetStringLen == 0)
break;
/* GMP can set an MpInt only with unsigned ints or strings. We'll
* use the unsigned int version. Set the initial value with an
* unsigned int, then add in successive values.
* The input Int may not have enough space allocated, so to avoid
* repeated realloc's, set the value to 1, shift left by the required
* amount, set back to 0 and start adding.
*/
bitSize = sourceOctetStringLen << 3;
mpzTarget = (mpz_ptr)(destInt->mpInt);
mpz_set_ui (mpzTarget, 1);
mpz_mul_2exp (mpzTarget, mpzTarget, bitSize);
mpz_set_ui (mpzTarget, 0);
/* For each byte in the octetString (except the low order byte),
* add to the intermediate value, then multiply by 256 (a "shift
* left" by 8). Don't do the last in this loop, because we just
* want to add that one in, no shift.
*/
for (index = 0; index < (sourceOctetStringLen - 1); ++index)
{
mpz_add_ui (
mpzTarget, mpzTarget, (unsigned int)(sourceOctetString[index]));
mpz_mul_2exp (mpzTarget, mpzTarget, 8);
}
mpz_add_ui (
mpzTarget, mpzTarget, (unsigned int)(sourceOctetString[index]));
/* We just added the number as a positive value. If sign is not
* positive, negate.
*/
if (sign != 0)
mpz_neg (mpzTarget, mpzTarget);
status = 0;
} while (0);
VOLT_LOG_ERROR_COMPARE (
status, destInt->mpCtx->voltObject.libraryCtx, status,
VT_ERROR_TYPE_PRIMARY, fnctLine, "GMPWrapOctetStringToMpInt", (char *)0)
return (status);
}
int GMPWrapIntToMpInt (
int signCheck,
int sourceValue,
VoltMpInt *destInt
)
{
/* Check the arguments.
* Can't log an error if NULL, no libCtx.
*/
if (destInt == (VoltMpInt *)0)
return (VT_ERROR_NULL_ARG);
if (signCheck == 0)
{
mpz_set_ui ((mpz_ptr)(destInt->mpInt), sourceValue);
return (0);
}
mpz_set_si ((mpz_ptr)(destInt->mpInt), sourceValue);
return (0);
}
int GMPWrapMpIntToInt (
VoltMpInt *sourceInt,
int signCheck,
int *destValue
)
{
int status;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* If NULL, we can't log an error, no libCtx.
*/
if (sourceInt == (VoltMpInt *)0)
return (VT_ERROR_NULL_ARG);
do
{
/* Check the arguments.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_NULL_ARG;
if (destValue == (int *)0)
break;
*destValue = 0;
status = VT_ERROR_MP_INT_RANGE;
/* If signCheck != 0, then return a signed integer.
*/
if (signCheck != 0)
{
/* Check to see if the value will fit into a signed int.
*/
VOLT_SET_FNCT_LINE (fnctLine)
if (mpz_fits_sint_p ((mpz_ptr)(sourceInt->mpInt)) == 0)
break;
*destValue = mpz_get_si ((mpz_ptr)(sourceInt->mpInt));
status = 0;
break;
}
/* The caller wants to get the value as an unsigned int. Check to
* see if the value will fit into an unsigned int.
*/
VOLT_SET_FNCT_LINE (fnctLine)
if (mpz_fits_uint_p ((mpz_ptr)(sourceInt->mpInt)) == 0)
break;
*destValue = (int)mpz_get_ui ((mpz_ptr)(sourceInt->mpInt));
status = 0;
} while (0);
VOLT_LOG_ERROR_COMPARE (
status, sourceInt->mpCtx->voltObject.libraryCtx, status,
VT_ERROR_TYPE_PRIMARY, fnctLine, "GMPWrapMpIntToInt", (char *)0)
return (status);
}
int GMPWrapMpIntToMpInt (
VoltMpInt *sourceInt,
VoltMpInt *destInt
)
{
/* Check the arguments.
* If NULL, can't log, no libCtx.
* We could check for one NULL, the other not, but this is the kind
* of error an app expects not to log.
*/
if ( (sourceInt == (VoltMpInt *)0) || (destInt == (VoltMpInt *)0) )
return (VT_ERROR_NULL_ARG);
mpz_set ((mpz_ptr)(destInt->mpInt), (mpz_ptr)(sourceInt->mpInt));
return (0);
}
int GMPWrapMpIntToOctetString (
VoltMpInt *sourceInt,
unsigned int *sign,
unsigned char *destBuf,
unsigned int bufferSize,
unsigned int *destLen
)
{
int status, getSign;
unsigned int octLen, wordCount, index, indexO, indexW, increment;
mp_limb_t currWord;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* If NULL, we can't log an error, no libCtx.
*/
if (sourceInt == (VoltMpInt *)0)
return (VT_ERROR_NULL_ARG);
do
{
/* Check the arguments.
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_NULL_ARG;
if ( (sign == (unsigned int *)0) || (destLen == (unsigned int *)0) )
break;
if (destBuf == (unsigned char *)0)
bufferSize = 0;
/* Get the sign, use octLen as a temp.
*/
getSign = (unsigned int)mpz_sgn ((mpz_ptr)(sourceInt->mpInt));
*sign = 1;
if (getSign >= 0)
*sign = 0;
/* How big does the buffer need to be?
*/
octLen = (unsigned int)mpz_sizeinbase ((mpz_ptr)(sourceInt->mpInt), 2);
octLen = (octLen + 7) / 8;
/* Is the buffer big enough?
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = VT_ERROR_BUFFER_TOO_SMALL;
*destLen = octLen;
if (bufferSize < octLen)
break;
/* Get each word from the mpz and shift and mask to get individual
* octets.
*/
wordCount = (unsigned int)mpz_size ((mpz_ptr)(sourceInt->mpInt));
increment = sizeof (mp_limb_t);
/* Start with the low order bytes/words.
*/
indexO = octLen - 1;
indexW = 1;
/* For all but the most significant word, grab all the bytes out of
* each word.
*/
while (indexW < wordCount)
{
currWord = mpz_getlimbn ((mpz_ptr)(sourceInt->mpInt), indexW - 1);
indexW++;
for (index = 0; index < increment; ++index)
{
destBuf[indexO] = (unsigned char)(currWord & 0xff);
currWord >>= 8;
indexO--;
}
}
/* The last word may not be an entire word.
*/
index = indexO + 1;
currWord = mpz_getlimbn ((mpz_ptr)(sourceInt->mpInt), indexW - 1);
for (; index > 0; index--)
{
destBuf[indexO] = (unsigned char)(currWord & 0xff);
currWord >>= 8;
indexO--;
}
status = 0;
} while (0);
VOLT_LOG_ERROR_COMPARE (
status, sourceInt->mpCtx->voltObject.libraryCtx, status,
VT_ERROR_TYPE_PRIMARY, fnctLine, "GMPWrapMpIntToOctetString", (char *)0)
return (status);
}
int GMPWrapCompare (
VoltMpInt *leftInt,
VoltMpInt *rightInt,
int *result
)
{
int gmpResult;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* Check the arguments.
* If NULL, can't log, no libCtx.
* We could check for one NULL, the other not, but this is the kind
* of error an app expects not to log.
*/
if ( (leftInt == (VoltMpInt *)0) ||
(rightInt == (VoltMpInt *)0) )
return (VT_ERROR_NULL_ARG);
VOLT_SET_FNCT_LINE (fnctLine)
if (result != (int *)0)
{
gmpResult = mpz_cmp (
(mpz_ptr)(leftInt->mpInt), (mpz_ptr)(rightInt->mpInt));
*result = 0;
if (gmpResult < 0)
*result = -1;
else if (gmpResult > 0)
*result = 1;
return (0);
}
VOLT_LOG_ERROR (
leftInt->mpCtx->voltObject.libraryCtx, VT_ERROR_NULL_ARG,
VT_ERROR_TYPE_PRIMARY, fnctLine, "GMPWrapCompare", (char *)0)
return (VT_ERROR_NULL_ARG);
}
int GMPWrapEvenOddZeroPositiveNegative (
VoltMpInt *theInt,
int *result
)
{
int retVal, theSign;
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* Check the arguments.
* If NULL, can't log, no libCtx.
*/
if (theInt == (VoltMpInt *)0)
return (VT_ERROR_NULL_ARG);
VOLT_SET_FNCT_LINE (fnctLine)
if (result != (int *)0)
{
/* mpz_sgn returns 0 if 0, 1 if positive, -1 if negative.
*/
*result = 0;
theSign = mpz_sgn ((mpz_ptr)(theInt->mpInt));
if (theSign == 0)
return (0);
/* mpz_tstbit returns 0 or 1, depending on what the bit at the given
* bit position is.
*/
retVal = mpz_tstbit ((mpz_ptr)(theInt->mpInt), 0);
if (retVal == 0)
retVal = 2;
if (theSign < 0)
retVal = -retVal;
*result = retVal;
return (0);
}
VOLT_LOG_ERROR (
theInt->mpCtx->voltObject.libraryCtx, VT_ERROR_NULL_ARG,
VT_ERROR_TYPE_PRIMARY, fnctLine, "GMPWrapEvenOddZeroPositiveNegative",
(char *)0)
return (VT_ERROR_NULL_ARG);
}
int GMPWrapGetBitLength (
VoltMpInt *theInt,
unsigned int *bitLen
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -