#include "precomp.h"
const UINT32 SymCryptEcpointFormatNumberofElements[] = {
0,
1,
2,
};
UINT32
SYMCRYPT_CALL
SymCryptSizeofEcpointEx(
UINT32 cbModElement,
UINT32 numOfCoordinates )
{
SYMCRYPT_ASSERT(numOfCoordinates > 0);
SYMCRYPT_ASSERT(numOfCoordinates <= SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH);
if( (numOfCoordinates == 0) || (numOfCoordinates > SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH) )
{
return 0;
}
return sizeof(SYMCRYPT_ECPOINT) + numOfCoordinates * cbModElement;
}
UINT32
SYMCRYPT_CALL
SymCryptSizeofEcpointFromCurve( PCSYMCRYPT_ECURVE pCurve )
{
return SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) );
}
PSYMCRYPT_ECPOINT
SYMCRYPT_CALL
SymCryptEcpointAllocate( _In_ PCSYMCRYPT_ECURVE pCurve )
{
PVOID p = NULL;
SIZE_T cb;
PSYMCRYPT_ECPOINT res = NULL;
cb = SymCryptSizeofEcpointFromCurve( pCurve );
if ( cb != 0 )
{
p = SymCryptCallbackAlloc( cb );
}
if ( p==NULL )
{
goto cleanup;
}
res = SymCryptEcpointCreate( p, cb, pCurve );
cleanup:
return res;
}
VOID
SYMCRYPT_CALL
SymCryptEcpointFree(
_In_ PCSYMCRYPT_ECURVE pCurve,
_Out_ PSYMCRYPT_ECPOINT poDst )
{
SYMCRYPT_CHECK_MAGIC( poDst );
SymCryptEcpointWipe( pCurve, poDst );
SymCryptCallbackFree( poDst );
}
PSYMCRYPT_ECPOINT
SYMCRYPT_CALL
SymCryptEcpointCreateEx(
_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,
SIZE_T cbBuffer,
PCSYMCRYPT_ECURVE pCurve,
UINT32 numOfCoordinates )
{
PSYMCRYPT_ECPOINT poPoint = NULL;
PSYMCRYPT_MODELEMENT pmTmp = NULL;
UINT32 cbModElement = pCurve->cbModElement;
PBYTE pbBufferEnd = pbBuffer + cbBuffer;
UNREFERENCED_PARAMETER( pbBufferEnd );
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofEcpointEx( pCurve->cbModElement, numOfCoordinates ) );
if ( cbBuffer == 0 || numOfCoordinates == 0 )
{
goto cleanup;
}
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
poPoint = (PSYMCRYPT_ECPOINT) pbBuffer;
pbBuffer += sizeof(SYMCRYPT_ECPOINT);
for (UINT32 i=0; i<numOfCoordinates; i++)
{
SYMCRYPT_ASSERT( pbBuffer + cbModElement <= pbBufferEnd );
pmTmp = SymCryptModElementCreate( pbBuffer, cbModElement, pCurve->FMod );
if ( pmTmp == NULL )
{
poPoint = NULL;
goto cleanup;
}
pbBuffer += cbModElement;
}
poPoint->normalized = FALSE;
poPoint->pCurve = pCurve;
SYMCRYPT_SET_MAGIC( poPoint );
cleanup:
return poPoint;
}
PSYMCRYPT_ECPOINT
SYMCRYPT_CALL
SymCryptEcpointCreate(
_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,
SIZE_T cbBuffer,
_In_ PCSYMCRYPT_ECURVE pCurve )
{
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
return SymCryptEcpointCreateEx( pbBuffer, cbBuffer, pCurve, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) );
}
PSYMCRYPT_ECPOINT
SYMCRYPT_CALL
SymCryptEcpointRetrieveHandle( _In_ PBYTE pbBuffer )
{
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
return (PSYMCRYPT_ECPOINT) pbBuffer;
}
VOID
SYMCRYPT_CALL
SymCryptEcpointWipe( _In_ PCSYMCRYPT_ECURVE pCurve, _Out_ PSYMCRYPT_ECPOINT poDst )
{
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
SymCryptWipe( poDst, SymCryptSizeofEcpointFromCurve( pCurve ) );
}
VOID
SymCryptEcpointCopy(
_In_ PCSYMCRYPT_ECURVE pCurve,
_In_ PCSYMCRYPT_ECPOINT poSrc,
_Out_ PSYMCRYPT_ECPOINT poDst )
{
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
if( poSrc != poDst )
{
poDst->normalized = poSrc->normalized;
memcpy(poDst + 1, poSrc + 1, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits * SYMCRYPT_FDEF_DIGIT_SIZE);
}
}
VOID
SymCryptEcpointMaskedCopy(
_In_ PCSYMCRYPT_ECURVE pCurve,
_In_ PCSYMCRYPT_ECPOINT poSrc,
_Out_ PSYMCRYPT_ECPOINT poDst,
UINT32 mask )
{
SYMCRYPT_ASSERT( (mask == 0) || (mask == 0xffffffff) );
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
poDst->normalized &= poSrc->normalized;
SymCryptFdefMaskedCopy((PCBYTE)poSrc + sizeof(SYMCRYPT_ECPOINT), (PBYTE)poDst + sizeof(SYMCRYPT_ECPOINT), SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits, mask );
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEcpointTransform(
_In_ PCSYMCRYPT_ECURVE pCurve,
_In_ PCSYMCRYPT_ECPOINT poSrc,
_Out_ PSYMCRYPT_ECPOINT poDst,
SYMCRYPT_ECPOINT_FORMAT eformat,
BOOLEAN setValue,
UINT32 flags,
_Out_writes_bytes_( cbScratch )
PBYTE pbScratch,
SIZE_T cbScratch )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
PSYMCRYPT_MODELEMENT peSrc = NULL;
PSYMCRYPT_MODELEMENT peDst = NULL;
PSYMCRYPT_MODELEMENT peX = NULL;
PSYMCRYPT_MODELEMENT peY = NULL;
SYMCRYPT_ECPOINT_COORDINATES coFrom = SYMCRYPT_ECPOINT_COORDINATES_INVALID;
SYMCRYPT_ECPOINT_COORDINATES coTo = SYMCRYPT_ECPOINT_COORDINATES_INVALID;
PSYMCRYPT_MODELEMENT peT[2] = { 0 };
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ),
SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->FModDigits )) +
2 * pCurve->cbModElement );
switch (eformat)
{
case (SYMCRYPT_ECPOINT_FORMAT_X):
coFrom = SYMCRYPT_ECPOINT_COORDINATES_SINGLE;
break;
case (SYMCRYPT_ECPOINT_FORMAT_XY):
coFrom = SYMCRYPT_ECPOINT_COORDINATES_AFFINE;
break;
default:
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
if (setValue)
{
coTo = pCurve->eCoordinates;
}
else
{
coTo = coFrom;
coFrom = pCurve->eCoordinates;
}
if ( coFrom == coTo )
{
SymCryptEcpointCopy( pCurve, poSrc, poDst );
}
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE)
{
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
{
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peX != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch );
}
else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
{
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peX != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
poDst->normalized = TRUE;
}
else
{
scError = SYMCRYPT_NOT_IMPLEMENTED;
goto cleanup;
}
}
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
{
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
)
{
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peX != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) )
{
peY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
SYMCRYPT_ASSERT( peY != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementCopy( pCurve->FMod, peY, peDst );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE)
{
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peX, peY, peDst, pbScratch, cbScratch );
}
poDst->normalized = TRUE;
}
else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
{
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
poDst->normalized = TRUE;
}
}
else
{
scError = SYMCRYPT_NOT_IMPLEMENTED;
goto cleanup;
}
}
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN)
{
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
{
for (UINT32 i=0; i<2; i++)
{
peT[i] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
SYMCRYPT_ASSERT( peT[i] != NULL);
pbScratch += pCurve->cbModElement;
}
cbScratch -= 2*pCurve->cbModElement;
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
{
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
goto cleanup;
}
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
SymCryptModMul( pCurve->FMod, peT[0], peT[0], peT[1], pbScratch, cbScratch );
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch );
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
{
SymCryptModMul( pCurve->FMod, peT[0], peT[1], peT[1], pbScratch, cbScratch );
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch );
}
}
else
{
scError = SYMCRYPT_NOT_IMPLEMENTED;
goto cleanup;
}
}
else if ( coFrom == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE )
{
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
{
peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
SYMCRYPT_ASSERT( peT[0] != NULL);
pbScratch += pCurve->cbModElement;
cbScratch -= 2*pCurve->cbModElement;
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
{
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
goto cleanup;
}
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch );
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
{
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch );
}
}
else
{
scError = SYMCRYPT_NOT_IMPLEMENTED;
goto cleanup;
}
}
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
{
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
{
peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
SYMCRYPT_ASSERT( peT[0] != NULL);
pbScratch += pCurve->cbModElement;
cbScratch -= pCurve->cbModElement;
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
{
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
goto cleanup;
}
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch );
if( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
SYMCRYPT_ASSERT( peSrc != NULL );
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch );
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
{
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
SYMCRYPT_ASSERT( peDst != NULL );
SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch );
}
}
}
else
{
scError = SYMCRYPT_NOT_IMPLEMENTED;
goto cleanup;
}
cleanup:
return scError;
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEcpointSetValue(
_In_ PCSYMCRYPT_ECURVE pCurve,
_In_reads_bytes_(cbSrc) PCBYTE pbSrc,
SIZE_T cbSrc,
SYMCRYPT_NUMBER_FORMAT nformat,
SYMCRYPT_ECPOINT_FORMAT eformat,
_Out_ PSYMCRYPT_ECPOINT poDst,
UINT32 flags,
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
SIZE_T cbScratch )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED;
PSYMCRYPT_MODELEMENT peTmp = NULL;
PSYMCRYPT_ECPOINT poLarge = NULL;
UINT32 cbLarge = 0;
PSYMCRYPT_INT piTemp = NULL;
UINT32 cbTemp = 0;
UINT32 publicKeyDigits = SymCryptEcurveDigitsofFieldElement( pCurve );
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
if ( cbSrc != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) )
{
scError = SYMCRYPT_BUFFER_TOO_SMALL;
goto cleanup;
}
cbSrc = cbSrc / SymCryptEcpointFormatNumberofElements[ eformat ];
cbTemp = SymCryptSizeofIntFromDigits( publicKeyDigits );
SYMCRYPT_ASSERT( cbScratch > cbTemp );
piTemp = SymCryptIntCreate( pbScratch, cbTemp, publicKeyDigits );
for ( UINT32 i = 0; i < SymCryptEcpointFormatNumberofElements[eformat]; i++ )
{
scError = SymCryptIntSetValue( pbSrc + i * cbSrc, cbSrc, nformat, piTemp );
if (scError != SYMCRYPT_NO_ERROR)
{
goto cleanup;
}
if ( !SymCryptIntIsLessThan( piTemp, SymCryptIntFromModulus( pCurve->FMod ) ) )
{
scError = SYMCRYPT_INVALID_ARGUMENT;
goto cleanup;
}
}
cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
SYMCRYPT_ASSERT( cbScratch > cbLarge );
poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
if ( poLarge == NULL )
{
scError = SYMCRYPT_INVALID_BLOB;
goto cleanup;
}
for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++)
{
peTmp = (PSYMCRYPT_MODELEMENT)((PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i ));
if ( peTmp == NULL )
{
scError = SYMCRYPT_INVALID_BLOB;
goto cleanup;
}
scError = SymCryptModElementSetValue(
pbSrc,
cbSrc,
nformat,
pCurve->FMod,
peTmp,
pbScratch + cbLarge,
cbScratch - cbLarge );
if ( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
pbSrc += cbSrc;
}
scError = SymCryptEcpointTransform( pCurve, poLarge, poDst, eformat, TRUE, flags, pbScratch + cbLarge, cbScratch - cbLarge);
cleanup:
return scError;
}
SYMCRYPT_ERROR
SYMCRYPT_CALL
SymCryptEcpointGetValue(
_In_ PCSYMCRYPT_ECURVE pCurve,
_In_ PCSYMCRYPT_ECPOINT poSrc,
SYMCRYPT_NUMBER_FORMAT nformat,
SYMCRYPT_ECPOINT_FORMAT eformat,
_Out_writes_bytes_(cbDst) PBYTE pbDst,
SIZE_T cbDst,
UINT32 flags,
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
SIZE_T cbScratch )
{
SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED;
PSYMCRYPT_MODELEMENT peTmp = NULL;
PSYMCRYPT_ECPOINT poLarge = NULL;
UINT32 cbLarge = 0;
SIZE_T cbDstElem;
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
if ( cbDst != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) )
{
scError = SYMCRYPT_BUFFER_TOO_SMALL;
goto cleanup;
}
SYMCRYPT_ASSERT( SymCryptEcpointFormatNumberofElements[ eformat ] > 0 );
cbDstElem = cbDst / SymCryptEcpointFormatNumberofElements[ eformat ];
cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
SYMCRYPT_ASSERT( cbScratch > cbLarge );
poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
if ( poLarge == NULL )
{
scError = SYMCRYPT_INVALID_BLOB;
goto cleanup;
}
scError = SymCryptEcpointTransform( pCurve, poSrc, poLarge, eformat, FALSE, flags, pbScratch + cbLarge, cbScratch - cbLarge);
if (scError != SYMCRYPT_NO_ERROR)
{
goto cleanup;
}
for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++)
{
SYMCRYPT_ASSERT( cbDst >= cbDstElem );
peTmp = (PSYMCRYPT_MODELEMENT)( (PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i ) );
if ( peTmp == NULL )
{
scError = SYMCRYPT_INVALID_BLOB;
goto cleanup;
}
scError = SymCryptModElementGetValue(
pCurve->FMod,
peTmp,
pbDst,
cbDstElem,
nformat,
pbScratch + cbLarge,
cbScratch - cbLarge );
if ( scError != SYMCRYPT_NO_ERROR )
{
goto cleanup;
}
pbDst += cbDstElem;
cbDst -= cbDstElem;
}
cleanup:
return scError;
}