mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
DirtySDK (EA's Dirty Sockets library) will be used for the LiveAPI implementation, and depends on: EABase, EAThread.
649 lines
22 KiB
C
649 lines
22 KiB
C
/*H********************************************************************************/
|
|
/*!
|
|
\File cryptmont.h
|
|
|
|
\Description
|
|
This module implements the math for elliptic curve cryptography
|
|
using montgomery curves
|
|
|
|
\Copyright
|
|
Copyright (c) Electronic Arts 2018. ALL RIGHTS RESERVED.
|
|
*/
|
|
/********************************************************************************H*/
|
|
|
|
#include "DirtySDK/dirtysock/dirtylib.h"
|
|
#include "DirtySDK/dirtysock/dirtymem.h"
|
|
#include "DirtySDK/crypt/cryptrand.h"
|
|
|
|
#include "DirtySDK/crypt/cryptmont.h"
|
|
|
|
/*** Defines **********************************************************************/
|
|
|
|
//! size of the window used to determined the table size
|
|
#define CRYPTMONT_WINDOW_SIZE (5)
|
|
|
|
//! calculation of the table size based on the window
|
|
#define CRYPTMONT_TABLE_SIZE (1 << (CRYPTMONT_WINDOW_SIZE - 1))
|
|
|
|
//! memgroup for allocating the table
|
|
#define CRYPTMONT_MEMID ('mont')
|
|
|
|
//! number of iterations to do per call
|
|
#define CRYPTMONT_NUM_ITERATIONS (0x10)
|
|
|
|
/*** Variables ********************************************************************/
|
|
|
|
//! prime for x25519
|
|
static const uint8_t _aPrime25519[] =
|
|
{
|
|
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed
|
|
};
|
|
|
|
//! prime for x25519
|
|
static const uint8_t _aPrime448[] =
|
|
{
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
};
|
|
|
|
/*** Private Functions ************************************************************/
|
|
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function _CryptMontSwap
|
|
|
|
\Description
|
|
Constant time conditional swap of two big numbers
|
|
|
|
\Input uSwap - determintes if we should swap
|
|
\Input *pLhs - [out] first big number in the swap
|
|
\Input *pRhs - [out] second big number in the swap
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
static void _CryptMontSwap(uint8_t uSwap, CryptBnT *pLhs, CryptBnT *pRhs)
|
|
{
|
|
CryptBnT Temp, Mask;
|
|
|
|
// mask = (1 << bits) - swap
|
|
CryptBnInitSet(&Mask, 1);
|
|
CryptBnInitSet(&Temp, uSwap);
|
|
CryptBnLeftShift2(&Mask, DS_MAX(CryptBnBitLen(pLhs), CryptBnBitLen(pRhs)));
|
|
CryptBnSubtract(&Mask, &Mask, &Temp);
|
|
|
|
// temp = mask & (lhs ^ rhs)
|
|
CryptBnBitXor(&Temp, pLhs, pRhs);
|
|
CryptBnBitAnd(&Temp, &Temp, &Mask);
|
|
|
|
// lhs ^= temp
|
|
CryptBnBitXor(pLhs, pLhs, &Temp);
|
|
|
|
// rhs ^= temp
|
|
CryptBnBitXor(pRhs, pRhs, &Temp);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function _CryptMontPointCalculate
|
|
|
|
\Description
|
|
Calculates the point multiplication on the curve based on the private key
|
|
before doing the final result calculation
|
|
|
|
\Input *pState - curve state
|
|
\Input *pU - the point we multiply with the private key
|
|
|
|
\Output
|
|
uint8_t - TRUE=complete, FALSE=pending
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
static uint8_t _CryptMontPointCalculate(CryptMontT *pState, CryptBnT *pU)
|
|
{
|
|
int32_t iIter;
|
|
|
|
// initialize the operation
|
|
if (pState->iBitIndex < 0)
|
|
{
|
|
pState->iBitIndex = CryptBnBitLen(&pState->Prime) - 1;
|
|
pState->uCryptUsecs = 0;
|
|
|
|
CryptBnInitSet(&pState->X_2, 1);
|
|
CryptBnInitSet(&pState->Result.X, 0);
|
|
CryptBnClone(&pState->X_3, pU);
|
|
CryptBnInitSet(&pState->Result.Y, 1);
|
|
}
|
|
|
|
for (iIter = 0; (pState->iBitIndex >= 0) && (iIter < CRYPTMONT_NUM_ITERATIONS); pState->iBitIndex -= 1, iIter += 1)
|
|
{
|
|
CryptBnT A, AA, B, BB, C, D, DA, CB, E;
|
|
uint8_t bBitSet = CryptBnBitTest(&pState->PrivateKey, pState->iBitIndex);
|
|
const uint64_t uTickUsecs = NetTickUsec();
|
|
|
|
CryptBnInitSet(&A, 0);
|
|
CryptBnInitSet(&B, 0);
|
|
CryptBnInitSet(&C, 0);
|
|
CryptBnInitSet(&D, 0);
|
|
CryptBnInitSet(&E, 0);
|
|
|
|
// swap ^= bitset;
|
|
pState->uSwap ^= bBitSet;
|
|
|
|
// constant time conditional swap
|
|
_CryptMontSwap(pState->uSwap, &pState->X_2, &pState->X_3);
|
|
_CryptMontSwap(pState->uSwap, &pState->Result.X, &pState->Result.Y);
|
|
|
|
// swap = bitset
|
|
pState->uSwap = bBitSet;
|
|
|
|
// A = (x_2 + z_2) % p
|
|
CryptBnModAdd(&A, &pState->X_2, &pState->Result.X, &pState->Prime);
|
|
|
|
// AA = (A * A) % p
|
|
CryptBnModMultiply(&AA, &A, &A, &pState->Prime);
|
|
|
|
// B = (x_2 - z_2)
|
|
CryptBnSubtract(&B, &pState->X_2, &pState->Result.X);
|
|
|
|
// BB = (B * B) % p
|
|
CryptBnModMultiply(&BB, &B, &B, &pState->Prime);
|
|
|
|
// E = (AA - BB)
|
|
CryptBnSubtract(&E, &AA, &BB);
|
|
|
|
// x_2 = (AA * BB) % p
|
|
CryptBnModMultiply(&pState->X_2, &AA, &BB, &pState->Prime);
|
|
|
|
// z_2 = (E * (AA + (a24 * E))) % p
|
|
CryptBnModMultiply(&pState->Result.X, &pState->A24, &E, &pState->Prime);
|
|
CryptBnModAdd(&pState->Result.X, &AA, &pState->Result.X, &pState->Prime);
|
|
CryptBnModMultiply(&pState->Result.X, &E, &pState->Result.X, &pState->Prime);
|
|
|
|
// C = (x_3 + z_3) % p
|
|
CryptBnModAdd(&C, &pState->X_3, &pState->Result.Y, &pState->Prime);
|
|
|
|
// D = x_3 - z_3
|
|
CryptBnSubtract(&D, &pState->X_3, &pState->Result.Y);
|
|
|
|
// DA = (D * A) % p
|
|
CryptBnModMultiply(&DA, &D, &A, &pState->Prime);
|
|
|
|
// CB = (C * B) % p
|
|
CryptBnModMultiply(&CB, &C, &B, &pState->Prime);
|
|
|
|
// x_3 = (DA+CB)^2 % p
|
|
CryptBnModAdd(&pState->X_3, &DA, &CB, &pState->Prime);
|
|
CryptBnModMultiply(&pState->X_3, &pState->X_3, &pState->X_3, &pState->Prime);
|
|
|
|
// z_3 = (u * ((DA-CB)^2 % p)) % p
|
|
CryptBnSubtract(&pState->Result.Y, &DA, &CB);
|
|
CryptBnModMultiply(&pState->Result.Y, &pState->Result.Y, &pState->Result.Y, &pState->Prime);
|
|
CryptBnModMultiply(&pState->Result.Y, pU, &pState->Result.Y, &pState->Prime);
|
|
|
|
// update timing
|
|
pState->uCryptUsecs += (uint32_t)NetTickDiff(NetTickUsec(), uTickUsecs);
|
|
}
|
|
|
|
// check for completion of first stage, perform required operations and move to next
|
|
if (pState->iBitIndex < 0)
|
|
{
|
|
// constant time conditional swap
|
|
_CryptMontSwap(pState->uSwap, &pState->X_2, &pState->X_3);
|
|
_CryptMontSwap(pState->uSwap, &pState->Result.X, &pState->Result.Y);
|
|
}
|
|
|
|
return((pState->iBitIndex < 0) ? TRUE : FALSE);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function _CryptMontResultCalculate
|
|
|
|
\Description
|
|
Determines the final using the final result using the formula:
|
|
result = x_2 * (z_2 ^ (p - 2) % p) % p
|
|
|
|
\Input *pState - curve state
|
|
|
|
\Output
|
|
uint8_t - TRUE=complete, FALSE=pending
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
static uint8_t _CryptMontResultCalculate(CryptMontT *pState)
|
|
{
|
|
int32_t iIter;
|
|
|
|
// initialize the operation
|
|
if (pState->iBitIndex < 0)
|
|
{
|
|
int32_t iTableIndex;
|
|
CryptBnT Square;
|
|
|
|
// query memgroup
|
|
DirtyMemGroupQuery(&pState->iMemGroup, &pState->pMemGroupUserdata);
|
|
|
|
if ((pState->pTable = (CryptBnT *)DirtyMemAlloc(sizeof(*pState->pTable) * CRYPTMONT_TABLE_SIZE, CRYPTMONT_MEMID, pState->iMemGroup, pState->pMemGroupUserdata)) == NULL)
|
|
{
|
|
NetPrintf(("cryptmont: failed to allocate window table\n"));
|
|
return(TRUE);
|
|
}
|
|
ds_memclr(pState->pTable, sizeof(*pState->pTable) * CRYPTMONT_TABLE_SIZE);
|
|
|
|
/* put the already reduced input into the first index of the table, this will make it so further
|
|
entries in the table will not be too large for our modulus operations */
|
|
CryptBnClone(&pState->pTable[0], &pState->Result.X);
|
|
|
|
// calculate (input^2) % mod as the basis for the other calculations
|
|
CryptBnModMultiply(&Square, &pState->pTable[0], &pState->pTable[0], &pState->Prime);
|
|
|
|
// calculate (input^(2+iTableIndex)) % mod for the rest of the table
|
|
for (iTableIndex = 1; iTableIndex < CRYPTMONT_TABLE_SIZE; iTableIndex += 1)
|
|
{
|
|
CryptBnModMultiply(&pState->pTable[iTableIndex], &pState->pTable[iTableIndex - 1], &Square, &pState->Prime);
|
|
}
|
|
|
|
pState->bAccumulOne = TRUE;
|
|
|
|
// save prime - 2
|
|
CryptBnInitSet(&pState->PrimeMin2, 2);
|
|
CryptBnSubtract(&pState->PrimeMin2, &pState->Prime, &pState->PrimeMin2);
|
|
|
|
pState->iBitIndex = CryptBnBitLen(&pState->PrimeMin2) - 1;
|
|
}
|
|
|
|
for (iIter = 0; (pState->iBitIndex >= 0) && (iIter < CRYPTMONT_NUM_ITERATIONS); iIter += 1)
|
|
{
|
|
const uint64_t uTickUsecs = NetTickUsec();
|
|
|
|
/* scan backwards from the current exponent bit until a set bit is found to denote the start of the window
|
|
squaring the results until such a bit is found */
|
|
if (CryptBnBitTest(&pState->PrimeMin2, pState->iBitIndex))
|
|
{
|
|
int32_t iWindowBit, iWindowValue, iWindowEnd;
|
|
|
|
/* scan backwards from the start of the window until the last set bit in the range of the window size is found which denotes the end bit index of the window
|
|
calculate the value of the window that will be used when multiplying against our precomputed table we skip the first bit as we know it is set based on the
|
|
current exponent bit check we make right above */
|
|
for (iWindowBit = 1, iWindowValue = 1, iWindowEnd = 0; (iWindowBit < CRYPTMONT_WINDOW_SIZE) && ((pState->iBitIndex - iWindowBit) >= 0); iWindowBit += 1)
|
|
{
|
|
if (CryptBnBitTest(&pState->PrimeMin2, pState->iBitIndex - iWindowBit))
|
|
{
|
|
iWindowValue <<= (iWindowBit - iWindowEnd);
|
|
iWindowValue |= 1; /* force odd */
|
|
iWindowEnd = iWindowBit;
|
|
}
|
|
}
|
|
|
|
// square for all the bits in the window and moving the exponent bit index down each time
|
|
for (iWindowBit = 0; iWindowBit < iWindowEnd + 1; iWindowBit += 1, pState->iBitIndex -= 1)
|
|
{
|
|
CryptBnModMultiply(&pState->Result.X, &pState->Result.X, &pState->Result.X, &pState->Prime);
|
|
}
|
|
|
|
// skip the first multiply
|
|
if (!pState->bAccumulOne)
|
|
{
|
|
CryptBnModMultiply(&pState->Result.X, &pState->Result.X, &pState->pTable[iWindowValue/2], &pState->Prime);
|
|
}
|
|
else
|
|
{
|
|
CryptBnClone(&pState->Result.X, &pState->pTable[iWindowValue/2]);
|
|
pState->bAccumulOne = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CryptBnModMultiply(&pState->Result.X, &pState->Result.X, &pState->Result.X, &pState->Prime);
|
|
pState->iBitIndex -= 1;
|
|
}
|
|
|
|
// update timing
|
|
pState->uCryptUsecs += (uint32_t)NetTickDiff(NetTickUsec(), uTickUsecs);
|
|
}
|
|
|
|
// calculate the final result
|
|
if (pState->iBitIndex < 0)
|
|
{
|
|
DirtyMemFree(pState->pTable, CRYPTMONT_MEMID, pState->iMemGroup, pState->pMemGroupUserdata);
|
|
pState->pTable = NULL;
|
|
|
|
CryptBnModMultiply(&pState->Result.X, &pState->X_2, &pState->Result.X, &pState->Prime);
|
|
}
|
|
|
|
return((pState->iBitIndex < 0) ? TRUE : FALSE);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function _CryptMontInit25519PrivateKey
|
|
|
|
\Description
|
|
Initializes the private key based on the requirements for this curve
|
|
(x25519)
|
|
|
|
\Input *pPrivateKey - [out] private key state
|
|
\Input *pK - private key buffer or NULL if we should generate one
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
static void _CryptMontInit25519PrivateKey(CryptBnT *pPrivateKey, const uint8_t *pK)
|
|
{
|
|
uint8_t aSecret[32];
|
|
|
|
/* per: https://tools.ietf.org/html/rfc7748#section-5
|
|
For X25519, in order to decode 32 random bytes as an integer scalar, set the three least significant bits of the first byte and
|
|
the most significant bit of the last to zero, set the second most significant bit of the last byte to 1 and, finally, decode as
|
|
little-endian. This means that the resulting integer is of the form 2^254 plus eight times a value between 0 and 2^251 - 1 (inclusive) */
|
|
|
|
// retrieve the random bytes if not provided one
|
|
if (pK == NULL)
|
|
{
|
|
CryptRandGet(aSecret, sizeof(aSecret));
|
|
}
|
|
else
|
|
{
|
|
ds_memcpy(aSecret, pK, sizeof(aSecret));
|
|
}
|
|
|
|
aSecret[0] &= 248;
|
|
aSecret[31] &= 127;
|
|
aSecret[31] |= 64;
|
|
CryptBnInitLeFrom(pPrivateKey, aSecret, sizeof(aSecret));
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function _CryptMontInit448PrivateKey
|
|
|
|
\Description
|
|
Initializes the private key based on the requirements for this curve
|
|
(x448)
|
|
|
|
\Input *pPrivateKey - [out] private key state
|
|
\Input *pK - private key buffer or NULL if we should generate one
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
static void _CryptMontInit448PrivateKey(CryptBnT *pPrivateKey, const uint8_t *pK)
|
|
{
|
|
uint8_t aSecret[56];
|
|
|
|
/* per: https://tools.ietf.org/html/rfc7748#section-5
|
|
Likewise, for X448, set the two least significant bits of the first byte to 0, and the most significant bit of the last byte to 1. This
|
|
means that the resulting integer is of the form 2^447 plus four times a value between 0 and 2^445 - 1 (inclusive). */
|
|
|
|
if (pK == NULL)
|
|
{
|
|
CryptRandGet(aSecret, sizeof(aSecret));
|
|
}
|
|
else
|
|
{
|
|
ds_memcpy(aSecret, pK, sizeof(aSecret));
|
|
}
|
|
|
|
aSecret[0] &= 252;
|
|
aSecret[55] |= 128;
|
|
CryptBnInitLeFrom(pPrivateKey, aSecret, sizeof(aSecret));
|
|
}
|
|
|
|
/*** Public Functions ************************************************************/
|
|
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontInit
|
|
|
|
\Description
|
|
Initializes the curve given an identifier
|
|
|
|
\Input *pState - curve state we are initializing
|
|
\Input iCurveType - the curve identifier (CRYPTMONT_CURVE_*)
|
|
|
|
\Output
|
|
int32_t - 0=success, negative=failure
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t CryptMontInit(CryptMontT *pState, int32_t iCurveType)
|
|
{
|
|
// init state
|
|
ds_memclr(pState, sizeof(*pState));
|
|
pState->iBitIndex = -1;
|
|
pState->iCurveType = iCurveType;
|
|
|
|
if (iCurveType == CRYPTCURVE_X25519)
|
|
{
|
|
// save prime
|
|
CryptBnInitFrom(&pState->Prime, -1, _aPrime25519, sizeof(_aPrime25519));
|
|
// save a24
|
|
CryptBnInitSet(&pState->A24, 121665);
|
|
// save u
|
|
CryptBnInitSet(&pState->BasePoint, 9);
|
|
// get k
|
|
_CryptMontInit25519PrivateKey(&pState->PrivateKey, NULL);
|
|
}
|
|
else if (iCurveType == CRYPTCURVE_X448)
|
|
{
|
|
// save prime
|
|
CryptBnInitFrom(&pState->Prime, -1, _aPrime448, sizeof(_aPrime448));
|
|
// save a24
|
|
CryptBnInitSet(&pState->A24, 39081);
|
|
// save u
|
|
CryptBnInitSet(&pState->BasePoint, 5);
|
|
// get k
|
|
_CryptMontInit448PrivateKey(&pState->PrivateKey, NULL);
|
|
}
|
|
else
|
|
{
|
|
NetPrintf(("cryptmont: unrecognized curve type (%d) passed to init\n", iCurveType));
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontSetPrivateKey
|
|
|
|
\Description
|
|
Sets our internal private key for verifying our test vectors based
|
|
on the state's curve type
|
|
|
|
\Input *pState - curve state
|
|
\Input *pKey - the private key buffer
|
|
|
|
\Notes
|
|
This is for testing purposes only
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
void CryptMontSetPrivateKey(CryptMontT *pState, const uint8_t *pKey)
|
|
{
|
|
#if DIRTYCODE_DEBUG
|
|
if (pState->iCurveType == CRYPTCURVE_X25519)
|
|
{
|
|
_CryptMontInit25519PrivateKey(&pState->PrivateKey, pKey);
|
|
}
|
|
else if (pState->iCurveType == CRYPTCURVE_X448)
|
|
{
|
|
_CryptMontInit448PrivateKey(&pState->PrivateKey, pKey);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontPublic
|
|
|
|
\Description
|
|
Generates our public key by doing our PrivateKey * BasePoint on the curve
|
|
|
|
\Input *pState - curve state
|
|
\Input *pResult - [out] result output (optional)
|
|
\Input *pCryptUsecs - [out] timing information for the operation (optional)
|
|
|
|
\Output
|
|
int32_t - zero=success, otherwise=pending
|
|
|
|
\Notes
|
|
If pResult is NULL, the result can be pulled from CryptMontT.Result
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t CryptMontPublic(CryptMontT *pState, CryptEccPointT *pResult, uint32_t *pCryptUsecs)
|
|
{
|
|
int32_t iResult = 1;
|
|
|
|
if ((pState->eState == CRYPTMONT_COMPUTE_POINT) && (_CryptMontPointCalculate(pState, &pState->BasePoint)))
|
|
{
|
|
// switch state on completion
|
|
pState->eState = CRYPTMONT_COMPUTE_EXP;
|
|
}
|
|
else if ((pState->eState == CRYPTMONT_COMPUTE_EXP) && (_CryptMontResultCalculate(pState)))
|
|
{
|
|
// reset back to original state in case they want to perform a different operation
|
|
pState->eState = CRYPTMONT_COMPUTE_POINT;
|
|
|
|
// copy the timing if passed in
|
|
if (pCryptUsecs != NULL)
|
|
{
|
|
*pCryptUsecs = pState->uCryptUsecs;
|
|
}
|
|
// signal completion
|
|
if (pResult != NULL)
|
|
{
|
|
CryptBnClone(&pResult->X, &pState->Result.X);
|
|
}
|
|
iResult = 0;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontSecret
|
|
|
|
\Description
|
|
Generates our shared secret by doing our PrivateKey * PublicKey on the curve
|
|
|
|
\Input *pState - curve state
|
|
\Input *pPublicKey - the peer's public key
|
|
\Input *pResult - [out] result output (optional)
|
|
\Input *pCryptUsecs - [out] timing information for the operation (optional)
|
|
|
|
\Output
|
|
int32_t - zero=success, otherwise=pending
|
|
|
|
\Notes
|
|
If pResult is NULL, the result can be pulled from CryptMontT.Result
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t CryptMontSecret(CryptMontT *pState, CryptEccPointT *pPublicKey, CryptEccPointT *pResult, uint32_t *pCryptUsecs)
|
|
{
|
|
int32_t iResult = 1;
|
|
|
|
if ((pState->eState == CRYPTMONT_COMPUTE_POINT) && (_CryptMontPointCalculate(pState, &pPublicKey->X)))
|
|
{
|
|
// switch state on completion
|
|
pState->eState = CRYPTMONT_COMPUTE_EXP;
|
|
}
|
|
else if ((pState->eState == CRYPTMONT_COMPUTE_EXP) && (_CryptMontResultCalculate(pState)))
|
|
{
|
|
// reset back to original state in case they want to perform a different operation
|
|
pState->eState = CRYPTMONT_COMPUTE_POINT;
|
|
|
|
// copy the timing if passed in
|
|
if (pCryptUsecs != NULL)
|
|
{
|
|
*pCryptUsecs = pState->uCryptUsecs;
|
|
}
|
|
// signal completion
|
|
if (pResult != NULL)
|
|
{
|
|
CryptBnClone(&pResult->X, &pState->Result.X);
|
|
}
|
|
iResult = 0;
|
|
}
|
|
return(iResult);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontPointInitFrom
|
|
|
|
\Description
|
|
Initializes our point representation given a buffer
|
|
|
|
\Input *pPoint - point state
|
|
\Input *pBuffer - the buffer we are copying from
|
|
\Input iBufSize - size of the buffer
|
|
|
|
\Output
|
|
int32_t - zero=success, otherwise=failure
|
|
|
|
\Notes
|
|
These curves work in little endian so need to copy different functions
|
|
from our nist curves.
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t CryptMontPointInitFrom(CryptEccPointT *pPoint, const uint8_t *pBuffer, int32_t iBufSize)
|
|
{
|
|
CryptBnInitLeFrom(&pPoint->X, pBuffer, iBufSize);
|
|
return(0);
|
|
}
|
|
|
|
/*F********************************************************************************/
|
|
/*!
|
|
\Function CryptMontPointFinal
|
|
|
|
\Description
|
|
Copies our point data into an output buffer
|
|
|
|
\Input *pState - curve state
|
|
\Input *pPoint - point state or NULL to use curve result
|
|
\Input bSecret - is this the shared secret?
|
|
\Input *pBuffer - [out] the buffer we are copying into
|
|
\Input iBufSize - size of the buffer
|
|
|
|
\Output
|
|
int32_t - number of bytes encoded into the buffer
|
|
|
|
\Notes
|
|
These curves work in little endian so need to copy different functions
|
|
from our nist curves.
|
|
|
|
The bSecret is unused here but is left for compatibility with the other
|
|
curves' API.
|
|
|
|
\Version 04/11/2018 (eesponda)
|
|
*/
|
|
/********************************************************************************F*/
|
|
int32_t CryptMontPointFinal(const CryptMontT *pState, const CryptEccPointT *pPoint, uint8_t bSecret, uint8_t *pBuffer, int32_t iBufSize)
|
|
{
|
|
// if point not provided assume we are using the result
|
|
if ((pState != NULL) && (pPoint == NULL))
|
|
{
|
|
pPoint = &pState->Result;
|
|
}
|
|
|
|
CryptBnFinalLe(&pPoint->X, pBuffer, iBufSize);
|
|
return(CryptBnByteLen(&pPoint->X));
|
|
}
|