Files
slimbootloader/BootloaderCommonPkg/Library/IppCryptoLib/auth/pcpbnca.c
T
Mike Crowe 990e3e81e6 Use LF line endings in the repository
Convert the line endings stored for all text files in the repository to
LF. The majority previously used DOS-style CRLF line endings. Add a
.gitattributes file to enforce this and treat certain extensions as
never being text files.

Update PatchCheck.py to insist on LF line endings rather than CRLF.
However, its other checks fail on this commit due to lots of
pre-existing complaints that it only notices because the line endings
have changed.

Silicon/QemuSocPkg/FspBin/Patches/0001-Build-QEMU-FSP-2.0-binaries.patch
needs to be treated as binary since it contains a mixture of line
endings.

This change has implications depending on the client platform you are
using the repository from:

* Windows

The usual configuration for Git on Windows means that text files will
be checked out to the work tree with DOS-style CRLF line endings. If
that's not the case then you can configure Git to do so for the entire
machine with:

 git config --global core.autocrlf true

or for just the repository with:

 git config core.autocrlf true

Line endings will be normalised to LF when they are committed to the
repository. If you commit a text file with only LF line endings then it
will be converted to CRLF line endings in your work tree.

* Linux, MacOS and other Unices

The usual configuration for Git on such platforms is to check files out
of the repository with LF line endings. This is probably the right thing
for you. In the unlikely even that you are using Git on Unix but editing
or compiling on Windows for some reason then you may need to tweak your
configuration to force the use of CRLF line endings as described above.

* General

For more information see
https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings .

Fixes: https://github.com/slimbootloader/slimbootloader/issues/1400
Signed-off-by: Mike Crowe <mac@mcrowe.com>
2021-11-10 12:46:42 -08:00

1320 lines
39 KiB
C

/*******************************************************************************
* Copyright 2002-2020 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
/*
// Intel(R) Integrated Performance Primitives
// Cryptographic Primitives (ippcp)
//
// Contents:
// ippsBigNumGetSize()
// ippsBigNumInit()
//
// ippsSet_BN()
// ippsGet_BN()
// ippsGetSize_BN()
// ippsExtGet_BN()
// ippsRef_BN()
//
// ippsCmpZero_BN()
// ippsCmp_BN()
//
// ippsAdd_BN()
// ippsSub_BN()
// ippsMul_BN()
// ippsMAC_BN_I()
// ippsDiv_BN()
// ippsMod_BN()
// ippsGcd_BN()
// ippsModInv_BN()
//
// cpPackBigNumCtx(), cpUnpackBigNumCtx()
//
//
*/
#include "owndefs.h"
#include "owncp.h"
#include "pcpbn.h"
#include "pcptool.h"
/* BN(1) and reference */
static IppsBigNumStateChunk cpChunk_BN1 = {
{
idCtxBigNum,
ippBigNumPOS,
1,1,
&cpChunk_BN1.value,&cpChunk_BN1.temporary
},
1,0
};
#define cpBN_OneRef OWNAPI(cpBN_OneRef)
IppsBigNumState* cpBN_OneRef(void)
{ return &cpChunk_BN1.bn; };
/* BN(2) and reference */
static IppsBigNumStateChunk cpChunk_BN2 = {
{
idCtxBigNum,
ippBigNumPOS,
1,1,
&cpChunk_BN2.value,&cpChunk_BN2.temporary
},
2,0
};
#define cpBN_TwoRef OWNAPI(cpBN_TwoRef)
IppsBigNumState* cpBN_TwoRef(void)
{ return &cpChunk_BN2.bn; };
/* BN(3) and reference */
static IppsBigNumStateChunk cpChunk_BN3 = {
{
idCtxBigNum,
ippBigNumPOS,
1,1,
&cpChunk_BN3.value,&cpChunk_BN3.temporary
},
3,0
};
#define cpBN_ThreeRef OWNAPI(cpBN_ThreeRef)
IppsBigNumState* cpBN_ThreeRef(void)
{ return &cpChunk_BN3.bn; };
/*F*
// Name: ippsBigNumGetSize
//
// Purpose: Returns size of BigNum ctx (bytes).
//
// Returns: Reason:
// ippStsNullPtrErr pCtxSize == NULL
// ippStsLengthErr len32 < 1
// len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
// ippStsNoErr no errors
//
// Parameters:
// pCtxSize pointer BigNum ctx size
//
*F*/
IPPFUN(IppStatus, ippsBigNumGetSize, (cpSize len32, cpSize *pCtxSize))
{
IPP_BAD_PTR1_RET(pCtxSize);
IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
{
/* convert length to the number of BNU_CHUNK_T */
cpSize len = INTERNAL_BNU_LENGTH(len32);
/* reserve one BNU_CHUNK_T more for cpDiv_BNU,
mul, mont exp operations */
len++;
*pCtxSize = sizeof(IppsBigNumState)
+ len*sizeof(BNU_CHUNK_T)
+ len*sizeof(BNU_CHUNK_T)
+ BN_ALIGNMENT-1;
return ippStsNoErr;
}
}
/*F*
// Name: ippsBigNumInit
//
// Purpose: Init BigNum spec for future usage.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// ippStsLengthErr len32<1
// len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
// ippStsNoErr no errors
//
// Parameters:
// len32 max BN length (32-bits segments)
// pBN BigNum ctx
//
*F*/
IPPFUN(IppStatus, ippsBigNumInit, (cpSize len32, IppsBigNumState* pBN))
{
IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
IPP_BAD_PTR1_RET(pBN);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
{
Ipp8u* ptr = (Ipp8u*)pBN;
/* convert length to the number of BNU_CHUNK_T */
cpSize len = INTERNAL_BNU_LENGTH(len32);
BN_ID(pBN) = idCtxUnknown;
BN_SIGN(pBN) = ippBigNumPOS;
BN_SIZE(pBN) = 1; /* initial valie is zero */
BN_ROOM(pBN) = len; /* close to what has been passed by user */
/* reserve one BNU_CHUNK_T more for cpDiv_BNU,
mul, mont exp operations */
len++;
/* allocate buffers */
BN_NUMBER(pBN) = (BNU_CHUNK_T*)(ptr += sizeof(IppsBigNumState));
BN_BUFFER(pBN) = (BNU_CHUNK_T*)(ptr += len*sizeof(BNU_CHUNK_T)); /* use expanded length here */
/* set BN value and buffer to zero */
ZEXPAND_BNU(BN_NUMBER(pBN), 0, len);
ZEXPAND_BNU(BN_BUFFER(pBN), 0, len);
BN_ID(pBN) = idCtxBigNum;
return ippStsNoErr;
}
}
/*
// Serialize / Deserialize bigNum context
*/
void cpPackBigNumCtx(const IppsBigNumState* pBN, Ipp8u* pBuffer)
{
IppsBigNumState* pAlignedBuffer = (IppsBigNumState*)(IPP_ALIGNED_PTR((pBuffer), BN_ALIGNMENT));
CopyBlock(pBN, pAlignedBuffer, sizeof(IppsBigNumState));
BN_NUMBER(pAlignedBuffer) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(BN_NUMBER(pBN))-IPP_UINT_PTR(pBN));
BN_BUFFER(pAlignedBuffer) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(BN_BUFFER(pBN))-IPP_UINT_PTR(pBN));
CopyBlock(BN_NUMBER(pBN), (Ipp8u*)pAlignedBuffer+IPP_UINT_PTR(BN_NUMBER(pAlignedBuffer)), BN_ROOM(pBN)*sizeof(BNU_CHUNK_T));
CopyBlock(BN_BUFFER(pBN), (Ipp8u*)pAlignedBuffer+IPP_UINT_PTR(BN_BUFFER(pAlignedBuffer)), BN_ROOM(pBN)*sizeof(BNU_CHUNK_T));
}
void cpUnpackBigNumCtx(const Ipp8u* pBuffer, IppsBigNumState* pBN)
{
IppsBigNumState* pAlignedBuffer = (IppsBigNumState*)(IPP_ALIGNED_PTR((pBuffer), BN_ALIGNMENT));
CopyBlock(pBuffer, pBN, sizeof(IppsBigNumState));
BN_NUMBER(pBN) = (BNU_CHUNK_T*)((Ipp8u*)pBN + IPP_UINT_PTR(BN_NUMBER(pAlignedBuffer)));
BN_BUFFER(pBN) = (BNU_CHUNK_T*)((Ipp8u*)pBN + IPP_UINT_PTR(BN_BUFFER(pAlignedBuffer)));
CopyBlock((Ipp8u*)pAlignedBuffer+IPP_UINT_PTR(BN_NUMBER(pAlignedBuffer)), BN_NUMBER(pBN), BN_ROOM(pBN)*sizeof(BNU_CHUNK_T));
CopyBlock((Ipp8u*)pAlignedBuffer+IPP_UINT_PTR(BN_BUFFER(pAlignedBuffer)), BN_BUFFER(pBN), BN_ROOM(pBN)*sizeof(BNU_CHUNK_T));
}
/*F*
// Name: ippsCmpZero_BN
//
// Purpose: Test BigNum value.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// pResult == NULL
// ippStsContextMatchErr BN_VALID_ID()
// ippStsNoErr no errors
//
// Parameters:
// pBN BigNum ctx
// pResult result of comparison
//
*F*/
IPPFUN(IppStatus, ippsCmpZero_BN, (const IppsBigNumState* pBN, Ipp32u* pResult))
{
IPP_BAD_PTR2_RET(pBN, pResult);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
if(BN_SIZE(pBN)==1 && BN_NUMBER(pBN)[0]==0)
*pResult = IS_ZERO;
else if (BN_SIGN(pBN)==ippBigNumPOS)
*pResult = GREATER_THAN_ZERO;
else if (BN_SIGN(pBN)==ippBigNumNEG)
*pResult = LESS_THAN_ZERO;
return ippStsNoErr;
}
/*F*
// Name: ippsCmp_BN
//
// Purpose: Compare two BigNums.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pResult == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// ippStsNoErr no errors
//
// Parameters:
// pA BigNum ctx
// pB BigNum ctx
// pResult result of comparison
//
*F*/
IPPFUN(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u *pResult))
{
IPP_BAD_PTR3_RET(pA, pB, pResult);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
{
int res;
if(BN_SIGN(pA)==BN_SIGN(pB)) {
res = cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB));
if(ippBigNumNEG==BN_SIGN(pA))
res = -res;
}
else
res = (ippBigNumPOS==BN_SIGN(pA))? 1 :-1;
*pResult = (1==res)? IPP_IS_GT : (-1==res)? IPP_IS_LT : IPP_IS_EQ;
return ippStsNoErr;
}
}
/*F*
// Name: ippsGetSize_BN
//
// Purpose: Returns BigNum room.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// pSize == NULL
// ippStsContextMatchErr BN_VALID_ID(pBN)
// ippStsNoErr no errors
//
// Parameters:
// pBN BigNum ctx
// pSize max BigNum length (in Ipp32u chunks)
//
*F*/
IPPFUN(IppStatus, ippsGetSize_BN, (const IppsBigNumState* pBN, cpSize* pSize))
{
IPP_BAD_PTR2_RET(pBN, pSize);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
*pSize = BN_ROOM(pBN)*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u);
return ippStsNoErr;
}
/*F*
// Name: ippsSet_BN
//
// Purpose: Set BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// pData == NULL
// ippStsContextMatchErr BN_VALID_ID(pBN)
// ippStsLengthErr len32 < 1
// ippStsOutOfRangeErr len32 > BN_ROOM()
// ippStsNoErr no errors
//
// Parameters:
// sgn sign
// len32 data size (in Ipp32u chunks)
// pData source data pointer
// pBn BigNum ctx
//
*F*/
IPPFUN(IppStatus, ippsSet_BN, (IppsBigNumSGN sgn, cpSize len32, const Ipp32u* pData,
IppsBigNumState* pBN))
{
IPP_BAD_PTR2_RET(pData, pBN);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
IPP_BADARG_RET(len32<1, ippStsLengthErr);
/* compute real size */
FIX_BNU(pData, len32);
{
cpSize len = INTERNAL_BNU_LENGTH(len32);
IPP_BADARG_RET(len > BN_ROOM(pBN), ippStsOutOfRangeErr);
ZEXPAND_COPY_BNU((Ipp32u*)BN_NUMBER(pBN), BN_ROOM(pBN)*(int)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), pData, len32);
BN_SIZE(pBN) = len;
if(len32==1 && pData[0] == 0)
sgn = ippBigNumPOS; /* consider zero value as positive */
BN_SIGN(pBN) = sgn;
return ippStsNoErr;
}
}
/*F*
// Name: ippsGet_BN
//
// Purpose: Get BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// pData == NULL
// pSgn == NULL
// pLen32 ==NULL
// ippStsContextMatchErr !BN_VALID_ID(pBN)
// ippStsNoErr no errors
//
// Parameters:
// pSgn pointer to the sign
// pLen32 pointer to the data size (in Ipp32u chunks)
// pData pointer to the data buffer
// pBN BigNum ctx
//
*F*/
IPPFUN(IppStatus, ippsGet_BN, (IppsBigNumSGN* pSgn, cpSize* pLen32, Ipp32u* pData,
const IppsBigNumState* pBN))
{
IPP_BAD_PTR4_RET(pSgn, pLen32, pData, pBN);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
{
cpSize len32 = BN_SIZE(pBN)*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u);
Ipp32u* bnData = (Ipp32u*)BN_NUMBER(pBN);
FIX_BNU(bnData, len32);
COPY_BNU(pData, bnData, len32);
*pSgn = BN_SIGN(pBN);
*pLen32 = len32;
return ippStsNoErr;
}
}
/*F*
// Name: ippsRef_BN
//
// Purpose: Get BigNum info.
//
// Returns: Reason:
// ippStsNullPtrErr pBN == NULL
// ippStsContextMatchErr BN_VALID_ID(pBN)
// ippStsNoErr no errors
//
// Parameters:
// pSgn pointer to the sign
// pBitSize pointer to the data size (in bits)
// ppData pointer to the data buffer
// pBN BigNum ctx
//
*F*/
IPPFUN(IppStatus, ippsRef_BN, (IppsBigNumSGN* pSgn, cpSize* pBitSize, Ipp32u** const ppData,
const IppsBigNumState *pBN))
{
IPP_BAD_PTR1_RET(pBN);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
if(pSgn)
*pSgn = BN_SIGN(pBN);
if(pBitSize) {
cpSize bitLen = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN));
*pBitSize = bitLen? bitLen : 1;
}
if(ppData)
*ppData = (Ipp32u*)BN_NUMBER(pBN);
return ippStsNoErr;
}
IPPFUN(IppStatus, ippsExtGet_BN, (IppsBigNumSGN* pSgn, cpSize* pBitSize, Ipp32u* pData,
const IppsBigNumState* pBN))
{
IPP_BAD_PTR1_RET(pBN);
pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr);
{
cpSize bitSize = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN));
if(0==bitSize)
bitSize = 1;
if(pData)
COPY_BNU(pData, (Ipp32u*)BN_NUMBER(pBN), BITS2WORD32_SIZE(bitSize));
if(pSgn)
*pSgn = BN_SIGN(pBN);
if(pBitSize)
*pBitSize = bitSize;
return ippStsNoErr;
}
}
/*F*
// Name: ippsAdd_BN
//
// Purpose: Add BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pR can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pR resultant BigNum
//
*F*/
IPPFUN(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
{
IPP_BAD_PTR3_RET(pA, pB, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
{
cpSize nsA = BN_SIZE(pA);
cpSize nsB = BN_SIZE(pB);
cpSize nsR = BN_ROOM(pR);
IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr);
{
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
IppsBigNumSGN sgnA = BN_SIGN(pA);
IppsBigNumSGN sgnB = BN_SIGN(pB);
BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
BNU_CHUNK_T carry;
if(sgnA==sgnB) {
if(nsA < nsB) {
SWAP(nsA, nsB);
SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
}
carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB);
if(nsA>nsB)
carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
if(carry) {
if(nsR>nsA)
pDataR[nsA++] = carry;
else
IPP_ERROR_RET(ippStsOutOfRangeErr);
}
BN_SIGN(pR) = sgnA;
}
else {
int cmpRes = cpCmp_BNU(pDataA, nsA, pDataB, nsB);
if(0==cmpRes) {
pDataR[0] = 0;
BN_SIZE(pR) = 1;
BN_SIGN(pR) = ippBigNumPOS;
return ippStsNoErr;
}
if(0>cmpRes) {
SWAP(nsA, nsB);
SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
}
carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB);
if(nsA>nsB)
cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA);
}
FIX_BNU(pDataR, nsA);
BN_SIZE(pR) = nsA;
return ippStsNoErr;
}
}
}
/*F*
// Name: ippsSub_BN
//
// Purpose: Subtcrac BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pR can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pR resultant BigNum
//
*F*/
IPPFUN(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
{
IPP_BAD_PTR3_RET(pA, pB, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
{
cpSize nsA = BN_SIZE(pA);
cpSize nsB = BN_SIZE(pB);
cpSize nsR = BN_ROOM(pR);
IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr);
{
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
IppsBigNumSGN sgnA = BN_SIGN(pA);
IppsBigNumSGN sgnB = BN_SIGN(pB);
BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
BNU_CHUNK_T carry;
if(sgnA!=sgnB) {
if(nsA < nsB) {
SWAP(nsA, nsB);
SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
}
carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB);
if(nsA>nsB)
carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
if(carry) {
if(nsR > nsA)
pDataR[nsA++] = carry;
else
IPP_ERROR_RET(ippStsOutOfRangeErr);
}
BN_SIGN(pR) = sgnA;
}
else {
int cmpRes= cpCmp_BNU(pDataA, nsA, pDataB, nsB);
if(0==cmpRes) {
ZEXPAND_BNU(pDataR,0, nsR);
BN_SIZE(pR) = 1;
BN_SIGN(pR) = ippBigNumPOS;
return ippStsNoErr;
}
if(0>cmpRes) {
SWAP(nsA, nsB);
SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB);
}
carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB);
if(nsA>nsB)
cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry);
BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA);
}
FIX_BNU(pDataR, nsA);
BN_SIZE(pR) = nsA;
return ippStsNoErr;
}
}
}
/*F*
// Name: ippsMul_BN
//
// Purpose: Multiply BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pR can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pR resultant BigNum
//
*F*/
IPPFUN(IppStatus, ippsMul_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
{
IPP_BAD_PTR3_RET(pA, pB, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
{
BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
cpSize nsA = BN_SIZE(pA);
cpSize nsB = BN_SIZE(pB);
cpSize nsR = BN_ROOM(pR);
cpSize bitSizeA = BITSIZE_BNU(pDataA, nsA);
cpSize bitSizeB = BITSIZE_BNU(pDataB, nsB);
/* test if multiplicant/multiplier is zero */
if(!bitSizeA || !bitSizeB) {
BN_SIZE(pR) = 1;
BN_SIGN(pR) = IppsBigNumPOS;
pDataR[0] = 0;
return ippStsNoErr;
}
/* test if even low estimation of product A*B exceeded */
IPP_BADARG_RET(nsR*BNU_CHUNK_BITS < (bitSizeA+bitSizeB-1), ippStsOutOfRangeErr);
{
BNU_CHUNK_T* aData = pDataA;
BNU_CHUNK_T* bData = pDataB;
if(pA == pR) {
aData = BN_BUFFER(pR);
COPY_BNU(aData, pDataA, nsA);
}
if((pB == pR) && (pA != pB)) {
bData = BN_BUFFER(pR);
COPY_BNU(bData, pDataB, nsB);
}
/* clear result */
ZEXPAND_BNU(pDataR, 0, nsR+1);
if(pA==pB)
cpSqr_BNU_school(pDataR, aData, nsA);
else
cpMul_BNU_school(pDataR, aData, nsA, bData, nsB);
nsR = (bitSizeA + bitSizeB + BNU_CHUNK_BITS - 1) /BNU_CHUNK_BITS;
FIX_BNU(pDataR, nsR);
IPP_BADARG_RET(nsR>BN_ROOM(pR), ippStsOutOfRangeErr);
BN_SIZE(pR) = nsR;
BN_SIGN(pR) = (BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG);
return ippStsNoErr;
}
}
}
/*F*
// Name: ippsMAC_BN_I
//
// Purpose: Multiply and Accumulate BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pR can not fit result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pR resultant BigNum
//
*F*/
IPPFUN(IppStatus, ippsMAC_BN_I, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR))
{
IPP_BAD_PTR3_RET(pA, pB, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
{
BNU_CHUNK_T* pDataA = BN_NUMBER(pA);
BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
cpSize nsA = BN_SIZE(pA);
cpSize nsB = BN_SIZE(pB);
cpSize bitSizeA = BITSIZE_BNU(pDataA, nsA);
cpSize bitSizeB = BITSIZE_BNU(pDataB, nsB);
/* size of temporary pruduct */
cpSize nsP = BITS_BNU_CHUNK(bitSizeA+bitSizeB);
/* test if multiplicant/multiplier is zero */
//gres: mistaken condition: if(!nsP) return ippStsNoErr;
if(!bitSizeA || !bitSizeB) return ippStsNoErr;
/* test if product can't fit to the result */
IPP_BADARG_RET(BN_ROOM(pR)<nsP, ippStsOutOfRangeErr);
{
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
IppsBigNumSGN sgnR = BN_SIGN(pR);
cpSize nsR = BN_SIZE(pR);
cpSize room = BN_ROOM(pR);
/* temporary product */
BNU_CHUNK_T* pDataP = BN_BUFFER(pR);
IppsBigNumSGN sgnP = BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG;
/* clear the rest of R data buffer */
ZEXPAND_BNU(pDataR, nsR, room);
/* temporary product */
if(pA==pB)
cpSqr_BNU_school(pDataP, pDataA, nsA);
else
cpMul_BNU_school(pDataP, pDataA, nsA, pDataB, nsB);
/* clear the rest of rpoduct */
ZEXPAND_BNU(pDataP, nsP, room);
if(sgnR==sgnP) {
BNU_CHUNK_T carry = cpAdd_BNU(pDataR, pDataR, pDataP, room);
if(carry) {
BN_SIZE(pR) = room;
IPP_ERROR_RET(ippStsOutOfRangeErr);
}
}
else {
BNU_CHUNK_T* pTmp = pDataR;
int cmpRes = cpCmp_BNU(pDataR, room, pDataP, room);
if(0>cmpRes) {
SWAP_PTR(BNU_CHUNK_T, pTmp, pDataP);
}
cpSub_BNU(pDataR, pTmp, pDataP, room);
BN_SIGN(pR) = cmpRes>0? sgnR : INVERSE_SIGN(sgnR);
}
FIX_BNU(pDataR, room);
BN_SIZE(pR) = room;
return ippStsNoErr;
}
}
}
/*F*
// Name: ippsDiv_BN
//
// Purpose: Divide BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pQ == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pQ)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pQ and/or pR can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pQ quotient BigNum
// pR reminder BigNum
//
// A = Q*B + R, 0 <= val(R) < val(B), sgn(A)==sgn(R)
//
*F*/
IPPFUN(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR))
{
IPP_BAD_PTR4_RET(pA, pB, pQ, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
pQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pQ, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pQ), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
IPP_BADARG_RET(BN_SIZE(pB)== 1 && BN_NUMBER(pB)[0]==0, ippStsDivByZeroErr);
IPP_BADARG_RET(BN_ROOM(pR)<BN_SIZE(pB), ippStsOutOfRangeErr);
IPP_BADARG_RET((int)BN_ROOM(pQ)<(int)(BN_SIZE(pA)-BN_SIZE(pB)), ippStsOutOfRangeErr);
{
BNU_CHUNK_T* pDataA = BN_BUFFER(pA);
cpSize nsA = BN_SIZE(pA);
BNU_CHUNK_T* pDataB = BN_NUMBER(pB);
cpSize nsB = BN_SIZE(pB);
BNU_CHUNK_T* pDataQ = BN_NUMBER(pQ);
cpSize nsQ;
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
cpSize nsR;
COPY_BNU(pDataA, BN_NUMBER(pA), nsA);
nsR = cpDiv_BNU(pDataQ, &nsQ, pDataA, nsA, pDataB, nsB);
COPY_BNU(pDataR, pDataA, nsR);
BN_SIGN(pQ) = BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG;
//gres: leading zeros are removed by cpDiv_BNU: FIX_BNU(pDataQ, nsQ);
BN_SIZE(pQ) = nsQ;
if(nsQ==1 && pDataQ[0]==0) BN_SIGN(pQ) = ippBigNumPOS;
BN_SIGN(pR) = BN_SIGN(pA);
//gres: leading zeros are removed by cpDiv_BNU: FIX_BNU(pDataR, nsR);
BN_SIZE(pR) = nsR;
if(nsR==1 && pDataR[0]==0) BN_SIGN(pR) = ippBigNumPOS;
return ippStsNoErr;
}
}
/*F*
// Name: ippsMod_BN
//
// Purpose: reduction BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pM == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pM)
// BN_VALID_ID(pR)
// ippStsOutOfRangeErr pR can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pR reminder BigNum
//
// A = Q*M + R, 0 <= R < B
//
*F*/
IPPFUN(IppStatus, ippsMod_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR))
{
IPP_BAD_PTR3_RET(pA, pM, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pM = (IppsBigNumState*)( IPP_ALIGNED_PTR(pM, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
IPP_BADARG_RET(BN_NEGATIVE(pM), ippStsBadModulusErr);
IPP_BADARG_RET(BN_SIZE(pM)== 1 && BN_NUMBER(pM)[0]==0, ippStsBadModulusErr);
IPP_BADARG_RET(BN_ROOM(pR)<BN_SIZE(pM), ippStsOutOfRangeErr);
if(cpEqu_BNU_CHUNK(BN_NUMBER(pA), BN_SIZE(pA), 0)) {
BN_SIGN(pR) = ippBigNumPOS;
BN_SIZE(pR) = 1;
BN_NUMBER(pR)[0] = 0;
}
else {
BNU_CHUNK_T* pDataM = BN_NUMBER(pM);
cpSize nsM = BN_SIZE(pM);
BNU_CHUNK_T* pBuffA = BN_BUFFER(pA);
cpSize nsA = BN_SIZE(pA);
BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
cpSize nsR;
COPY_BNU(pBuffA, BN_NUMBER(pA), nsA);
nsR = cpMod_BNU(pBuffA, nsA, pDataM, nsM);
COPY_BNU(pDataR, pBuffA, nsR);
BN_SIZE(pR) = nsR;
BN_SIGN(pR) = ippBigNumPOS;
if(BN_NEGATIVE(pA) && !(nsR==1 && pDataR[0]==0)) {
ZEXPAND_BNU(pDataR, nsR, nsM);
cpSub_BNU(pDataR, pDataM, pDataR, nsM);
FIX_BNU(pDataR, nsM);
BN_SIZE(pR) = nsM;
}
}
return ippStsNoErr;
}
/*F*
// Name: ippsGcd_BN
//
// Purpose: compute GCD value.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pB == NULL
// pG == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pB)
// BN_VALID_ID(pG)
// ippStsBadArgErr A==B==0
// ippStsOutOfRangeErr pG can not hold result
// ippStsNoErr no errors
//
// Parameters:
// pA source BigNum
// pB source BigNum
// pG GCD value
//
*F*/
IPPFUN(IppStatus, ippsGcd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pG))
{
IPP_BAD_PTR3_RET(pA, pB, pG);
pA = (IppsBigNumState*)(IPP_ALIGNED_PTR(pA, BN_ALIGNMENT));
pB = (IppsBigNumState*)(IPP_ALIGNED_PTR(pB, BN_ALIGNMENT));
pG = (IppsBigNumState*)(IPP_ALIGNED_PTR(pG, BN_ALIGNMENT));
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
IPP_BADARG_RET(!BN_VALID_ID(pG), ippStsContextMatchErr);
IPP_BADARG_RET(BN_ROOM(pG) < IPP_MIN(BN_SIZE(pA), BN_SIZE(pB)), ippStsOutOfRangeErr);
{
IppsBigNumState* x = pA;
IppsBigNumState* y = pB;
IppsBigNumState* g = pG;
int aIsZero = BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0;
int bIsZero = BN_SIZE(pB)==1 && BN_NUMBER(pB)[0]==0;
if(aIsZero && bIsZero)
return ippStsBadArgErr;
if(aIsZero && !bIsZero) {
COPY_BNU(BN_NUMBER(g), BN_NUMBER(pB), BN_SIZE(pB));
BN_SIZE(g) = BN_SIZE(pB);
BN_SIGN(g) = ippBigNumPOS;
return ippStsNoErr;
}
if(bIsZero && !aIsZero) {
COPY_BNU(BN_NUMBER(g), BN_NUMBER(pA), BN_SIZE(pA));
BN_SIZE(g) = BN_SIZE(pA);
BN_SIGN(g) = ippBigNumPOS;
return ippStsNoErr;
}
/*
// Lehmer's algorithm requres that first number must be greater than second
// x is the first, y is the second
*/
{
int cmpRes = cpCmp_BNU(BN_NUMBER(x), BN_SIZE(x), BN_NUMBER(y), BN_SIZE(y));
if(0>cmpRes)
SWAP_PTR(IppsBigNumState, x, y);
if(0==cmpRes) {
COPY_BNU(BN_NUMBER(g), BN_NUMBER(x), BN_SIZE(x));
BN_SIGN(g) = ippBigNumPOS;
BN_SIZE(g) = BN_SIZE(x);
return ippStsNoErr;
}
if(BN_SIZE(x)==1) {
BNU_CHUNK_T gcd = cpGcd_BNU(BN_NUMBER(x)[0], BN_NUMBER(y)[0]);
BN_NUMBER(g)[0] = gcd;
BN_SIZE(g) = 1;
return ippStsNoErr;
}
}
{
Ipp32u* xBuffer = (Ipp32u*)BN_BUFFER(x);
Ipp32u* yBuffer = (Ipp32u*)BN_BUFFER(y);
Ipp32u* gBuffer = (Ipp32u*)BN_BUFFER(g);
Ipp32u* xData = (Ipp32u*)BN_NUMBER(x);
Ipp32u* yData = (Ipp32u*)BN_NUMBER(y);
Ipp32u* gData = (Ipp32u*)BN_NUMBER(g);
cpSize nsXmax = BN_ROOM(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
cpSize nsYmax = BN_ROOM(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
cpSize nsGmax = BN_ROOM(g)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
cpSize nsX = BN_SIZE(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
cpSize nsY = BN_SIZE(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u));
Ipp32u* T;
Ipp32u* u;
FIX_BNU(xData, nsX);
FIX_BNU(yData, nsY);
/* init buffers */
//gres: seems length parameters mistaken exchaged: ZEXPAND_COPY_BNU(xBuffer, nsX, xData, nsXmax);
//gres: seems length parameters mistaken exchaged: ZEXPAND_COPY_BNU(yBuffer, nsY, yData, nsYmax);
ZEXPAND_COPY_BNU(xBuffer, nsXmax, xData, nsX);
ZEXPAND_COPY_BNU(yBuffer, nsYmax, yData, nsY);
T = gBuffer;
u = gData;
ZEXPAND_BNU(T, 0, nsGmax);
ZEXPAND_BNU(u, 0, nsGmax);
while(nsX > (cpSize)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) {
/* xx and yy is the high-order digits of x and y (yy could be 0) */
Ipp64u xx = (Ipp64u)(xBuffer[nsX-1]);
Ipp64u yy = (nsY < nsX)? 0 : (Ipp64u)(yBuffer[nsY-1]);
Ipp64s AA = 1;
Ipp64s BB = 0;
Ipp64s CC = 0;
Ipp64s DD = 1;
Ipp64s t;
while((yy+CC)!=0 && (yy+DD)!=0) {
#ifdef _SLIMBOOT_OPT
Ipp64u q = DivU64x64Remainder ( xx + AA , yy + CC , 0);
Ipp64u q1 = DivU64x64Remainder ( xx + BB , yy + DD , 0);
#else
Ipp64u q = ( xx + AA ) / ( yy + CC );
Ipp64u q1 = ( xx + BB ) / ( yy + DD );
#endif
if(q!=q1)
break;
#ifdef _SLIMBOOT_OPT
t = AA - MultS64x64 ((Ipp64s)q , CC);
#else
t = AA - q*CC;
#endif
AA = CC;
CC = t;
#ifdef _SLIMBOOT_OPT
t = BB - MultS64x64 ((Ipp64s)q , DD);
#else
t = BB - q*DD;
#endif
BB = DD;
DD = t;
#ifdef _SLIMBOOT_OPT
t = xx - MultU64x64 (q , yy);
#else
t = xx - q*yy;
#endif
xx = yy;
yy = t;
}
if(BB == 0) {
/* T = x mod y */
cpSize nsT = cpMod_BNU32(xBuffer, nsX, yBuffer, nsY);
ZEXPAND_BNU(T, 0, nsGmax);
COPY_BNU(T, xBuffer, nsT);
/* a = b; b = T; */
ZEXPAND_BNU(xBuffer, 0, nsXmax);
COPY_BNU(xBuffer, yBuffer, nsY);
ZEXPAND_BNU(yBuffer, 0, nsYmax);
COPY_BNU(yBuffer, T, nsY);
}
else {
Ipp32u carry;
/*
// T = AA*x + BB*y;
// u = CC*x + DD*y;
// b = u; a = T;
*/
if((AA <= 0)&&(BB>=0)) {
Ipp32u a1 = (Ipp32u)(-AA);
carry = cpMulDgt_BNU32(T, yBuffer, nsY, (Ipp32u)BB);
carry = cpMulDgt_BNU32(u, xBuffer, nsY, a1);
/* T = BB*y - AA*x; */
carry = cpSub_BNU32(T, T, u, nsY);
}
else {
if((AA >= 0)&&(BB<=0)) {
Ipp32u b1 = (Ipp32u)(-BB);
carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA);
carry = cpMulDgt_BNU32(u, yBuffer, nsY, b1);
/* T = AA*x - BB*y; */
carry = cpSub_BNU32(T, T, u, nsY);
}
else {
/*AA*BB>=0 */
carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA);
carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)BB);
/* T = AA*x + BB*y; */
carry = cpAdd_BNU32(T, T, u, nsY);
}
}
/* Now T is reserved. We use only u for intermediate results. */
if((CC <= 0)&&(DD>=0)){
Ipp32u c1 = (Ipp32u)(-CC);
/* u = x*CC; x = u; */
carry = cpMulDgt_BNU32(u, xBuffer, nsY, c1);
COPY_BNU(xBuffer, u, nsY);
/* u = y*DD; */
carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD);
/* u = DD*y - CC*x; */
carry = cpSub_BNU32(u, u, xBuffer, nsY);
}
else {
if((CC >= 0)&&(DD<=0)){
Ipp32u d1 = (Ipp32u)(-DD);
/* u = y*DD; y = u */
carry = cpMulDgt_BNU32(u, yBuffer, nsY, d1);
COPY_BNU(yBuffer, u, nsY);
/* u = CC*x; */
carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC);
/* u = CC*x - DD*y; */
carry = cpSub_BNU32(u, u, yBuffer, nsY);
}
else {
/*CC*DD>=0 */
/* y = y*DD */
carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD);
COPY_BNU(yBuffer, u, nsY);
/* u = x*CC */
carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC);
/* u = x*CC + y*DD */
carry = cpAdd_BNU32(u, u, yBuffer, nsY);
}
}
/* y = u; x = T; */
COPY_BNU(yBuffer, u, nsY);
COPY_BNU(xBuffer, T, nsY);
}
FIX_BNU(xBuffer, nsX);
FIX_BNU(yBuffer, nsY);
if (nsY > nsX) {
SWAP_PTR(IppsBigNumState, x, y);
SWAP(nsX, nsY);
}
if (nsY==1 && yBuffer[nsY-1]==0) {
/* End evaluation */
ZEXPAND_BNU(gData, 0, nsGmax);
COPY_BNU(gData, xBuffer, nsX);
BN_SIZE(g) = INTERNAL_BNU_LENGTH(nsX);
BN_SIGN(g) = ippBigNumPOS;
return ippStsNoErr;
}
}
BN_NUMBER(g)[0] = cpGcd_BNU(((BNU_CHUNK_T*)xBuffer)[0], ((BNU_CHUNK_T*)yBuffer)[0]);
BN_SIZE(g) = 1;
BN_SIGN(g) = ippBigNumPOS;
return ippStsNoErr;
}
}
}
/*F*
// Name: ippsModInv_BN
//
// Purpose: Multiplicative Inversion BigNum.
//
// Returns: Reason:
// ippStsNullPtrErr pA == NULL
// pM == NULL
// pR == NULL
// ippStsContextMatchErr BN_VALID_ID(pA)
// BN_VALID_ID(pM)
// BN_VALID_ID(pR)
// ippStsBadArgErr A<=0
// ippStsBadModulusErr M<=0
// ippStsScaleRangeErr A>=M
// ippStsOutOfRangeErr pR can not hold result
// ippStsNoErr no errors
// ippStsBadModulusErr inversion not found
//
// Parameters:
// pA source (value) BigNum
// pM source (modulus) BigNum
// pR reminder BigNum
//
*F*/
IPPFUN(IppStatus, ippsModInv_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR) )
{
IPP_BAD_PTR3_RET(pA, pM, pR);
pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
pM = (IppsBigNumState*)( IPP_ALIGNED_PTR(pM, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr);
pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
IPP_BADARG_RET(BN_ROOM(pR) < BN_SIZE(pM), ippStsOutOfRangeErr);
IPP_BADARG_RET(BN_NEGATIVE(pA) || (BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0), ippStsBadArgErr);
IPP_BADARG_RET(BN_NEGATIVE(pM) || (BN_SIZE(pM)==1 && BN_NUMBER(pM)[0]==0), ippStsBadModulusErr);
IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pM), BN_SIZE(pM)) >= 0, ippStsScaleRangeErr);
{
cpSize nsR = cpModInv_BNU(BN_NUMBER(pR),
BN_NUMBER(pA), BN_SIZE(pA),
BN_NUMBER(pM), BN_SIZE(pM),
BN_BUFFER(pR), BN_BUFFER(pA), BN_BUFFER(pM));
if(nsR) {
BN_SIGN(pR) = ippBigNumPOS;
BN_SIZE(pR) = nsR;
return ippStsNoErr;
}
else
return ippStsBadModulusErr;
}
}