ReactOS 0.4.17-dev-1005-g171e1de
eckey.c File Reference
#include "precomp.h"
Include dependency graph for eckey.c:

Go to the source code of this file.

Macros

#define SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION   (0x1)
 
#define SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES   (1000)
 

Functions

PSYMCRYPT_ECKEY SYMCRYPT_CALL SymCryptEckeyAllocate (_In_ PCSYMCRYPT_ECURVE pCurve)
 
VOID SYMCRYPT_CALL SymCryptEckeyFree (_Out_ PSYMCRYPT_ECKEY pkObj)
 
UINT32 SYMCRYPT_CALL SymCryptSizeofEckeyFromCurve (_In_ PCSYMCRYPT_ECURVE pCurve)
 
PSYMCRYPT_ECKEY SYMCRYPT_CALL SymCryptEckeyCreate (_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, PCSYMCRYPT_ECURVE pCurve)
 
VOID SYMCRYPT_CALL SymCryptEckeyWipePrivateState (_Inout_ PSYMCRYPT_ECKEY pkEckey)
 
VOID SYMCRYPT_CALL SymCryptEckeyWipe (_Out_ PSYMCRYPT_ECKEY pkDst)
 
VOID SymCryptEckeyCopy (_In_ PCSYMCRYPT_ECKEY pkSrc, _Out_ PSYMCRYPT_ECKEY pkDst)
 
UINT32 SYMCRYPT_CALL SymCryptEckeySizeofPublicKey (_In_ PCSYMCRYPT_ECKEY pkEckey, _In_ SYMCRYPT_ECPOINT_FORMAT ecPointFormat)
 
UINT32 SYMCRYPT_CALL SymCryptEckeySizeofPrivateKey (_In_ PCSYMCRYPT_ECKEY pkEckey)
 
BOOLEAN SYMCRYPT_CALL SymCryptEckeyHasPrivateKey (_In_ PCSYMCRYPT_ECKEY pkEckey)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyPerformPublicKeyValidation (_In_ PCSYMCRYPT_ECKEY pEckey, _In_ UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeySetValue (_In_reads_bytes_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey, _In_reads_bytes_(cbPublicKey) PCBYTE pbPublicKey, SIZE_T cbPublicKey, SYMCRYPT_NUMBER_FORMAT numFormat, SYMCRYPT_ECPOINT_FORMAT ecPointFormat, UINT32 flags, _Inout_ PSYMCRYPT_ECKEY pEckey)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyGetValue (_In_ PCSYMCRYPT_ECKEY pEckey, _Out_writes_bytes_(cbPrivateKey) PBYTE pbPrivateKey, SIZE_T cbPrivateKey, _Out_writes_bytes_(cbPublicKey) PBYTE pbPublicKey, SIZE_T cbPublicKey, SYMCRYPT_NUMBER_FORMAT numFormat, SYMCRYPT_ECPOINT_FORMAT ecPointFormat, UINT32 flags)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeySetRandom (_In_ UINT32 flags, _Inout_ PSYMCRYPT_ECKEY pEckey)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyExtendKeyUsage (_Inout_ PSYMCRYPT_ECKEY pEckey, UINT32 flags)
 

Macro Definition Documentation

◆ SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES

#define SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES   (1000)

Definition at line 729 of file eckey.c.

◆ SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION

#define SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION   (0x1)

Definition at line 176 of file eckey.c.

Function Documentation

◆ SymCryptEckeyAllocate()

PSYMCRYPT_ECKEY SYMCRYPT_CALL SymCryptEckeyAllocate ( _In_ PCSYMCRYPT_ECURVE  pCurve)

Definition at line 12 of file eckey.c.

13{
14 PVOID p;
15 SIZE_T cb;
17
19
21
22 if ( p==NULL )
23 {
24 goto cleanup;
25 }
26
28
30 return res;
31}
#define NULL
Definition: types.h:112
static void cleanup(void)
Definition: main.c:1335
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
PSYMCRYPT_ECKEY SYMCRYPT_CALL SymCryptEckeyCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, PCSYMCRYPT_ECURVE pCurve)
Definition: eckey.c:58
UINT32 SYMCRYPT_CALL SymCryptSizeofEckeyFromCurve(_In_ PCSYMCRYPT_ECURVE pCurve)
Definition: eckey.c:44
GLuint res
Definition: glext.h:9613
GLfloat GLfloat p
Definition: glext.h:8902
void *SYMCRYPT_CALL SymCryptCallbackAlloc(SIZE_T size)
Definition: implglue.c:37
PCSYMCRYPT_ECURVE pCurve
SYMCRYPT_ECKEY * PSYMCRYPT_ECKEY
ULONG_PTR SIZE_T
Definition: typedefs.h:80

◆ SymCryptEckeyCopy()

VOID SymCryptEckeyCopy ( _In_ PCSYMCRYPT_ECKEY  pkSrc,
_Out_ PSYMCRYPT_ECKEY  pkDst 
)

Definition at line 122 of file eckey.c.

125{
126 //
127 // in-place copy is somewhat common...
128 //
129 if( pkSrc != pkDst )
130 {
131 // Copy the fAlgorithmInfo flags
132 pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
133
134 // Copy the hasPrivateKey flag
135 pkDst->hasPrivateKey = pkSrc->hasPrivateKey;
136
137 // Copy the public key
138 SymCryptEcpointCopy( pkSrc->pCurve, pkSrc->poPublicKey, pkDst->poPublicKey );
139
140 // Copy the private key
141 SymCryptIntCopy( pkSrc->piPrivateKey, pkDst->piPrivateKey );
142 }
143}
VOID SYMCRYPT_CALL SymCryptIntCopy(_In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:161
VOID SymCryptEcpointCopy(_In_ PCSYMCRYPT_ECURVE pCurve, _In_ PCSYMCRYPT_ECPOINT poSrc, _Out_ PSYMCRYPT_ECPOINT poDst)
Definition: ecpoint.c:173

◆ SymCryptEckeyCreate()

PSYMCRYPT_ECKEY SYMCRYPT_CALL SymCryptEckeyCreate ( _Out_writes_bytes_(cbBuffer) PBYTE  pbBuffer,
SIZE_T  cbBuffer,
PCSYMCRYPT_ECURVE  pCurve 
)

Definition at line 58 of file eckey.c.

62{
63 PSYMCRYPT_ECKEY pkObj = NULL;
65
67 SIZE_T cbPrivateKey = SymCryptSizeofIntFromDigits( privateKeyDigits );
68
69 UNREFERENCED_PARAMETER( cbBuffer ); // only referenced in ASSERTs...
70
73
75 cbPublicKey +
76 cbPrivateKey );
77
79
80 pkObj = (PSYMCRYPT_ECKEY) pbBuffer;
81
82 pkObj->fAlgorithmInfo = 0;
83 pkObj->hasPrivateKey = FALSE;
84 pkObj->pCurve = pCurve;
85
86 pkObj->poPublicKey = SymCryptEcpointCreate(
87 pbBuffer + sizeof(SYMCRYPT_ECKEY),
88 cbPublicKey,
89 pCurve );
90 SYMCRYPT_ASSERT( pkObj->poPublicKey != NULL );
91
92 pkObj->piPrivateKey = SymCryptIntCreate(
93 pbBuffer + sizeof(SYMCRYPT_ECKEY) + cbPublicKey,
94 cbPrivateKey,
95 privateKeyDigits );
96 SYMCRYPT_ASSERT( pkObj->piPrivateKey );
97
98 // Setting the magic
99 SYMCRYPT_SET_MAGIC( pkObj );
100
101 return pkObj;
102}
#define FALSE
Definition: types.h:117
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define SYMCRYPT_ASSERT_ASYM_ALIGNED(_p)
Definition: sc_lib.h:1912
SIZE_T cbBuffer
Definition: sc_lib_mldsa.h:405
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
SYMCRYPT_MAGIC_FIELD SYMCRYPT_ECKEY
#define SYMCRYPT_SET_MAGIC(p)
PSYMCRYPT_ECPOINT SYMCRYPT_CALL SymCryptEcpointCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, _In_ PCSYMCRYPT_ECURVE pCurve)
Definition: ecpoint.c:142
UINT32 SYMCRYPT_CALL SymCryptSizeofEcpointFromCurve(PCSYMCRYPT_ECURVE pCurve)
Definition: ecpoint.c:41
UINT32 SYMCRYPT_CALL SymCryptSizeofIntFromDigits(UINT32 nDigits)
Definition: a_dispatch.c:134
UINT32 SYMCRYPT_CALL SymCryptEcurveDigitsofScalarMultiplier(_In_ PCSYMCRYPT_ECURVE pCurve)
Definition: ecurve.c:710
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nDigits)
Definition: a_dispatch.c:141
uint32_t UINT32
Definition: typedefs.h:59

Referenced by SymCryptEckeyAllocate().

◆ SymCryptEckeyExtendKeyUsage()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyExtendKeyUsage ( _Inout_ PSYMCRYPT_ECKEY  pEckey,
UINT32  flags 
)

Definition at line 976 of file eckey.c.

979{
980 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
981
982 // Ensure caller has specified what algorithm(s) the key will be used with
984
985 if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
986 ( ( flags & algorithmFlags ) == 0) )
987 {
988 scError = SYMCRYPT_INVALID_ARGUMENT;
989 goto cleanup;
990 }
991
992 pEckey->fAlgorithmInfo |= flags;
993
994cleanup:
995 return scError;
996}
GLbitfield flags
Definition: glext.h:7161
#define SYMCRYPT_FLAG_ECKEY_ECDSA
Definition: symcrypt.h:7595
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_FLAG_ECKEY_ECDH
Definition: symcrypt.h:7596

◆ SymCryptEckeyFree()

VOID SYMCRYPT_CALL SymCryptEckeyFree ( _Out_ PSYMCRYPT_ECKEY  pkObj)

Definition at line 35 of file eckey.c.

36{
37 SYMCRYPT_CHECK_MAGIC( pkObj );
38 SymCryptEckeyWipe( pkObj );
39 SymCryptCallbackFree( pkObj );
40}
VOID SYMCRYPT_CALL SymCryptEckeyWipe(_Out_ PSYMCRYPT_ECKEY pkDst)
Definition: eckey.c:115
void SYMCRYPT_CALL SymCryptCallbackFree(void *ptr)
Definition: implglue.c:42
#define SYMCRYPT_CHECK_MAGIC(p)

◆ SymCryptEckeyGetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyGetValue ( _In_ PCSYMCRYPT_ECKEY  pEckey,
_Out_writes_bytes_(cbPrivateKey) PBYTE  pbPrivateKey,
SIZE_T  cbPrivateKey,
_Out_writes_bytes_(cbPublicKey) PBYTE  pbPublicKey,
SIZE_T  cbPublicKey,
SYMCRYPT_NUMBER_FORMAT  numFormat,
SYMCRYPT_ECPOINT_FORMAT  ecPointFormat,
UINT32  flags 
)

Definition at line 581 of file eckey.c.

592{
593 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
594 PBYTE pbScratch = NULL;
595 UINT32 cbScratch = 0;
596 PBYTE pbScratchInternal = NULL;
597 UINT32 cbScratchInternal = 0;
598
599 PCSYMCRYPT_ECURVE pCurve = pEckey->pCurve;
600
601 PSYMCRYPT_INT piTmpInteger = NULL;
602 UINT32 cbTmpInteger = 0;
603 PSYMCRYPT_MODELEMENT peTmpModElement = NULL;
604 UINT32 cbTmpModElement = pCurve->cbModElement;
605
607
608 SYMCRYPT_ASSERT( (cbPrivateKey==0) || (cbPrivateKey == SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve )) );
609 SYMCRYPT_ASSERT( (cbPublicKey==0) || (cbPublicKey == SymCryptEckeySizeofPublicKey( pEckey, ecPointFormat)) );
610
611 // Make sure we only specify the correct flags
612 if (flags != 0)
613 {
614 scError = SYMCRYPT_INVALID_ARGUMENT;
615 goto cleanup;
616 }
617
618 // Allocate scratch space
620 pbScratch = SymCryptCallbackAlloc( cbScratch );
621 if ( pbScratch == NULL )
622 {
623 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
624 goto cleanup;
625 }
626
627 pbScratchInternal = pbScratch;
628 cbScratchInternal = cbScratch;
629
630 // Allocate the integer
631 cbTmpInteger = SymCryptSizeofIntFromDigits( privateKeyDigits );
632 piTmpInteger = SymCryptIntCreate( pbScratchInternal, cbTmpInteger, privateKeyDigits );
633 SYMCRYPT_ASSERT( piTmpInteger != NULL );
634
635 pbScratchInternal += cbTmpInteger;
636 cbScratchInternal -= cbTmpInteger;
637
638 // Allocate the modelement
639 peTmpModElement = SymCryptModElementCreate( pbScratchInternal, cbTmpModElement, pCurve->GOrd );
640 SYMCRYPT_ASSERT( peTmpModElement != NULL );
641
642 pbScratchInternal += cbTmpModElement;
643 cbScratchInternal -= cbTmpModElement;
644
645 if ((cbPrivateKey == 0) && (cbPublicKey == 0))
646 {
647 scError = SYMCRYPT_INVALID_ARGUMENT;
648 goto cleanup;
649 }
650
651 if (cbPrivateKey != 0)
652 {
653 if (!pEckey->hasPrivateKey)
654 {
655 scError = SYMCRYPT_INVALID_BLOB;
656 goto cleanup;
657 }
658
659 // If this keypair may be used in ECDSA, and does not have the no FIPS flag, run the PCT if
660 // it has not already been run
661 if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
662 ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
663 {
666 pEckey,
668 }
669
670 // Copy the key into the temporary integer
671 SymCryptIntCopy( pEckey->piPrivateKey, piTmpInteger );
672
673 // Convert the "DivH" format into the external format
674 if (pCurve->coFactorPower>0)
675 {
676 // For the "Canonical" format: Multiply the integer by h
677 // and then take the result modulo GOrd
678 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
679 {
680 SymCryptIntMulPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
682 piTmpInteger,
684 NULL,
685 piTmpInteger,
686 pbScratchInternal,
687 cbScratchInternal );
688 }
689
690 // For the "TimesH" format: Multiply the integer by h again by shifting
691 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
692 {
693 SymCryptIntMulPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
694 }
695 }
696
697 scError = SymCryptIntGetValue( piTmpInteger, pbPrivateKey, cbPrivateKey, numFormat );
698 if (scError != SYMCRYPT_NO_ERROR)
699 {
700 goto cleanup;
701 }
702 }
703
704 if (cbPublicKey != 0)
705 {
706 scError = SymCryptEcpointGetValue(
707 pCurve,
708 pEckey->poPublicKey,
709 numFormat,
710 ecPointFormat,
711 pbPublicKey,
712 cbPublicKey,
714 pbScratch,
715 cbScratch );
716 }
717
718cleanup:
719
720 if ( pbScratch != NULL )
721 {
722 SymCryptWipe( pbScratch, cbScratch );
723 SymCryptCallbackFree( pbScratch );
724 }
725
726 return scError;
727}
UINT32 SYMCRYPT_CALL SymCryptEckeySizeofPublicKey(_In_ PCSYMCRYPT_ECKEY pkEckey, _In_ SYMCRYPT_ECPOINT_FORMAT ecPointFormat)
Definition: eckey.c:147
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_RUN_KEY_GEN_PCT(KeySelftestFunction, Key, KeySelftestFlag)
Definition: sc_lib.h:3699
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEcDsaPct(PCSYMCRYPT_ECKEY pkEckey)
UINT32 UINT32 UINT32 UINT32 cbScratch
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
UINT32 SYMCRYPT_CALL SymCryptEcurveSizeofScalarMultiplier(_In_ PCSYMCRYPT_ECURVE pCurve)
Definition: ecurve.c:696
@ SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH
Definition: symcrypt.h:7132
@ SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL
Definition: symcrypt.h:7130
#define SYMCRYPT_FLAG_KEY_NO_FIPS
Definition: symcrypt.h:7579
SYMCRYPT_MODELEMENT * PSYMCRYPT_MODELEMENT
#define SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_ECKEY_ECURVE_OPERATIONS(_pCurve)
#define SYMCRYPT_PCT_ECDSA
SYMCRYPT_INT * PSYMCRYPT_INT
const SYMCRYPT_ECURVE * PCSYMCRYPT_ECURVE
PSYMCRYPT_DIVISOR SYMCRYPT_CALL SymCryptDivisorFromModulus(_In_ PSYMCRYPT_MODULUS pmSrc)
Definition: a_dispatch.c:703
PSYMCRYPT_MODELEMENT SYMCRYPT_CALL SymCryptModElementCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, _In_ PCSYMCRYPT_MODULUS pmMod)
Definition: a_dispatch.c:665
VOID SYMCRYPT_CALL SymCryptIntMulPow2(_In_ PCSYMCRYPT_INT piSrc, SIZE_T exp, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:354
VOID SYMCRYPT_CALL SymCryptIntDivMod(_In_ PCSYMCRYPT_INT piSrc, _In_ PCSYMCRYPT_DIVISOR pdDivisor, _Out_opt_ PSYMCRYPT_INT piQuotient, _Out_opt_ PSYMCRYPT_INT piRemainder, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:573
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptIntGetValue(_In_ PCSYMCRYPT_INT piSrc, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst, SYMCRYPT_NUMBER_FORMAT format)
Definition: a_dispatch.c:259
#define SYMCRYPT_FLAG_DATA_PUBLIC
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)
Definition: ecpoint.c:705

◆ SymCryptEckeyHasPrivateKey()

BOOLEAN SYMCRYPT_CALL SymCryptEckeyHasPrivateKey ( _In_ PCSYMCRYPT_ECKEY  pkEckey)

Definition at line 171 of file eckey.c.

172{
173 return pkEckey->hasPrivateKey;
174}

◆ SymCryptEckeyPerformPublicKeyValidation()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyPerformPublicKeyValidation ( _In_ PCSYMCRYPT_ECKEY  pEckey,
_In_ UINT32  flags,
_Out_writes_bytes_(cbScratch) PBYTE  pbScratch,
SIZE_T  cbScratch 
)

Definition at line 180 of file eckey.c.

185{
186 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
187
188 PCSYMCRYPT_ECURVE pCurve = pEckey->pCurve;
189
190 PSYMCRYPT_ECPOINT poNPub = NULL;
192
193 // This is an excessive amount of space to require, but all callers can currently provide it, and it's easy to phrase
195
196 SYMCRYPT_ASSERT( cbScratch >= cbNPub );
197
198 // Check if Public key is O
199 if ( SymCryptEcpointIsZero( pCurve, pEckey->poPublicKey, pbScratch, cbScratch ) )
200 {
201 return SYMCRYPT_INVALID_ARGUMENT;
202 }
203
204 // Public key is represented by Modelements of the underlying finite field for the curve
205 // If we have reached this point we have either:
206 // Constructed the Public key to have coordinates in the field (Generate case), or
207 // Verified the Public key has coordinates in the field (SetValue case)
208
209 // Check that Public key is on the curve
210 // Skip check for Montgomery curves as we do not have an EcpointOnCurve function for them
212 !SymCryptEcpointOnCurve( pCurve, pEckey->poPublicKey, pbScratch, cbScratch ) )
213 {
214 return SYMCRYPT_INVALID_ARGUMENT;
215 }
216
217 // Perform validation that Public key is in a subgroup of order GOrd.
219 {
220 if ( SymCryptIntIsEqualUint32( pCurve->H, 1 ) )
221 {
222 // If cofactor is 1 then to validate that Public key has order GOrd
223 // it is sufficient to validate Public key is on the curve
224 // We just performed this check - so we are done.
225 }
226 else
227 {
228 // Ensure GOrd*(Public key) == O
229 poNPub = SymCryptEcpointCreate( pbScratch, cbNPub, pCurve );
230 pbScratch += cbNPub;
231 cbScratch -= cbNPub;
232
233 SYMCRYPT_ASSERT( poNPub != NULL );
234
235 // Do the multiplication
236 scError = SymCryptEcpointScalarMul(
237 pCurve,
239 pEckey->poPublicKey,
240 0, // Do not multiply by cofactor!
241 poNPub,
242 pbScratch,
243 cbScratch );
244 if ( scError != SYMCRYPT_NO_ERROR )
245 {
246 return scError;
247 }
248
249 if ( !SymCryptEcpointIsZero( pCurve, poNPub, pbScratch, cbScratch ) )
250 {
251 return SYMCRYPT_INVALID_ARGUMENT;
252 }
253 }
254 }
255
256 return SYMCRYPT_NO_ERROR;
257}
#define SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION
Definition: eckey.c:176
#define SYMCRYPT_CURVE_IS_MONTGOMERY_TYPE(_pCurve)
SYMCRYPT_ECPOINT * PSYMCRYPT_ECPOINT
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEcpointScalarMul(_In_ PCSYMCRYPT_ECURVE pCurve, _In_ PCSYMCRYPT_INT piScalar, _In_opt_ PCSYMCRYPT_ECPOINT poSrc, UINT32 flags, _Out_ PSYMCRYPT_ECPOINT poDst, _Out_writes_bytes_opt_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: ec_dispatch.c:262
UINT32 SYMCRYPT_CALL SymCryptEcpointIsZero(_In_ PCSYMCRYPT_ECURVE pCurve, _In_ PCSYMCRYPT_ECPOINT poSrc, _Out_writes_bytes_opt_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: ec_dispatch.c:176
UINT32 SYMCRYPT_CALL SymCryptEcpointOnCurve(_In_ PCSYMCRYPT_ECURVE pCurve, _In_ PCSYMCRYPT_ECPOINT poSrc, _Out_writes_bytes_opt_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: ec_dispatch.c:189
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntFromModulus(_In_ PSYMCRYPT_MODULUS pmSrc)
Definition: a_dispatch.c:720
UINT32 SYMCRYPT_CALL SymCryptIntIsEqualUint32(_In_ PCSYMCRYPT_INT piSrc1, _In_ UINT32 u32Src2)
Definition: a_dispatch.c:424

Referenced by SymCryptEckeySetRandom(), and SymCryptEckeySetValue().

◆ SymCryptEckeySetRandom()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeySetRandom ( _In_ UINT32  flags,
_Inout_ PSYMCRYPT_ECKEY  pEckey 
)

Definition at line 733 of file eckey.c.

736{
737 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
738 PBYTE pbScratch = NULL;
739 UINT32 cbScratch = 0;
740 PBYTE pbScratchInternal = NULL;
741 UINT32 cbScratchInternal = 0;
742
743 PCSYMCRYPT_ECURVE pCurve = pEckey->pCurve;
744
745 PSYMCRYPT_ECPOINT poTmp = NULL;
746 UINT32 cbTmp = 0;
747
749
750 PSYMCRYPT_MODELEMENT peScalar = NULL;
751 PSYMCRYPT_INT piScalar = NULL;
752 UINT32 cbScalar = 0;
753
754 UINT32 highBitRestrictionPosition = pCurve->HighBitRestrictionPosition;
755
756 // Ensure caller has specified what algorithm(s) the key will be used with
758 // Make sure only allowed flags are specified
759 UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
760
761 if ( ( ( flags & ~allowedFlags ) != 0 ) ||
762 ( ( flags & algorithmFlags ) == 0 ) )
763 {
764 scError = SYMCRYPT_INVALID_ARGUMENT;
765 goto cleanup;
766 }
767
768 //
769 // From symcrypt_internal.h we have:
770 // - sizeof results are upper bounded by 2^19
771 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
772 // Thus the following calculation does not overflow cbScratch.
773 //
775 pbScratch = SymCryptCallbackAlloc( cbScratch );
776 if ( pbScratch == NULL )
777 {
778 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
779 goto cleanup;
780 }
781
782 // Allocating temporaries
783 pbScratchInternal = pbScratch;
784 cbScratchInternal = cbScratch;
785
786 peScalar = SymCryptModElementCreate( pbScratchInternal, pCurve->cbModElement, pCurve->GOrd );
787 SYMCRYPT_ASSERT( peScalar != NULL );
788
789 pbScratchInternal += pCurve->cbModElement;
790 cbScratchInternal -= pCurve->cbModElement;
791
793 piScalar = SymCryptIntCreate( pbScratchInternal, cbScalar, SymCryptEcurveDigitsofScalarMultiplier(pCurve) );
794
795 pbScratchInternal += cbScalar;
796 cbScratchInternal -= cbScalar;
797
798 // Shift the high bit position if the format is "TIMESH"
799 // Note: Do not actually multiply the integer as we will check if it is
800 // less than the group order
801 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
802 {
803 highBitRestrictionPosition -= pCurve->coFactorPower;
804 }
805
806 // Main loop
807 do
808 {
809 // We perform Private key range validation by construction
810 // Setting a random mod element in the [1, SubgroupOrder-1] set
811 // This will be the "DivH" format of the private key. This means
812 // that PublicKey = h * PrivateKey * G
814 pCurve->GOrd,
815 peScalar,
817 pbScratchInternal,
818 cbScratchInternal );
819
820 // Converting to "canonical" format
821 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
822 {
823 for (UINT32 i=0; i<pCurve->coFactorPower; i++)
824 {
825 SymCryptModAdd( pCurve->GOrd, peScalar, peScalar, peScalar, pbScratchInternal, cbScratchInternal );
826 }
827 }
828
829 // Set the temporary scalar to verify the format
830 SymCryptModElementToInt( pCurve->GOrd, peScalar, piScalar, pbScratchInternal, cbScratchInternal );
831
832 if (pCurve->HighBitRestrictionNumOfBits > 0)
833 {
834 // Set the desired bits
836 piScalar,
837 pCurve->HighBitRestrictionValue,
838 highBitRestrictionPosition,
839 pCurve->HighBitRestrictionNumOfBits );
840
841 // Make sure we didn't exceed the group order
843 piScalar,
845 {
846 break;
847 }
848 }
849 else
850 {
851 // No high bit restriction was specified
852 break;
853 }
854
855 cntr--;
856 }
857 while (cntr>0);
858
859 if (cntr <= 0)
860 {
861 scError = SYMCRYPT_INVALID_ARGUMENT;
862 goto cleanup;
863 }
864
865 // Here piScalar has a private key that satisfies the restriction(s)
866 // Move it to the modelement
867 SymCryptIntToModElement( piScalar, pCurve->GOrd, peScalar, pbScratchInternal, cbScratchInternal );
868
869 // Convert the private key back to "DIVH" format
870 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
871 {
872 SymCryptModDivPow2( pCurve->GOrd, peScalar, pCurve->coFactorPower, peScalar, pbScratchInternal, cbScratchInternal );
873 }
874
875 // Set the private key
876 SymCryptModElementToInt( pCurve->GOrd, peScalar, pEckey->piPrivateKey, pbScratchInternal, cbScratchInternal );
877
878 // Do the multiplication (pass over the entire scratch space as it is not needed anymore)
879 scError = SymCryptEcpointScalarMul(
880 pCurve,
881 pEckey->piPrivateKey,
882 NULL,
884 pEckey->poPublicKey,
885 pbScratch,
886 cbScratch );
887 if ( scError != SYMCRYPT_NO_ERROR )
888 {
889 goto cleanup;
890 }
891
892 // Perform range and public key order validation on generated Public key.
893 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
894 {
895 // Perform Public key validation.
896 // Always perform range validation and validation that Public key is in subgroup of order GOrd
898 pEckey,
900 pbScratch,
901 cbScratch );
902 if ( scError != SYMCRYPT_NO_ERROR )
903 {
904 goto cleanup;
905 }
906 }
907
908 pEckey->hasPrivateKey = TRUE;
909
910 pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
911
912 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
913 {
914 if( ( flags & SYMCRYPT_FLAG_ECKEY_ECDSA ) != 0 )
915 {
916 // Ensure ECDSA algorithm selftest is run before first use of ECDSA algorithm
920 }
921
922 if( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
923 {
924 // Ensure we have run the algorithm selftest at least once.
928
929 // Run PCT eagerly so it only needs to be defined here
930 // The important case for performance is ECDH key generation
931
932 // ECDH PCT per SP80056a-rev3 5.6.2.1.4 b)
933 // Recompute the public key from the private key
934 // Option a) appears to be explicitly overruled by 140-3 IG
935 pbScratchInternal = pbScratch;
936 cbScratchInternal = cbScratch;
937
939 poTmp = SymCryptEcpointCreate( pbScratchInternal, cbTmp, pCurve );
940 pbScratchInternal += cbTmp;
941 cbScratchInternal -= cbTmp;
942
943 SYMCRYPT_ASSERT( poTmp != NULL );
944
945 // Always multiply by the cofactor since the internal format is "DIVH"
946 scError = SymCryptEcpointScalarMul(
947 pCurve,
948 pEckey->piPrivateKey,
949 NULL,
951 poTmp,
952 pbScratchInternal,
953 cbScratchInternal );
954 if ( scError != SYMCRYPT_NO_ERROR )
955 {
956 goto cleanup;
957 }
958
959 SYMCRYPT_FIPS_ASSERT( SymCryptEcpointIsEqual( pCurve, poTmp, pEckey->poPublicKey, 0, pbScratchInternal, cbScratchInternal ) );
960 }
961 }
962
963cleanup:
964
965 if ( pbScratch != NULL )
966 {
967 SymCryptWipe( pbScratch, cbScratch );
968 SymCryptCallbackFree( pbScratch );
969 }
970
971 return scError;
972}
#define TRUE
Definition: types.h:120
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeyPerformPublicKeyValidation(_In_ PCSYMCRYPT_ECKEY pEckey, _In_ UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: eckey.c:180
#define SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES
Definition: eckey.c:729
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define SYMCRYPT_RUN_SELFTEST_ONCE(AlgorithmSelftestFunction, AlgorithmSelftestFlag)
Definition: sc_lib.h:3686
VOID SYMCRYPT_CALL SymCryptEcDsaSelftest(void)
VOID SYMCRYPT_CALL SymCryptEcDhSecretAgreementSelftest(void)
@ SYMCRYPT_SELFTEST_ALGORITHM_ECDH
@ SYMCRYPT_SELFTEST_ALGORITHM_ECDSA
#define SYMCRYPT_FIPS_ASSERT(x)
UINT32 SYMCRYPT_CALL SymCryptIntIsLessThan(_In_ PCSYMCRYPT_INT piSrc1, _In_ PCSYMCRYPT_INT piSrc2)
Definition: a_dispatch.c:442
VOID SYMCRYPT_CALL SymCryptIntToModElement(_In_ PCSYMCRYPT_INT piSrc, _In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:749
VOID SYMCRYPT_CALL SymCryptIntSetBits(_In_ PSYMCRYPT_INT piDst, UINT32 value, UINT32 iBit, UINT32 nBits)
Definition: a_dispatch.c:413
VOID SYMCRYPT_CALL SymCryptModSetRandom(_In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:993
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE
VOID SYMCRYPT_CALL SymCryptModAdd(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc1, _In_ PCSYMCRYPT_MODELEMENT peSrc2, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:838
VOID SYMCRYPT_CALL SymCryptModElementToInt(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, _Out_ PSYMCRYPT_INT piDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:762
UINT32 SYMCRYPT_CALL SymCryptEcpointIsEqual(_In_ PCSYMCRYPT_ECURVE pCurve, _In_ PCSYMCRYPT_ECPOINT poSrc1, _In_ PCSYMCRYPT_ECPOINT poSrc2, UINT32 flags, _Out_writes_bytes_opt_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: ec_dispatch.c:161
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE
#define SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL
VOID SYMCRYPT_CALL SymCryptModDivPow2(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, UINT32 exp, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:934
int32_t INT32
Definition: typedefs.h:58

◆ SymCryptEckeySetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptEckeySetValue ( _In_reads_bytes_(cbPrivateKey) PCBYTE  pbPrivateKey,
SIZE_T  cbPrivateKey,
_In_reads_bytes_(cbPublicKey) PCBYTE  pbPublicKey,
SIZE_T  cbPublicKey,
SYMCRYPT_NUMBER_FORMAT  numFormat,
SYMCRYPT_ECPOINT_FORMAT  ecPointFormat,
UINT32  flags,
_Inout_ PSYMCRYPT_ECKEY  pEckey 
)

Definition at line 261 of file eckey.c.

272{
273 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
274 PBYTE pbScratch = NULL;
275 UINT32 cbScratch = 0;
276 PBYTE pbScratchInternal = NULL;
277 UINT32 cbScratchInternal = 0;
278
279 PCSYMCRYPT_ECURVE pCurve = pEckey->pCurve;
280
281 PSYMCRYPT_ECPOINT poTmp = NULL;
282 UINT32 cbTmp = 0;
283
284 PSYMCRYPT_INT piTmpInteger = NULL;
285 UINT32 cbTmpInteger = 0;
286 PSYMCRYPT_MODELEMENT peTmpModElement = NULL;
287 UINT32 cbTmpModElement = pCurve->cbModElement;
288
290
292
293 // Ensure caller has specified what algorithm(s) the key will be used with
295 // Make sure only allowed flags are specified
297
298 if ( ( ( flags & ~allowedFlags ) != 0 ) ||
299 ( ( flags & algorithmFlags ) == 0 ) )
300 {
301 scError = SYMCRYPT_INVALID_ARGUMENT;
302 goto cleanup;
303 }
304
305 // Check that minimal validation flag only specified with no fips
306 if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
308 {
309 scError = SYMCRYPT_INVALID_ARGUMENT;
310 goto cleanup;
311 }
312
313 if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) != 0 )
314 {
315 fValidatePublicKeyOrder = 0;
316 }
317
318 if ( ( ( cbPrivateKey == 0 ) && ( cbPublicKey == 0 ) ) ||
319 ( ( cbPrivateKey != 0 ) && ( cbPrivateKey != SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve ) ) ) ||
320 ( ( cbPublicKey != 0 ) && ( cbPublicKey != SymCryptEckeySizeofPublicKey( pEckey, ecPointFormat ) ) ) )
321 {
322 scError = SYMCRYPT_INVALID_ARGUMENT;
323 goto cleanup;
324 }
325
326 // Allocate scratch space
328 pbScratch = SymCryptCallbackAlloc( cbScratch );
329 if ( pbScratch == NULL )
330 {
331 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
332 goto cleanup;
333 }
334
335 if ( pbPrivateKey != NULL )
336 {
337 //
338 // Private key calculations
339 //
340
341 pbScratchInternal = pbScratch;
342 cbScratchInternal = cbScratch;
343
344 // Allocate the integer
345 cbTmpInteger = SymCryptSizeofIntFromDigits( privateKeyDigits );
346 piTmpInteger = SymCryptIntCreate( pbScratchInternal, cbTmpInteger, privateKeyDigits );
347 SYMCRYPT_ASSERT( piTmpInteger != NULL );
348
349 pbScratchInternal += cbTmpInteger;
350 cbScratchInternal -= cbTmpInteger;
351
352 // Allocate the modelement
353 peTmpModElement = SymCryptModElementCreate( pbScratchInternal, cbTmpModElement, pCurve->GOrd );
354 SYMCRYPT_ASSERT( peTmpModElement != NULL );
355
356 pbScratchInternal += cbTmpModElement;
357 cbScratchInternal -= cbTmpModElement;
358
359 // Get the "raw" private key
360 scError = SymCryptIntSetValue( pbPrivateKey, cbPrivateKey, numFormat, piTmpInteger );
361 if (scError != SYMCRYPT_NO_ERROR)
362 {
363 goto cleanup;
364 }
365
366 // Validation steps
368 {
369 // Perform range validation on imported Private key if it is in canonical format
370 if ( pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL )
371 {
372 // Check if Private key is greater than or equal to GOrd
373 if ( !SymCryptIntIsLessThan( piTmpInteger, SymCryptIntFromModulus( pCurve->GOrd ) ) )
374 {
375 scError = SYMCRYPT_INVALID_ARGUMENT;
376 goto cleanup;
377 }
378 }
379
380 // "TimesH" formats
381 // IntGetBits requirements:
382 // We know that coFactorPower is up to SYMCRYPT_ECURVE_MAX_COFACTOR_POWER. Thus
383 // less than 32 and less than the digits size in bits.
384 if ( (pCurve->coFactorPower>0) &&
385 (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH) &&
386 (SymCryptIntGetBits( piTmpInteger, 0, pCurve->coFactorPower) != 0) )
387 {
388 scError = SYMCRYPT_INVALID_ARGUMENT;
389 goto cleanup;
390 }
391
392
393 // High bit restrictions
394 // IntGetBits requirements:
395 // Satisfied by asserting that
396 // HighBitRestrictionPosition + HighBitRestrictionNumOfBits <= GOrdBitsize + coFactorPower
397 // during EcurveAllocate.
398 if ( (pCurve->HighBitRestrictionNumOfBits>0) &&
400 piTmpInteger,
401 pCurve->HighBitRestrictionPosition,
402 pCurve->HighBitRestrictionNumOfBits) != pCurve->HighBitRestrictionValue) )
403 {
404 scError = SYMCRYPT_INVALID_ARGUMENT;
405 goto cleanup;
406 }
407 }
408
409 // Convert the private key to "DivH" format
410 if (pCurve->coFactorPower>0)
411 {
412 // "TimesH" format: Divide the input private key with the cofactor
413 // by shifting right the appropriate number of bits
414 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
415 {
416 SymCryptIntDivPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
417 }
418
419 // "Canonical" format: Divide by h modulo GOrd
420 if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
421 {
422 SymCryptIntToModElement( piTmpInteger, pCurve->GOrd, peTmpModElement, pbScratchInternal, cbScratchInternal );
423 SymCryptModDivPow2( pCurve->GOrd, peTmpModElement, pCurve->coFactorPower, peTmpModElement, pbScratchInternal, cbScratchInternal );
424 SymCryptModElementToInt( pCurve->GOrd, peTmpModElement, piTmpInteger, pbScratchInternal, cbScratchInternal );
425 }
426 }
427
428 // Divide the input private key since it could be larger than subgroup order
430 piTmpInteger,
432 NULL,
433 piTmpInteger,
434 pbScratchInternal,
435 cbScratchInternal );
436
437 // Check if Private key is 0 after dividing it by the subgroup order
438 // Other part of range validation - perform unconditionally as it is cheap
439 // and it never makes sense for private key to be 0 intentionally
440 if (SymCryptIntIsEqualUint32( piTmpInteger, 0 ))
441 {
442 scError = SYMCRYPT_INVALID_ARGUMENT;
443 goto cleanup;
444 }
445
446 // Copy into the ECKEY
447 SymCryptIntCopy( piTmpInteger, pEckey->piPrivateKey );
448
449 pEckey->hasPrivateKey = TRUE;
450 }
451
452 if ( pbPublicKey != NULL )
453 {
454 scError = SymCryptEcpointSetValue(
455 pCurve,
456 pbPublicKey,
457 cbPublicKey,
458 numFormat,
459 ecPointFormat,
460 pEckey->poPublicKey,
462 pbScratch,
463 cbScratch );
464 if ( scError != SYMCRYPT_NO_ERROR )
465 {
466 goto cleanup;
467 }
468
469 // Perform Public key validation on imported Public key.
471 {
473 pEckey,
474 fValidatePublicKeyOrder,
475 pbScratch,
476 cbScratch );
477 if ( scError != SYMCRYPT_NO_ERROR )
478 {
479 goto cleanup;
480 }
481 }
482 }
483
484 // Calculating the public key if no key was provided
485 // or if needed for keypair regeneration validation
486 if ( (pbPublicKey==NULL) ||
487 ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
488 (pbPrivateKey!=NULL) && (pbPublicKey!=NULL) ) )
489 {
490 // Calculate the public key from the private key
491 pbScratchInternal = pbScratch;
492 cbScratchInternal = cbScratch;
493
494 // By default calculate the Public key directly where it will be persisted
495 poTmp = pEckey->poPublicKey;
496
497 if ( pbPublicKey != NULL )
498 {
499 // If doing regeneration validation calculate the Public key in scratch
501 poTmp = SymCryptEcpointCreate( pbScratchInternal, cbTmp, pCurve );
502 pbScratchInternal += cbTmp;
503 cbScratchInternal -= cbTmp;
504 }
505
506 SYMCRYPT_ASSERT( poTmp != NULL );
507
508 // Always multiply by the cofactor since the internal format is "DIVH"
509 scError = SymCryptEcpointScalarMul(
510 pCurve,
511 pEckey->piPrivateKey,
512 NULL,
514 poTmp,
515 pbScratchInternal,
516 cbScratchInternal );
517 if ( scError != SYMCRYPT_NO_ERROR )
518 {
519 goto cleanup;
520 }
521
522 if ( pbPublicKey != NULL )
523 {
524 if ( !SymCryptEcpointIsEqual( pCurve, poTmp, pEckey->poPublicKey, 0, pbScratchInternal, cbScratchInternal ) )
525 {
526 scError = SYMCRYPT_INVALID_ARGUMENT;
527 goto cleanup;
528 }
529 }
530 else if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
531 {
532 // Perform Public key validation on generated Public key.
534 pEckey,
535 fValidatePublicKeyOrder,
536 pbScratch,
537 cbScratch );
538 if ( scError != SYMCRYPT_NO_ERROR )
539 {
540 goto cleanup;
541 }
542 }
543 }
544
545 pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
546
547 if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
548 {
549 if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDSA ) != 0 )
550 {
551 // Ensure ECDSA algorithm selftest is run before first use of ECDSA algorithm
555
556 // PCT does not need to be run on import - mark it as done
557 pEckey->fAlgorithmInfo |= SYMCRYPT_PCT_ECDSA;
558 }
559
560 if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
561 {
565 }
566 }
567
568cleanup:
569
570 if ( pbScratch != NULL )
571 {
572 SymCryptWipe( pbScratch, cbScratch );
573 SymCryptCallbackFree( pbScratch );
574 }
575
576 return scError;
577}
#define SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
Definition: symcrypt.h:7586
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)
Definition: ecpoint.c:605
VOID SYMCRYPT_CALL SymCryptIntDivPow2(_In_ PCSYMCRYPT_INT piSrc, SIZE_T exp, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:364
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptIntSetValue(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_NUMBER_FORMAT format, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:248
UINT32 SYMCRYPT_CALL SymCryptIntGetBits(_In_ PCSYMCRYPT_INT piSrc, UINT32 iBit, UINT32 nBits)
Definition: a_dispatch.c:403

◆ SymCryptEckeySizeofPrivateKey()

UINT32 SYMCRYPT_CALL SymCryptEckeySizeofPrivateKey ( _In_ PCSYMCRYPT_ECKEY  pkEckey)

Definition at line 164 of file eckey.c.

165{
166 return SymCryptEcurveSizeofScalarMultiplier( pkEckey->pCurve );
167}

◆ SymCryptEckeySizeofPublicKey()

UINT32 SYMCRYPT_CALL SymCryptEckeySizeofPublicKey ( _In_ PCSYMCRYPT_ECKEY  pkEckey,
_In_ SYMCRYPT_ECPOINT_FORMAT  ecPointFormat 
)

Definition at line 147 of file eckey.c.

150{
151 //
152 // From symcrypt_internal.h we have:
153 // - sizeof results are upper bounded by 2^19
154 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
155 // - SymCryptEcpointFormatNumberofElements returns up to 4 elements.
156 //
157 // Thus the following calculation does not overflow cbScratch.
158 //
159 return SymCryptEcpointFormatNumberofElements[ecPointFormat] * SymCryptEcurveSizeofFieldElement( pkEckey->pCurve );
160}
const UINT32 SymCryptEcpointFormatNumberofElements[]
Definition: ecpoint.c:11
UINT32 SYMCRYPT_CALL SymCryptEcurveSizeofFieldElement(_In_ PCSYMCRYPT_ECURVE pCurve)
Definition: ecurve.c:689

Referenced by SymCryptEckeyGetValue(), and SymCryptEckeySetValue().

◆ SymCryptEckeyWipe()

VOID SYMCRYPT_CALL SymCryptEckeyWipe ( _Out_ PSYMCRYPT_ECKEY  pkDst)

Definition at line 115 of file eckey.c.

116{
117 // Wipe the whole structure in one go.
118 SymCryptWipe( pkDst, SymCryptSizeofEckeyFromCurve( pkDst->pCurve ) );
119}

Referenced by SymCryptEckeyFree().

◆ SymCryptEckeyWipePrivateState()

VOID SYMCRYPT_CALL SymCryptEckeyWipePrivateState ( _Inout_ PSYMCRYPT_ECKEY  pkEckey)

Definition at line 106 of file eckey.c.

108{
109 SymCryptIntSetValueUint32( 0, pkEckey->piPrivateKey );
110 pkEckey->hasPrivateKey = FALSE;
111}
VOID SYMCRYPT_CALL SymCryptIntSetValueUint32(UINT32 u32Src, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:230

◆ SymCryptSizeofEckeyFromCurve()

UINT32 SYMCRYPT_CALL SymCryptSizeofEckeyFromCurve ( _In_ PCSYMCRYPT_ECURVE  pCurve)

Definition at line 44 of file eckey.c.

45{
46 //
47 // From symcrypt_internal.h we have:
48 // - sizeof results are upper bounded by 2^19
49 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
50 // - SymCryptSizeofEcpointFromCurve outputs the size of up to 4 modelements + some overhead
51 // Thus the following calculation does not overflow the result.
52 //
54}

Referenced by SymCryptEckeyAllocate(), SymCryptEckeyCreate(), and SymCryptEckeyWipe().