📄 pgpbignum.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpBigNum.c,v 1.8 2002/08/06 20:10:57 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include "pgpSDKPriv.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpContext.h"
#include "pgpBigNum.h"
#include "pgpMemoryMgr.h"
#include "pgpPFLPriv.h"
#include "bn.h"
#define IsBNError( i ) ( (i) != 0 )
#define IsntBNError( i ) ( (i) == 0 )
struct PGPBigNum
{
BigNum bn;
};
static PGPBoolean
pgpBigNumIsValid( PGPBigNumRef bn )
{
return( IsntNull( bn ) &&
IsntPGPError( PGPValidateMemoryMgr( ( bn->bn.mgr ) ) ) );
}
#define pgpValidateBigNum( bn ) PGPValidateParam( pgpBigNumIsValid( bn ) )
static PGPError
pgpNewBigNumInternal(
PGPMemoryMgrRef memoryMgr,
PGPBoolean secure,
PGPBigNumRef * newBN )
{
PGPError err = kPGPError_NoErr;
PGPBigNumRef ref;
ref = (PGPBigNumRef) PGPNewData( memoryMgr, sizeof( **newBN ),
kPGPMemoryMgrFlags_Clear);
if ( IsntNull( ref ) )
{
bnBegin( &ref->bn, memoryMgr, secure );
*newBN = ref;
}
else
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/* Creates a new bignum */
PGPError
PGPNewBigNum(
PGPContextRef context,
PGPBoolean secure,
PGPBigNumRef * newBN )
{
PGPError err = kPGPError_NoErr;
PGPMemoryMgrRef mgr = PGPPeekContextMemoryMgr( context );
PGPValidatePtr( newBN );
*newBN = kPGPInvalidBigNumRef;
pgpEnterPGPErrorFunction();
err = PGPValidateMemoryMgr( mgr );
if( IsntPGPError( err ) )
{
err = pgpNewBigNumInternal( mgr, secure, newBN );
}
return( err );
}
/* destoys the bignum and all memory it uses */
PGPError
PGPFreeBigNum( PGPBigNumRef bn )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( bn );
pgpEnterPGPErrorFunction();
bnEnd( &bn->bn );
err = PGPFreeData( bn );
return( err );
}
/* Create a new big num with same value as src */
PGPError
PGPCopyBigNum(
PGPBigNumRef src,
PGPBigNumRef * dest )
{
PGPError err = kPGPError_NoErr;
PGPBigNumRef temp = NULL;
PGPValidatePtr( dest );
*dest = NULL;
pgpValidateBigNum( src );
pgpEnterPGPErrorFunction();
err = pgpNewBigNumInternal( src->bn.mgr, src->bn.isSecure, &temp );
if ( IsntPGPError( err ) )
{
err = PGPAssignBigNum( src, temp );
if ( IsPGPError( err ) )
{
PGPFreeBigNum( temp );
temp = NULL;
}
}
*dest = temp;
return( err );
}
/* Make existing bignum dest have same value as source */
PGPError
PGPAssignBigNum(
PGPBigNumRef src,
PGPBigNumRef dest )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( src );
pgpValidateBigNum( dest );
pgpEnterPGPErrorFunction();
if ( IsBNError( bnCopy( &dest->bn, &src->bn ) ) )
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/* Swap two BigNums. Very fast. */
PGPError
PGPSwapBigNum( PGPBigNumRef a, PGPBigNumRef b)
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( a );
pgpValidateBigNum( b );
pgpEnterPGPErrorFunction();
bnSwap( &a->bn, &b->bn );
return( err );
}
/*
* Move bytes between the given buffer and the given BigNum encoded in
* base 256. I.e. after either of these, the buffer will be equal to
* (bn / 256^lsbyte) % 256^len. The difference is which is altered to
* match the other!
*/
PGPError
PGPBigNumExtractBigEndianBytes(
PGPBigNumRef bn,
PGPByte * dest,
PGPUInt32 lsbyte,
PGPUInt32 len )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( bn );
pgpEnterPGPErrorFunction();
bnExtractBigBytes( &bn->bn, dest, lsbyte, len );
return( err );
}
PGPError
PGPBigNumInsertBigEndianBytes(
PGPBigNumRef bn,
PGPByte const * src,
PGPUInt32 lsbyte,
PGPUInt32 len )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( bn );
pgpEnterPGPErrorFunction();
if ( IsBNError( bnInsertBigBytes( &bn->bn, src, lsbyte, len ) ) )
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/* The same, but the buffer is little-endian. */
PGPError
PGPBigNumExtractLittleEndianBytes(
PGPBigNumRef bn,
PGPByte * dest,
PGPUInt32 lsbyte,
PGPUInt32 len )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( bn );
pgpEnterPGPErrorFunction();
bnExtractLittleBytes( &bn->bn, dest, lsbyte, len );
return( err );
}
PGPError
PGPBigNumInsertLittleEndianBytes(
PGPBigNumRef bn,
PGPByte const * src,
PGPUInt32 lsbyte,
PGPUInt32 len )
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( bn );
pgpEnterPGPErrorFunction();
if ( IsBNError( bnInsertLittleBytes( &bn->bn, src, lsbyte, len ) ) )
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/* Return the least-significant bits (at least 16) of the BigNum */
PGPUInt16
PGPBigNumGetLSWord( PGPBigNumRef bn )
{
PGPUInt16 lsWord = 0;
pgpEnterZeroFunction();
if ( pgpBigNumIsValid( bn ) )
{
lsWord = bnLSWord( &bn->bn );
}
return( lsWord );
}
/*
* Return the number of significant bits in the BigNum.
* 0 or 1+floor(log2(src))
*/
PGPUInt32
PGPBigNumGetSignificantBits( PGPBigNumRef bn )
{
PGPUInt32 numBits;
pgpEnterZeroFunction();
pgpValidateBigNum( bn );
numBits = bnBits( &bn->bn );
return( numBits );
}
/*
* Adds two bignums into dest. Faster if dest is same as lhs or rhs.
*/
PGPError
PGPBigNumAdd(
PGPBigNumRef lhs,
PGPBigNumRef rhs,
PGPBigNumRef dest )
{
PGPError err = kPGPError_NoErr;
int bnError;
pgpValidateBigNum( lhs );
pgpValidateBigNum( rhs );
pgpValidateBigNum( dest );
pgpEnterPGPErrorFunction();
if ( lhs == dest )
{
bnError = bnAdd( &dest->bn, &rhs->bn );
}
else if ( rhs == dest )
{
bnError = bnAdd( &dest->bn, &lhs->bn );
}
else
{
bnError = bnCopy( &dest->bn, &lhs->bn );
if ( bnError == 0 )
{
bnError = bnAdd( &dest->bn, &rhs->bn );
}
}
if ( IsBNError( bnError ) )
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/*
* lhs-rhs. dest and src may be the same, but bnSetQ(dest, 0) is faster.
* if dest < src, returns error and dest is undefined.
*/
PGPError
PGPBigNumSubtract(
PGPBigNumRef lhs,
PGPBigNumRef rhs,
PGPBigNumRef dest,
PGPBoolean * underflowPtr )
{
PGPError err = kPGPError_NoErr;
int bnError;
PGPBoolean underflow = FALSE;
if ( IsntNull( underflowPtr ) )
*underflowPtr = FALSE;
pgpValidateBigNum( lhs );
pgpValidateBigNum( rhs );
pgpValidateBigNum( dest );
pgpEnterPGPErrorFunction();
if ( lhs == dest )
{
bnError = bnSub( &dest->bn, &rhs->bn );
underflow = (bnError == 1);
bnError = 0;
}
else if ( rhs == dest )
{
BigNum temp;
PGPBoolean secure;
secure = lhs->bn.isSecure || rhs->bn.isSecure ||
dest->bn.isSecure;
bnBegin( &temp, dest->bn.mgr, secure );
bnError = bnCopy( &temp, &lhs->bn );
if ( bnError == 0 )
{
bnError = bnSub( &temp, &rhs->bn );
underflow = (bnError == 1);
bnError = 0;
bnError = bnCopy( &dest->bn, &temp );
}
bnEnd( &temp );
}
else
{
bnError = bnCopy( &dest->bn, &lhs->bn );
if ( bnError == 0 )
{
bnError = bnSub( &dest->bn, &rhs->bn );
underflow = (bnError == 1);
bnError = 0;
}
}
if ( IsntNull( underflowPtr ) )
*underflowPtr = underflow;
if ( bnError == -1 )
err = kPGPError_OutOfMemory;
return( err );
}
/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmpQ(a, b) <=> 0 */
PGPInt32
PGPBigNumCompareQ(
PGPBigNumRef bn,
PGPUInt16 sm )
{
PGPUInt32 result = 0;
pgpEnterZeroFunction();
if ( pgpBigNumIsValid( bn ) )
{
result = bnCmpQ( &bn->bn, sm );
}
return( result );
}
/* dest = src, where 0 <= src < 2^16. */
PGPError
PGPBigNumSetQ(
PGPBigNumRef dest,
PGPUInt16 sm)
{
PGPError err = kPGPError_NoErr;
pgpValidateBigNum( dest );
pgpEnterPGPErrorFunction();
if ( IsBNError( bnSetQ( &dest->bn, sm ) ) )
{
err = kPGPError_OutOfMemory;
}
return( err );
}
/* dest = bn + sm, where 0 <= sm < 2^16 */
PGPError
PGPBigNumAddQ(
PGPBigNumRef bn,
PGPUInt16 sm,
PGPBigNumRef dest)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -