blob: ee810f65006b9462c90473fca4c81e46e9fd98aa [file] [log] [blame]
/*############################################################################
# Copyright 1999-2018 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) Performance Primitives. Cryptography Primitives.
// EC over GF(p^m) definitinons
//
// Context:
// ippsGFpECGetSize()
// ippsGFpECInit()
//
// ippsGFpECInitStd192r1
// ippsGFpECInitStd224r1
// ippsGFpECInitStd256r1
// ippsGFpECInitStd384r1
// ippsGFpECInitStd521r1
// ippsGFpECInitStdSM2
// ippsGFpECInitStdBN256
//
// ippsGFpECSet()
// ippsGFpECSetSubgroup()
//
// ippsGFpECBindGxyTblStd192r1
// ippsGFpECBindGxyTblStd224r1
// ippsGFpECBindGxyTblStd256r1
// ippsGFpECBindGxyTblStd384r1
// ippsGFpECBindGxyTblStd521r1
// ippsGFpECBindGxyTblStdSM2
//
// ippsGFpECGet()
// ippsGFpECGetSubgroup()
//
// ippsGFpECScratchBufferSize()
// ippsGFpECVerify()
//
//
*/
#include "owndefs.h"
#include "owncp.h"
#include "pcpgfpecstuff.h"
#include "pcpeccp.h"
//gres: temporary excluded: #include <assert.h>
int cpGFpECGetSize(int basicDeg, int basicElmBitSize)
{
int ctxSize = 0;
int elemLen = basicDeg*BITS_BNU_CHUNK(basicElmBitSize);
int maxOrderBits = 1+ basicDeg*basicElmBitSize;
#if defined(_LEGACY_ECCP_SUPPORT_)
int maxOrderLen = BITS_BNU_CHUNK(maxOrderBits);
#endif
int modEngineCtxSize;
if(ippStsNoErr==gsModEngineGetSize(maxOrderBits, MONT_DEFAULT_POOL_LENGTH, &modEngineCtxSize)) {
ctxSize = sizeof(IppsGFpECState)
+elemLen*sizeof(BNU_CHUNK_T) /* EC coeff A */
+elemLen*sizeof(BNU_CHUNK_T) /* EC coeff B */
+elemLen*sizeof(BNU_CHUNK_T) /* generator G.x */
+elemLen*sizeof(BNU_CHUNK_T) /* generator G.y */
+elemLen*sizeof(BNU_CHUNK_T) /* generator G.z */
+modEngineCtxSize /* mont engine (R) */
+elemLen*sizeof(BNU_CHUNK_T) /* cofactor */
#if defined(_LEGACY_ECCP_SUPPORT_)
+2*elemLen*3*sizeof(BNU_CHUNK_T) /* regular and ephemeral public keys */
+2*maxOrderLen*sizeof(BNU_CHUNK_T) /* regular and ephemeral private keys */
#endif
+elemLen*sizeof(BNU_CHUNK_T)*3*EC_POOL_SIZE;
}
return ctxSize;
}
IPPFUN(IppStatus, ippsGFpECGetSize,(const IppsGFpState* pGF, int* pCtxSize))
{
IPP_BAD_PTR2_RET(pGF, pCtxSize);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
*pCtxSize = cpGFpECGetSize(cpGFpBasicDegreeExtension(pGFE), GFP_FEBITLEN(cpGFpBasic(pGFE)))
+ ECGFP_ALIGNMENT;
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInit,(const IppsGFpState* pGF,
const IppsGFpElement* pA, const IppsGFpElement* pB,
IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
{
Ipp8u* ptr = (Ipp8u*)pEC;
gsModEngine* pGFE = GFP_PMA(pGF);
int elemLen = GFP_FELEN(pGFE);
int maxOrderBits = 1+ cpGFpBasicDegreeExtension(pGFE) * GFP_FEBITLEN(cpGFpBasic(pGFE));
#if defined(_LEGACY_ECCP_SUPPORT_)
int maxOrdLen = BITS_BNU_CHUNK(maxOrderBits);
#endif
int modEngineCtxSize;
gsModEngineGetSize(maxOrderBits, MONT_DEFAULT_POOL_LENGTH, &modEngineCtxSize);
ECP_ID(pEC) = idCtxGFPEC;
ECP_GFP(pEC) = (IppsGFpState*)(IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT));
ECP_POINTLEN(pEC) = elemLen*3;
ECP_ORDBITSIZE(pEC) = maxOrderBits;
ECP_SPECIFIC(pEC) = ECP_ARB;
ptr += sizeof(IppsGFpECState);
ECP_A(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*sizeof(BNU_CHUNK_T);
ECP_B(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*sizeof(BNU_CHUNK_T);
ECP_G(pEC) = (BNU_CHUNK_T*)(ptr); ptr += ECP_POINTLEN(pEC)*sizeof(BNU_CHUNK_T);
ECP_PREMULBP(pEC) = (cpPrecompAP*)NULL;
ECP_MONT_R(pEC) = (gsModEngine*)( IPP_ALIGNED_PTR((ptr), (MONT_ALIGNMENT)) ); ptr += modEngineCtxSize;
ECP_COFACTOR(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*sizeof(BNU_CHUNK_T);
#if defined(_LEGACY_ECCP_SUPPORT_)
ECP_PUBLIC(pEC) = (BNU_CHUNK_T*)(ptr); ptr += 3*elemLen*sizeof(BNU_CHUNK_T);
ECP_PUBLIC_E(pEC) = (BNU_CHUNK_T*)(ptr); ptr += 3*elemLen*sizeof(BNU_CHUNK_T);
ECP_PRIVAT(pEC) = (BNU_CHUNK_T*)(ptr); ptr += maxOrdLen*sizeof(BNU_CHUNK_T);
ECP_PRIVAT_E(pEC) = (BNU_CHUNK_T*)(ptr); ptr += maxOrdLen*sizeof(BNU_CHUNK_T);
ECP_SBUFFER(pEC) = (BNU_CHUNK_T*)0;
#endif
ECP_POOL(pEC) = (BNU_CHUNK_T*)(ptr); //ptr += ECP_POINTLEN(pEC)*sizeof(BNU_CHUNK_T)*EC_POOL_SIZE;
cpGFpElementPadd(ECP_A(pEC), elemLen, 0);
cpGFpElementPadd(ECP_B(pEC), elemLen, 0);
cpGFpElementPadd(ECP_G(pEC), elemLen*3, 0);
gsModEngineInit(ECP_MONT_R(pEC), NULL, maxOrderBits, MONT_DEFAULT_POOL_LENGTH, gsModArithMont());
cpGFpElementPadd(ECP_COFACTOR(pEC), elemLen, 0);
cpGFpElementPadd(ECP_POOL(pEC), elemLen*3*EC_POOL_SIZE, 0);
/* set up EC if possible */
if(pA && pB)
return ippsGFpECSet(pA,pB, pEC);
else
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECSet,(const IppsGFpElement* pA,
const IppsGFpElement* pB,
IppsGFpECState* pEC))
{
IPP_BAD_PTR1_RET(pEC);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
IPP_BAD_PTR2_RET(pA, pB);
IPP_BADARG_RET( !GFPE_TEST_ID(pA), ippStsContextMatchErr );
IPP_BADARG_RET( !GFPE_TEST_ID(pB), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(ECP_GFP(pEC));
int elemLen = GFP_FELEN(pGFE);
IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
IPP_BADARG_RET( GFPE_ROOM(pB)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
/* copy A */
cpGFpElementPadd(ECP_A(pEC), elemLen, 0);
cpGFpElementCopy(ECP_A(pEC), GFPE_DATA(pA), elemLen);
/* and set up A-specific (a==0 or a==-3) if is */
if(GFP_IS_ZERO(ECP_A(pEC), elemLen))
ECP_SPECIFIC(pEC) = ECP_EPID2;
cpGFpElementSetChunk(ECP_B(pEC), elemLen, 3);
GFP_METHOD(pGFE)->encode(ECP_B(pEC), ECP_B(pEC), pGFE);
GFP_METHOD(pGFE)->add(ECP_B(pEC), ECP_A(pEC), ECP_B(pEC), pGFE);
if(GFP_IS_ZERO(ECP_B(pEC), elemLen))
ECP_SPECIFIC(pEC) = ECP_STD;
/* copy B */
cpGFpElementPadd(ECP_B(pEC), elemLen, 0);
cpGFpElementCopy(ECP_B(pEC), GFPE_DATA(pB), elemLen);
/* and set type of affine infinity representation:
// (0,1) if B==0
// (0,0) if B!=0 */
ECP_INFINITY(pEC) = GFP_IS_ZERO(ECP_B(pEC), elemLen);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECSetSubgroup,(const IppsGFpElement* pX, const IppsGFpElement* pY,
const IppsBigNumState* pOrder,
const IppsBigNumState* pCofactor,
IppsGFpECState* pEC))
{
IPP_BAD_PTR1_RET(pEC);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
IPP_BAD_PTR2_RET(pX, pY);
IPP_BADARG_RET( !GFPE_TEST_ID(pX), ippStsContextMatchErr );
IPP_BADARG_RET( !GFPE_TEST_ID(pY), ippStsContextMatchErr );
IPP_BAD_PTR2_RET(pOrder, pCofactor);
pOrder = (IppsBigNumState*)( IPP_ALIGNED_PTR(pOrder, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pOrder), ippStsContextMatchErr);
IPP_BADARG_RET(BN_SIGN(pOrder)!= IppsBigNumPOS, ippStsBadArgErr);
pCofactor = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCofactor, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pCofactor), ippStsContextMatchErr);
IPP_BADARG_RET(BN_SIGN(pCofactor)!= IppsBigNumPOS, ippStsBadArgErr);
{
gsModEngine* pGFE = GFP_PMA(ECP_GFP(pEC));
int elemLen = GFP_FELEN(pGFE);
IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
IPP_BADARG_RET( GFPE_ROOM(pY)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
gfec_SetPoint(ECP_G(pEC), GFPE_DATA(pX), GFPE_DATA(pY), pEC);
{
int maxOrderBits = 1+ cpGFpBasicDegreeExtension(pGFE) * GFP_FEBITLEN(cpGFpBasic(pGFE));
BNU_CHUNK_T* pOrderData = BN_NUMBER(pOrder);
int orderLen= BN_SIZE(pOrder);
int orderBitSize = BITSIZE_BNU(pOrderData, orderLen);
IPP_BADARG_RET(orderBitSize>maxOrderBits, ippStsRangeErr)
ECP_ORDBITSIZE(pEC) = orderBitSize;
gsModEngineInit(ECP_MONT_R(pEC),(Ipp32u*)pOrderData, orderBitSize, MONT_DEFAULT_POOL_LENGTH, gsModArithMont());
}
{
BNU_CHUNK_T* pCofactorData = BN_NUMBER(pCofactor);
int cofactorLen= BN_SIZE(pCofactor);
int cofactorBitSize = BITSIZE_BNU(pCofactorData, cofactorLen);
IPP_BADARG_RET(cofactorBitSize>elemLen*BITSIZE(BNU_CHUNK_T), ippStsRangeErr)
COPY_BNU(ECP_COFACTOR(pEC), pCofactorData, cofactorLen);
}
return ippStsNoErr;
}
}
static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA,
int bLen, const BNU_CHUNK_T* pB,
int xLen, const BNU_CHUNK_T* pX,
int yLen, const BNU_CHUNK_T* pY,
int rLen, const BNU_CHUNK_T* pR,
BNU_CHUNK_T h,
IppsGFpECState* pEC)
{
IppsGFpState* pGF = ECP_GFP(pEC);
gsModEngine* pGFE = GFP_PMA(pGF);
int elemLen = GFP_FELEN(pGFE);
IppsGFpElement elmA, elmB;
IppsBigNumState R, H;
/* convert A ans B coeffs into GF elements */
cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen);
cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen);
ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF);
ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF);
/* and set EC */
ippsGFpECSet(&elmA, &elmB, pEC);
/* construct R and H */
cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL);
cpConstructBN(&H, 1, &h, NULL);
/* convert GX ans GY coeffs into GF elements */
ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF);
ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF);
/* and init EC subgroup */
ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC);
}
IPPFUN(IppStatus, ippsGFpECInitStd128r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp128r1_p, BITS_BNU_CHUNK(128), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(128)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(128), secp128r1_a,
BITS_BNU_CHUNK(128), secp128r1_b,
BITS_BNU_CHUNK(128), secp128r1_gx,
BITS_BNU_CHUNK(128), secp128r1_gy,
BITS_BNU_CHUNK(128), secp128r1_r,
secp128r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd128r2,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp128r2_p, BITS_BNU_CHUNK(128), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(128)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(128), secp128r2_a,
BITS_BNU_CHUNK(128), secp128r2_b,
BITS_BNU_CHUNK(128), secp128r2_gx,
BITS_BNU_CHUNK(128), secp128r2_gy,
BITS_BNU_CHUNK(128), secp128r2_r,
secp128r2_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd192r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp192r1_p, BITS_BNU_CHUNK(192), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(192)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(192), secp192r1_a,
BITS_BNU_CHUNK(192), secp192r1_b,
BITS_BNU_CHUNK(192), secp192r1_gx,
BITS_BNU_CHUNK(192), secp192r1_gy,
BITS_BNU_CHUNK(192), secp192r1_r,
secp192r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd224r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp224r1_p, BITS_BNU_CHUNK(224), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(224)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(224), secp224r1_a,
BITS_BNU_CHUNK(224), secp224r1_b,
BITS_BNU_CHUNK(224), secp224r1_gx,
BITS_BNU_CHUNK(224), secp224r1_gy,
BITS_BNU_CHUNK(224), secp224r1_r,
secp224r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd256r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp256r1_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(256), secp256r1_a,
BITS_BNU_CHUNK(256), secp256r1_b,
BITS_BNU_CHUNK(256), secp256r1_gx,
BITS_BNU_CHUNK(256), secp256r1_gy,
BITS_BNU_CHUNK(256), secp256r1_r,
secp256r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd384r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp384r1_p, BITS_BNU_CHUNK(384), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(384)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(384), secp384r1_a,
BITS_BNU_CHUNK(384), secp384r1_b,
BITS_BNU_CHUNK(384), secp384r1_gx,
BITS_BNU_CHUNK(384), secp384r1_gy,
BITS_BNU_CHUNK(384), secp384r1_r,
secp384r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStd521r1,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(secp521r1_p, BITS_BNU_CHUNK(521), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(521)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(521), secp521r1_a,
BITS_BNU_CHUNK(521), secp521r1_b,
BITS_BNU_CHUNK(521), secp521r1_gx,
BITS_BNU_CHUNK(521), secp521r1_gy,
BITS_BNU_CHUNK(521), secp521r1_r,
secp521r1_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStdSM2,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(tpmSM2_p256_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(256), tpmSM2_p256_a,
BITS_BNU_CHUNK(256), tpmSM2_p256_b,
BITS_BNU_CHUNK(256), tpmSM2_p256_gx,
BITS_BNU_CHUNK(256), tpmSM2_p256_gy,
BITS_BNU_CHUNK(256), tpmSM2_p256_r,
tpmSM2_p256_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECInitStdBN256,(const IppsGFpState* pGF, IppsGFpECState* pEC))
{
IPP_BAD_PTR2_RET(pGF, pEC);
pGF = (IppsGFpState*)( IPP_ALIGNED_PTR(pGF, GFP_ALIGNMENT) );
IPP_BADARG_RET( !GFP_TEST_ID(pGF), ippStsContextMatchErr );
{
gsModEngine* pGFE = GFP_PMA(pGF);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(tpmBN_p256p_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
ippsGFpECInit(pGF, NULL, NULL, pEC);
cpGFpECSetStd(BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_a,
BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_b,
BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_gx,
BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_gy,
BITS_BNU_CHUNK(256), tpmBN_p256p_r,
tpmBN_p256p_h,
pEC);
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECGet,(IppsGFpState** const ppGF,
IppsGFpElement* pA, IppsGFpElement* pB,
const IppsGFpECState* pEC))
{
IPP_BAD_PTR1_RET(pEC);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
{
const IppsGFpState* pGF = ECP_GFP(pEC);
gsModEngine* pGFE = GFP_PMA(pGF);
Ipp32u elementSize = GFP_FELEN(pGFE);
if(ppGF) {
*ppGF = (IppsGFpState*)pGF;
}
if(pA) {
IPP_BADARG_RET( !GFPE_TEST_ID(pA), ippStsContextMatchErr );
IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
cpGFpElementCopy(GFPE_DATA(pA), ECP_A(pEC), elementSize);
}
if(pB) {
IPP_BADARG_RET( !GFPE_TEST_ID(pB), ippStsContextMatchErr );
IPP_BADARG_RET( GFPE_ROOM(pB)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
cpGFpElementCopy(GFPE_DATA(pB), ECP_B(pEC), elementSize);
}
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECGetSubgroup,(IppsGFpState** const ppGF,
IppsGFpElement* pX, IppsGFpElement* pY,
IppsBigNumState* pOrder,
IppsBigNumState* pCofactor,
const IppsGFpECState* pEC))
{
IPP_BAD_PTR1_RET(pEC);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
{
const IppsGFpState* pGF = ECP_GFP(pEC);
gsModEngine* pGFE = GFP_PMA(pGF);
Ipp32u elementSize = GFP_FELEN(pGFE);
if(ppGF) {
*ppGF = (IppsGFpState*)pGF;
}
if(pX) {
IPP_BADARG_RET( !GFPE_TEST_ID(pX), ippStsContextMatchErr );
IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
cpGFpElementCopy(GFPE_DATA(pX), ECP_G(pEC), elementSize);
}
if(pY) {
IPP_BADARG_RET( !GFPE_TEST_ID(pY), ippStsContextMatchErr );
IPP_BADARG_RET( GFPE_ROOM(pY)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr);
cpGFpElementCopy(GFPE_DATA(pY), ECP_G(pEC)+elementSize, elementSize);
}
if(pOrder) {
BNU_CHUNK_T* pOrderData = MOD_MODULUS(ECP_MONT_R(pEC));
int orderBitSize = ECP_ORDBITSIZE(pEC);
int orderLen = BITS_BNU_CHUNK(orderBitSize);
FIX_BNU(pOrderData, orderLen);
pOrder = (IppsBigNumState*)( IPP_ALIGNED_PTR(pOrder, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pOrder), ippStsContextMatchErr);
IPP_BADARG_RET(BN_ROOM(pOrder) < orderLen, ippStsLengthErr);
ZEXPAND_COPY_BNU(BN_NUMBER(pOrder), BN_ROOM(pOrder), pOrderData, orderLen);
BN_SIZE(pOrder) = orderLen;
BN_SIGN(pOrder) = ippBigNumPOS;
}
if(pCofactor) {
BNU_CHUNK_T* pCofactorData = ECP_COFACTOR(pEC);
int cofactorLen = elementSize;
FIX_BNU(pCofactorData, cofactorLen);
pCofactor = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCofactor, BN_ALIGNMENT) );
IPP_BADARG_RET(!BN_VALID_ID(pCofactor), ippStsContextMatchErr);
IPP_BADARG_RET(BN_ROOM(pCofactor) < cofactorLen, ippStsLengthErr);
ZEXPAND_COPY_BNU(BN_NUMBER(pCofactor), BN_ROOM(pCofactor), pCofactorData, cofactorLen);
BN_SIZE(pCofactor) = cofactorLen;
BN_SIGN(pCofactor) = ippBigNumPOS;
}
return ippStsNoErr;
}
}
static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime,
const cpPrecompAP* preComp,
IppsGFpECState* pEC)
{
IPP_BAD_PTR1_RET(pEC);
/* use aligned EC context */
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET(!ECP_TEST_ID(pEC), ippStsContextMatchErr);
{
IppsGFpState* pGF = ECP_GFP(pEC);
gsModEngine* pGFE = GFP_PMA(pGF);
Ipp32u elemLen = GFP_FELEN(pGFE);
/* test if GF is prime GF */
IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr);
/* test underlying prime value*/
IPP_BADARG_RET(cpCmp_BNU(pPrime, elemLen, GFP_MODULUS(pGFE), elemLen), ippStsBadArgErr);
{
BNU_CHUNK_T* pbp_ec = ECP_G(pEC);
int cmpFlag;
BNU_CHUNK_T* pbp_tbl = cpEcGFpGetPool(1, pEC);
selectAP select_affine_point = preComp->select_affine_point;
const BNU_CHUNK_T* pTbl = preComp->pTbl;
select_affine_point(pbp_tbl, pTbl, 1);
/* check if EC's and G-table's Base Point is the same */
cmpFlag = cpCmp_BNU(pbp_ec, elemLen*2, pbp_tbl, elemLen*2);
cpEcGFpReleasePool(1, pEC);
return cmpFlag? ippStsBadArgErr : ippStsNoErr;
}
}
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStd192r1,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(secp192r1_p, gfpec_precom_nistP192r1_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_nistP192r1_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStd224r1,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(secp224r1_p, gfpec_precom_nistP224r1_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_nistP224r1_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStd256r1,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(secp256r1_p, gfpec_precom_nistP256r1_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_nistP256r1_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStd384r1,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(secp384r1_p, gfpec_precom_nistP384r1_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_nistP384r1_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStd521r1,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(secp521r1_p, gfpec_precom_nistP521r1_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_nistP521r1_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECBindGxyTblStdSM2,(IppsGFpECState* pEC))
{
IppStatus sts = cpGFpECBindGxyTbl(tpmSM2_p256_p, gfpec_precom_sm2_fun(), pEC);
/* setup pre-computed g-table and point access function */
if(ippStsNoErr==sts)
ECP_PREMULBP(pEC) = gfpec_precom_sm2_fun();
return sts;
}
IPPFUN(IppStatus, ippsGFpECScratchBufferSize,(int nScalars, const IppsGFpECState* pEC, int* pBufferSize))
{
IPP_BAD_PTR2_RET(pEC, pBufferSize);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
IPP_BADARG_RET( (0>=nScalars)||(nScalars>IPP_MAX_EXPONENT_NUM), ippStsBadArgErr);
{
/* select constant size of window */
const int w = 5;
/* number of table entries */
const int nPrecomputed = 1<<(w-1); /* because of signed digit representation of scalar is uses */
int pointDataSize = ECP_POINTLEN(pEC)*sizeof(BNU_CHUNK_T);
*pBufferSize = nScalars * pointDataSize*nPrecomputed + CACHE_LINE_SIZE;
return ippStsNoErr;
}
}
IPPFUN(IppStatus, ippsGFpECVerify,(IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer))
{
IPP_BAD_PTR3_RET(pEC, pResult, pScratchBuffer);
pEC = (IppsGFpECState*)( IPP_ALIGNED_PTR(pEC, ECGFP_ALIGNMENT) );
IPP_BADARG_RET( !ECP_TEST_ID(pEC), ippStsContextMatchErr );
*pResult = ippECValid;
{
IppsGFpState* pGF = ECP_GFP(pEC);
gsModEngine* pGFE = GFP_PMA(pGF);
int elemLen = GFP_FELEN(pGFE);
mod_mul mulF = GFP_METHOD(pGFE)->mul;
mod_sqr sqrF = GFP_METHOD(pGFE)->sqr;
mod_add addF = GFP_METHOD(pGFE)->add;
/*
// check discriminant ( 4*A^3 + 27*B^2 != 0 mod P)
*/
if(ippECValid == *pResult) {
BNU_CHUNK_T* pT = cpGFpGetPool(1, pGFE);
BNU_CHUNK_T* pU = cpGFpGetPool(1, pGFE);
//gres: temporary excluded: assert(NULL!=pT && NULL!=pU);
if(ECP_SPECIFIC(pEC)==ECP_EPID2)
cpGFpElementPadd(pT, elemLen, 0); /* T = 4*A^3 = 0 */
else {
addF(pT, ECP_A(pEC), ECP_A(pEC), pGFE); /* T = 4*A^3 */
sqrF(pT, pT, pGFE);
mulF(pT, ECP_A(pEC), pT, pGFE);
}
addF(pU, ECP_B(pEC), ECP_B(pEC), pGFE); /* U = 9*B^2 */
addF(pU, pU, ECP_B(pEC), pGFE);
sqrF(pU, pU, pGFE);
addF(pT, pU, pT, pGFE); /* T += 3*U */
addF(pT, pU, pT, pGFE);
addF(pT, pU, pT, pGFE);
*pResult = GFP_IS_ZERO(pT, elemLen)? ippECIsZeroDiscriminant: ippECValid;
cpGFpReleasePool(2, pGFE);
}
/*
// check base point and it order
*/
if(ippECValid == *pResult) {
IppsGFpECPoint G;
cpEcGFpInitPoint(&G, ECP_G(pEC), ECP_AFFINE_POINT|ECP_FINITE_POINT, pEC);
/* check G != infinity */
*pResult = gfec_IsPointAtInfinity(&G)? ippECPointIsAtInfinite : ippECValid;
/* check G lies on EC */
if(ippECValid == *pResult)
*pResult = gfec_IsPointOnCurve(&G, pEC)? ippECValid : ippECPointIsNotValid;
/* check Gorder*G = infinity */
if(ippECValid == *pResult) {
IppsGFpECPoint T;
cpEcGFpInitPoint(&T, cpEcGFpGetPool(1, pEC),0, pEC);
//gfec_MulPoint(&T, &G, MNT_MODULUS(ECP_MONT_R(pEC)), BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC)), pEC, pScratchBuffer);
gfec_MulBasePoint(&T, MOD_MODULUS(ECP_MONT_R(pEC)), BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC)), pEC, pScratchBuffer);
*pResult = gfec_IsPointAtInfinity(&T)? ippECValid : ippECInvalidOrder;
cpEcGFpReleasePool(1, pEC);
}
}
/*
// check order==P
*/
if(ippECValid == *pResult) {
BNU_CHUNK_T* pPrime = GFP_MODULUS(pGFE);
int primeLen = GFP_FELEN(pGFE);
gsModEngine* pR = ECP_MONT_R(pEC);
BNU_CHUNK_T* pOrder = MOD_MODULUS(pR);
int orderLen = MOD_LEN(pR);
*pResult = (primeLen==orderLen && GFP_EQ(pPrime, pOrder, primeLen))? ippECIsWeakSSSA : ippECValid;
}
return ippStsNoErr;
}
}