/*******************************************************************************
* Copyright 2010-2018 Intel Corporation
* All Rights Reserved.
*
* If this software was obtained under the Intel Simplified Software License,
* the following terms apply:
*
* The source code, information and material ("Material") contained herein is
* owned by Intel Corporation or its suppliers or licensors, and title to such
* Material remains with Intel Corporation or its suppliers or licensors. The
* Material contains proprietary information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright laws and treaty
* provisions. No part of the Material may be used, copied, reproduced,
* modified, published, uploaded, posted, transmitted, distributed or disclosed
* in any way without Intel's prior express written permission. No license under
* any patent, copyright or other intellectual property rights in the Material
* is granted to or conferred upon you, either expressly, by implication,
* inducement, estoppel or otherwise. Any license under such intellectual
* property rights must be express and approved by Intel in writing.
*
* Unless otherwise agreed by Intel in writing, you may not remove or alter this
* notice or any other notice embedded in Materials by Intel or Intel's
* suppliers or licensors in any way.
*
*
* If this software was obtained under the Apache License, Version 2.0 (the
* "License"), the following terms apply:
*
* 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. Cryptography Primitives.
// Internal operations over GF(p) extension.
//
// Context:
// cpGFpxInv()
//
*/
#include "owncp.h"
#include "pcpbnumisc.h"
#include "pcpgfpxstuff.h"
#include "gsscramble.h"
//tbcd: temporary excluded: #include <assert.h>
static BNU_CHUNK_T* gfpxPolyDiv(BNU_CHUNK_T* pQ, BNU_CHUNK_T* pR,
const BNU_CHUNK_T* pA,
const BNU_CHUNK_T* pB,
gsModEngine* pGFEx)
{
if( GFP_IS_BASIC(pGFEx) )
return NULL;
else {
int elemLen = GFP_FELEN(pGFEx);
gsModEngine* pGroundGFE = GFP_PARENT(pGFEx);
int termLen = GFP_FELEN(pGroundGFE);
int degA = degree(pA, pGFEx);
int degB = degree(pB, pGFEx);
if(degB==0) {
if( GFP_IS_ZERO(pB, termLen) )
return NULL;
else {
gsModEngine* pBasicGFE = cpGFpBasic(pGroundGFE);
cpGFpInv(pR, pB, pBasicGFE);
cpGFpElementPadd(pR+GFP_FELEN(pGroundGFE), termLen-GFP_FELEN(pGroundGFE), 0);
cpGFpxMul_GFE(pQ, pA, pR, pGFEx);
cpGFpElementPadd(pR, elemLen, 0);
return pR;
}
}
if(degA < degB) {
cpGFpElementPadd(pQ, elemLen, 0);
cpGFpElementCopyPadd(pR, elemLen, pA, (degA+1)*termLen);
return pR;
}
else {
mod_mul mulF = GFP_METHOD(pGroundGFE)->mul;
mod_sub subF = GFP_METHOD(pGroundGFE)->sub;
int i, j;
BNU_CHUNK_T* pProduct = cpGFpGetPool(2, pGroundGFE);
BNU_CHUNK_T* pInvB = pProduct + GFP_PELEN(pGroundGFE);
//tbcd: temporary excluded: assert(NULL!=pProduct);
cpGFpElementCopyPadd(pR, elemLen, pA, (degA+1)*termLen);
cpGFpElementPadd(pQ, elemLen, 0);
cpGFpxInv(pInvB, GFPX_IDX_ELEMENT(pB, degB, termLen), pGroundGFE);
for(i=0; i<=degA-degB && !GFP_IS_ZERO(GFPX_IDX_ELEMENT(pR, degA-i, termLen), termLen); i++) {
/* compute q term */
mulF(GFPX_IDX_ELEMENT(pQ, degA-degB-i, termLen),
GFPX_IDX_ELEMENT(pR, degA-i, termLen),
pInvB,
pGroundGFE);
/* R -= B * q */
cpGFpElementPadd(GFPX_IDX_ELEMENT(pR, degA-i, termLen), termLen, 0);
for(j=0; j<degB; j++) {
mulF(pProduct,
GFPX_IDX_ELEMENT(pB, j ,termLen),
GFPX_IDX_ELEMENT(pQ, degA-degB-i, termLen),
pGroundGFE);
subF(GFPX_IDX_ELEMENT(pR, degA-degB-i+j, termLen),
GFPX_IDX_ELEMENT(pR, degA-degB-i+j, termLen),
pProduct,
pGroundGFE);
}
}
cpGFpReleasePool(2, pGroundGFE);
return pR;
}
}
}
static BNU_CHUNK_T* gfpxGeneratorDiv(BNU_CHUNK_T* pQ, BNU_CHUNK_T* pR, const BNU_CHUNK_T* pB, gsModEngine* pGFEx)
{
if( GFP_IS_BASIC(pGFEx) )
return NULL;
else {
int elemLen = GFP_FELEN(pGFEx);
gsModEngine* pGroundGFE = GFP_PARENT(pGFEx);
mod_mul mulF = GFP_METHOD(pGroundGFE)->mul;
mod_sub subF = GFP_METHOD(pGroundGFE)->sub;
int termLen = GFP_FELEN(pGroundGFE);
BNU_CHUNK_T* pInvB = cpGFpGetPool(2, pGroundGFE);
BNU_CHUNK_T* pTmp = pInvB + GFP_PELEN(pGroundGFE);
int degB = degree(pB, pGFEx);
int i;
//tbcd: temporary excluded: assert(NULL!=pInvB);
cpGFpElementCopy(pR, GFP_MODULUS(pGFEx), elemLen);
cpGFpElementPadd(pQ, elemLen, 0);
cpGFpxInv(pInvB, GFPX_IDX_ELEMENT(pB, degB, termLen), pGroundGFE);
for(i=0; i<degB; i++) {
BNU_CHUNK_T* ptr;
mulF(pTmp, pInvB, GFPX_IDX_ELEMENT(pB, i, termLen), pGroundGFE);
ptr = GFPX_IDX_ELEMENT(pR, GFP_EXTDEGREE(pGFEx)-degB+i, termLen);
subF(ptr, ptr, pTmp, pGroundGFE);
}
gfpxPolyDiv(pQ, pR, pR, pB, pGFEx);
cpGFpElementCopy(GFPX_IDX_ELEMENT(pQ, GFP_EXTDEGREE(pGFEx)-degB, termLen), pInvB, termLen);
cpGFpReleasePool(2, pGroundGFE);
return pR;
}
}
BNU_CHUNK_T* cpGFpxInv(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFEx)
{
if( GFP_IS_BASIC(pGFEx) )
return cpGFpInv(pR, pA, pGFEx);
if(0==degree(pA, pGFEx)) {
gsModEngine* pGroundGFE = GFP_PARENT(pGFEx);
BNU_CHUNK_T* tmpR = cpGFpGetPool(1, pGroundGFE);
//tbcd: temporary excluded: assert(NULL!=tmpR);
cpGFpxInv(tmpR, pA, pGroundGFE);
cpGFpElementCopyPadd(pR, GFP_FELEN(pGFEx), tmpR, GFP_FELEN(pGroundGFE));
cpGFpReleasePool(1, pGroundGFE);
return pR;
}
else {
int elemLen = GFP_FELEN(pGFEx);
gsModEngine* pGroundGFE = GFP_PARENT(pGFEx);
gsModEngine* pBasicGFE = cpGFpBasic(pGFEx);
int pxVars = 6;
int pelemLen = GFP_PELEN(pGFEx);
BNU_CHUNK_T* lastrem = cpGFpGetPool(pxVars, pGFEx);
BNU_CHUNK_T* rem = lastrem + pelemLen;
BNU_CHUNK_T* quo = rem + pelemLen;
BNU_CHUNK_T* lastaux = quo + pelemLen;
BNU_CHUNK_T* aux = lastaux + pelemLen;
BNU_CHUNK_T* temp = aux + pelemLen;
//tbcd: temporary excluded: assert(NULL!=lastrem);
cpGFpElementCopy(lastrem, pA, elemLen);
cpGFpElementCopyPadd(lastaux, elemLen, GFP_MNT_R(pBasicGFE), GFP_FELEN(pBasicGFE));
gfpxGeneratorDiv(quo, rem, pA, pGFEx);
cpGFpxNeg(aux, quo, pGFEx);
while(degree(rem, pGFEx) > 0) {
gfpxPolyDiv(quo, temp, lastrem, rem, pGFEx);
SWAP_PTR(BNU_CHUNK_T, rem, lastrem); //
SWAP_PTR(BNU_CHUNK_T, temp, rem);
GFP_METHOD(pGFEx)->neg(quo, quo, pGFEx);
GFP_METHOD(pGFEx)->mul(temp, quo, aux, pGFEx);
GFP_METHOD(pGFEx)->add(temp, lastaux, temp, pGFEx);
SWAP_PTR(BNU_CHUNK_T, aux, lastaux);
SWAP_PTR(BNU_CHUNK_T, temp, aux);
}
if (GFP_IS_ZERO(rem, elemLen)) { /* gcd != 1 */
cpGFpReleasePool(pxVars, pGFEx);
return NULL;
}
{
BNU_CHUNK_T* invRem = cpGFpGetPool(1, pGroundGFE);
//tbcd: temporary excluded: assert(NULL!=invRem);
cpGFpxInv(invRem, rem, pGroundGFE);
cpGFpxMul_GFE(pR, aux, invRem, pGFEx);
cpGFpReleasePool(1, pGroundGFE);
}
cpGFpReleasePool(pxVars, pGFEx);
return pR;
}
}