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

Go to the source code of this file.

Classes

struct  _DSA_NBITSOFQ_CUTOFFS
 

Macros

#define DLGROUP_MR_ITERATIONS   (64)
 

Functions

UINT32 SYMCRYPT_CALL SymCryptDlgroupCalculateBitsizeOfQ (UINT32 nBitsOfP)
 
PSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlgroupAllocate (UINT32 nBitsOfP, UINT32 nBitsOfQ)
 
VOID SYMCRYPT_CALL SymCryptDlgroupFree (_Out_ PSYMCRYPT_DLGROUP pgObj)
 
UINT32 SYMCRYPT_CALL SymCryptSizeofDlgroupFromBitsizes (UINT32 nBitsOfP, UINT32 nBitsOfQ)
 
PSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlgroupCreate (_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nBitsOfP, UINT32 nBitsOfQ)
 
VOID SYMCRYPT_CALL SymCryptDlgroupWipe (_Out_ PSYMCRYPT_DLGROUP pgDst)
 
VOID SYMCRYPT_CALL SymCryptDlgroupCopy (_In_ PCSYMCRYPT_DLGROUP pgSrc, _Out_ PSYMCRYPT_DLGROUP pgDst)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeQ_FIPS (_In_ PSYMCRYPT_DLGROUP pDlgroup, _In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext, _Out_ PUINT32 pfPrimeQFound, _Out_ PSYMCRYPT_INT piQ, _Out_ PSYMCRYPT_DIVISOR pdDivTwoQ, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeP_FIPS (_In_ PSYMCRYPT_DLGROUP pDlgroup, _In_ PSYMCRYPT_DIVISOR pdDivTwoQ, _In_ UINT32 dwMaxCounter, _In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext, _Out_ PUINT32 pfPrimePFound, _Out_ PSYMCRYPT_INT piP, _Out_ PUINT32 pdwCounter, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGenerateGenG_FIPS (_In_ PSYMCRYPT_DLGROUP pDlgroup, _Out_ PSYMCRYPT_MODELEMENT peG, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
 
UINT32 SYMCRYPT_CALL SymCryptDlgroupScratchSpace_FIPS (UINT32 nBitsOfP, UINT32 nBitsOfQ, PCSYMCRYPT_HASH pHashAlgorithm)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGenerate (_In_ PCSYMCRYPT_HASH hashAlgorithm, _In_ SYMCRYPT_DLGROUP_FIPS fipsStandard, _Inout_ PSYMCRYPT_DLGROUP pDlgroup)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupSetValueSafePrime (SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE dhSafePrimeType, _Inout_ PSYMCRYPT_DLGROUP pDlgroup)
 
BOOLEAN SYMCRYPT_CALL SymCryptDlgroupIsSame (_In_ PCSYMCRYPT_DLGROUP pDlgroup1, _In_ PCSYMCRYPT_DLGROUP pDlgroup2)
 
VOID SYMCRYPT_CALL SymCryptDlgroupGetSizes (_In_ PCSYMCRYPT_DLGROUP pDlgroup, _Out_ SIZE_T *pcbPrimeP, _Out_ SIZE_T *pcbPrimeQ, _Out_ SIZE_T *pcbGenG, _Out_ SIZE_T *pcbSeed)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupAutoCompleteNamedSafePrimeGroup (_Inout_ PSYMCRYPT_DLGROUP pDlgroup, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupSetValue (_In_reads_bytes_(cbPrimeP) PCBYTE pbPrimeP, SIZE_T cbPrimeP, _In_reads_bytes_(cbPrimeQ) PCBYTE pbPrimeQ, SIZE_T cbPrimeQ, _In_reads_bytes_(cbGenG) PCBYTE pbGenG, SIZE_T cbGenG, SYMCRYPT_NUMBER_FORMAT numFormat, _In_opt_ PCSYMCRYPT_HASH pHashAlgorithm, _In_reads_bytes_(cbSeed) PCBYTE pbSeed, SIZE_T cbSeed, UINT32 genCounter, SYMCRYPT_DLGROUP_FIPS fipsStandard, _Inout_ PSYMCRYPT_DLGROUP pDlgroup)
 
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGetValue (_In_ PCSYMCRYPT_DLGROUP pDlgroup, _Out_writes_bytes_(cbPrimeP) PBYTE pbPrimeP, SIZE_T cbPrimeP, _Out_writes_bytes_(cbPrimeQ) PBYTE pbPrimeQ, SIZE_T cbPrimeQ, _Out_writes_bytes_(cbGenG) PBYTE pbGenG, SIZE_T cbGenG, SYMCRYPT_NUMBER_FORMAT numFormat, _Out_ PCSYMCRYPT_HASH *ppHashAlgorithm, _Out_writes_bytes_(cbSeed) PBYTE pbSeed, SIZE_T cbSeed, _Out_ PUINT32 pGenCounter)
 

Variables

static const struct _DSA_NBITSOFQ_CUTOFFS g_nBitsOfQ_Cutoffs []
 
static const BYTE ggen [] = { 'g', 'g', 'e', 'n' }
 

Macro Definition Documentation

◆ DLGROUP_MR_ITERATIONS

#define DLGROUP_MR_ITERATIONS   (64)

Definition at line 11 of file dlgroup.c.

Function Documentation

◆ SymCryptDlgroupAllocate()

PSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlgroupAllocate ( UINT32  nBitsOfP,
UINT32  nBitsOfQ 
)

Definition at line 42 of file dlgroup.c.

43{
44 PVOID p;
45 SIZE_T cb;
47
48 // Invalid parameters
51 (nBitsOfP < nBitsOfQ) )
52 {
53 goto cleanup;
54 }
55
57
59
60 if ( p==NULL )
61 {
62 goto cleanup;
63 }
64
66
68 return res;
69}
UINT32 SYMCRYPT_CALL SymCryptSizeofDlgroupFromBitsizes(UINT32 nBitsOfP, UINT32 nBitsOfQ)
Definition: dlgroup.c:82
PSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlgroupCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nBitsOfP, UINT32 nBitsOfQ)
Definition: dlgroup.c:116
#define NULL
Definition: types.h:112
static void cleanup(void)
Definition: main.c:1335
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
GLuint res
Definition: glext.h:9613
GLfloat GLfloat p
Definition: glext.h:8902
void *SYMCRYPT_CALL SymCryptCallbackAlloc(SIZE_T size)
Definition: implglue.c:37
#define SYMCRYPT_DLGROUP_MIN_BITSIZE_P
UINT32 nBitsOfP
UINT32 nBitsOfQ
SYMCRYPT_DLGROUP * PSYMCRYPT_DLGROUP
#define SYMCRYPT_DLGROUP_MIN_BITSIZE_Q
ULONG_PTR SIZE_T
Definition: typedefs.h:80

◆ SymCryptDlgroupAutoCompleteNamedSafePrimeGroup()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupAutoCompleteNamedSafePrimeGroup ( _Inout_ PSYMCRYPT_DLGROUP  pDlgroup,
_Out_writes_bytes_(cbScratch) PBYTE  pbScratch,
SIZE_T  cbScratch 
)

Definition at line 1291 of file dlgroup.c.

1295{
1296 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1297
1298 PBYTE pbScratchInternal;
1299 SIZE_T cbScratchInternal;
1300
1301 PSYMCRYPT_INT piTemp = NULL;
1302 UINT32 cbTemp;
1303 UINT32 i;
1306
1307 // Check whether bottom 64b of P all 1 - as first cheap check
1309 {
1310 goto cleanup; // Not a named safe-prime group
1311 }
1312
1313 cbTemp = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfP );
1314 SYMCRYPT_ASSERT( cbScratch >= cbTemp );
1315
1316 // Create an integer piTemp
1317 piTemp = SymCryptIntCreate( pbScratch, cbTemp, pDlgroup->nDigitsOfP );
1318 pbScratchInternal = pbScratch + cbTemp;
1319 cbScratchInternal = cbScratch - cbTemp;
1320
1321 // Set piTemp to the generator G (this will fail if the number cannot fit in the object)
1322 SymCryptModElementToInt( pDlgroup->pmP, pDlgroup->peG, piTemp, pbScratchInternal, cbScratchInternal );
1323
1324 // Generator must be 2 mod P
1325 if ( !SymCryptIntIsEqualUint32( piTemp, 2 ) )
1326 {
1327 goto cleanup; // Not a named safe-prime group
1328 }
1329
1330 // Iterate through all named safe-prime groups and check whether any of them have matching Prime P
1331 // We can definitely do something smarter here, but we have only 10 values to check so do the dumb thing for now
1333 {
1334 if ( SymCryptNamedSafePrimeGroups[i]->nBitsOfP == pDlgroup->nBitsOfP )
1335 {
1336 // Set piTemp to the named safe-prime group's P (this will fail if the number cannot fit in the object)
1338
1339 if ( SymCryptIntIsEqual( piTemp, SymCryptIntFromModulus(pDlgroup->pmP) ) )
1340 {
1341 safePrimeParams = SymCryptNamedSafePrimeGroups[i];
1342 break;
1343 }
1344 }
1345 }
1346
1347 // If we found a match in the previous loop, auto-populate appropriate fields in pDlGroup
1348 if (safePrimeParams != NULL)
1349 {
1350 if ( pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2 ||
1351 pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_3 )
1352 {
1353 // Inappropriate use of named safe-prime groups
1354 scError = SYMCRYPT_INVALID_ARGUMENT;
1355 goto cleanup;
1356 }
1357
1358 // Set fields marking the Dlgroup as being a named safe-prime group
1359 pDlgroup->isSafePrimeGroup = TRUE;
1360 pDlgroup->eFipsStandard = SYMCRYPT_DLGROUP_FIPS_NONE;
1361 pDlgroup->nMinBitsPriv = safePrimeParams->nMinBitsPriv;
1362 pDlgroup->nDefaultBitsPriv = safePrimeParams->nDefaultBitsPriv;
1363
1364 // Ensure that fields which don't apply to named safe-prime groups are cleared
1365 pDlgroup->pHashAlgorithm = NULL;
1366 pDlgroup->dwGenCounter = 0;
1367
1368 pDlgroup->nBitsOfSeed = 0;
1369 pDlgroup->pbSeed = NULL;
1370 pDlgroup->cbSeed = 0;
1371
1372 // Set the bitsize and bytesize of Q
1373 nBitsOfQ = pDlgroup->nBitsOfP - 1;
1374 pDlgroup->nBitsOfQ = nBitsOfQ;
1375 pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1377
1378 // Create the modulus Q
1379 pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ ), pDlgroup->nDigitsOfQ );
1380
1381 // piTemp still has the value of P, and Q = floor( P / 2 )
1382 SymCryptIntShr1( 0, piTemp, piTemp );
1383
1384 // Set the prime Q
1385 scError = SymCryptIntCopyMixedSize( piTemp, SymCryptIntFromModulus(pDlgroup->pmQ) );
1386 if (scError!=SYMCRYPT_NO_ERROR)
1387 {
1388 goto cleanup;
1389 }
1390
1391 // IntToModulus requirement:
1392 // nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1395 pDlgroup->pmQ,
1396 1000*nBitsOfQ, // Average operations
1398 pbScratch,
1399 cbScratch );
1400
1401 pDlgroup->fHasPrimeQ = TRUE;
1402 }
1403
1404cleanup:
1405 return scError;
1406}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
const PCSYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS SymCryptNamedSafePrimeGroups[SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT]
#define TRUE
Definition: types.h:120
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
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT
Definition: sc_lib.h:3788
UINT32 UINT32 UINT32 UINT32 cbScratch
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
@ SYMCRYPT_DLGROUP_FIPS_186_3
Definition: symcrypt.h:250
@ SYMCRYPT_DLGROUP_FIPS_186_2
Definition: symcrypt.h:249
@ SYMCRYPT_DLGROUP_FIPS_NONE
Definition: symcrypt.h:248
@ SYMCRYPT_NUMBER_FORMAT_MSB_FIRST
Definition: symcrypt.h:7017
SYMCRYPT_ERROR
Definition: symcrypt.h:227
PCSYMCRYPT_DLGROUP pDlgroup
SYMCRYPT_INT * PSYMCRYPT_INT
VOID SYMCRYPT_CALL SymCryptIntShr1(UINT32 highestBit, _In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:374
UINT32 SymCryptDigitsFromBits(UINT32 nBits)
Definition: a_dispatch.c:111
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptIntCopyMixedSize(_In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:214
UINT64 SYMCRYPT_CALL SymCryptIntGetValueLsbits64(_In_ PCSYMCRYPT_INT piSrc)
Definition: a_dispatch.c:277
#define SYMCRYPT_FLAG_MODULUS_PRIME
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
PSYMCRYPT_MODULUS SYMCRYPT_CALL SymCryptModulusCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nDigits)
Definition: a_dispatch.c:608
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
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntFromModulus(_In_ PSYMCRYPT_MODULUS pmSrc)
Definition: a_dispatch.c:720
UINT32 SYMCRYPT_CALL SymCryptSizeofModulusFromDigits(UINT32 nDigits)
Definition: a_dispatch.c:601
UINT32 SYMCRYPT_CALL SymCryptIntIsEqualUint32(_In_ PCSYMCRYPT_INT piSrc1, _In_ UINT32 u32Src2)
Definition: a_dispatch.c:424
UINT32 SYMCRYPT_CALL SymCryptSizeofIntFromDigits(UINT32 nDigits)
Definition: a_dispatch.c:134
VOID SYMCRYPT_CALL SymCryptIntToModulus(_In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_MODULUS pmDst, UINT32 averageOperations, UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:727
UINT32 SYMCRYPT_CALL SymCryptIntIsEqual(_In_ PCSYMCRYPT_INT piSrc1, _In_ PCSYMCRYPT_INT piSrc2)
Definition: a_dispatch.c:433
#define SYMCRYPT_FLAG_DATA_PUBLIC
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 SymCryptDlgroupSetValue().

◆ SymCryptDlgroupCalculateBitsizeOfQ()

UINT32 SYMCRYPT_CALL SymCryptDlgroupCalculateBitsizeOfQ ( UINT32  nBitsOfP)

Definition at line 28 of file dlgroup.c.

29{
30 UINT32 i = 0;
33 {
34 i++;
35 };
36
37 return g_nBitsOfQ_Cutoffs[i].nBitsOfQ;
38}
static const struct _DSA_NBITSOFQ_CUTOFFS g_nBitsOfQ_Cutoffs[]
#define SYMCRYPT_ARRAY_SIZE(_x)
Definition: sc_lib.h:342

Referenced by SymCryptDlgroupGenerate().

◆ SymCryptDlgroupCopy()

VOID SYMCRYPT_CALL SymCryptDlgroupCopy ( _In_ PCSYMCRYPT_DLGROUP  pgSrc,
_Out_ PSYMCRYPT_DLGROUP  pgDst 
)

Definition at line 224 of file dlgroup.c.

227{
228 //
229 // in-place copy is somewhat common...
230 //
231 if( pgSrc != pgDst )
232 {
233 pgDst->cbTotalSize = pgSrc->cbTotalSize;
234 pgDst->fHasPrimeQ = pgSrc->fHasPrimeQ;
235
236 pgDst->nBitsOfP = pgSrc->nBitsOfP;
237 pgDst->cbPrimeP = pgSrc->cbPrimeP;
238 pgDst->nDigitsOfP = pgSrc->nDigitsOfP;
239 pgDst->nMaxBitsOfP = pgSrc->nMaxBitsOfP;
240
241 pgDst->nBitsOfQ = pgSrc->nBitsOfQ;
242 pgDst->cbPrimeQ = pgSrc->cbPrimeQ;
243 pgDst->nDigitsOfQ = pgSrc->nDigitsOfQ;
244 pgDst->nMaxBitsOfQ = pgSrc->nMaxBitsOfQ;
245
246 pgDst->isSafePrimeGroup = pgSrc->isSafePrimeGroup;
247 pgDst->nMinBitsPriv = pgSrc->nMinBitsPriv;
248 pgDst->nDefaultBitsPriv = pgSrc->nDefaultBitsPriv;
249
250 pgDst->nBitsOfSeed = pgSrc->nBitsOfSeed;
251 pgDst->cbSeed = pgSrc->cbSeed;
252
253 pgDst->eFipsStandard = pgSrc->eFipsStandard;
254 pgDst->pHashAlgorithm = pgSrc->pHashAlgorithm;
255 pgDst->dwGenCounter = pgSrc->dwGenCounter;
256 pgDst->bIndexGenG = pgSrc->bIndexGenG;
257 pgDst->pbQ = pgSrc->pbQ;
258
259 memcpy( (PBYTE)pgDst + sizeof(SYMCRYPT_DLGROUP), (PCBYTE)pgSrc + sizeof(SYMCRYPT_DLGROUP), pgSrc->cbTotalSize - sizeof(SYMCRYPT_DLGROUP) );
260 }
261}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
SYMCRYPT_MAGIC_FIELD SYMCRYPT_DLGROUP
const BYTE * PCBYTE

◆ SymCryptDlgroupCreate()

PSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlgroupCreate ( _Out_writes_bytes_(cbBuffer) PBYTE  pbBuffer,
SIZE_T  cbBuffer,
UINT32  nBitsOfP,
UINT32  nBitsOfQ 
)

Definition at line 116 of file dlgroup.c.

121{
123
124 UINT32 cbModP;
125 UINT32 cbModQ;
127
129 UNREFERENCED_PARAMETER( cbBuffer ); // only referenced in ASSERTs...
131
132 // Invalid parameters
135 (nBitsOfP < nBitsOfQ) )
136 {
137 goto cleanup;
138 }
139
140 if ( nBitsOfP == nBitsOfQ )
141 {
142 nBitsOfQ--;
143 }
144
145 pDlgroup = (PSYMCRYPT_DLGROUP) pbBuffer;
146
148
149 // DLGROUP parameters
151 pDlgroup->fHasPrimeQ = FALSE;
152
153 pDlgroup->nBitsOfP = nBitsOfP;
154 pDlgroup->cbPrimeP = (nBitsOfP+7)/8;
156 pDlgroup->nMaxBitsOfP = nBitsOfP;
157
158 pDlgroup->nBitsOfQ = nBitsOfQ; // 0 value possible
159 pDlgroup->cbPrimeQ = (nBitsOfQ+7)/8; // 0 value possible
160 pDlgroup->nDigitsOfQ = (nBitsOfQ>0)?SymCryptDigitsFromBits( nBitsOfQ ):0; // 0 value possible
161 pDlgroup->nMaxBitsOfQ = (nBitsOfQ==0)?(nBitsOfP-1):nBitsOfQ;
162
163 pDlgroup->isSafePrimeGroup = FALSE;
164 pDlgroup->nMinBitsPriv = 0;
165 pDlgroup->nDefaultBitsPriv = nBitsOfQ; // 0 value possible
166
167 pDlgroup->nBitsOfSeed = nBitsOfQ; // 0 value possible
168 pDlgroup->cbSeed = (pDlgroup->nBitsOfSeed+7)/8; // 0 value possible
169
170 pDlgroup->eFipsStandard = SYMCRYPT_DLGROUP_FIPS_NONE; // This will be set either on generate or import
171 pDlgroup->pHashAlgorithm = NULL; // Like-wise
172 pDlgroup->dwGenCounter = 0; // Like-wise
173 pDlgroup->bIndexGenG = 1; // Default: 1
174
175 // Create SymCrypt objects
176 pbBuffer += sizeof(SYMCRYPT_DLGROUP);
177
178 cbModP = SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfP );
179 SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP );
180 pDlgroup->pmP = SymCryptModulusCreate( pbBuffer, cbModP, pDlgroup->nDigitsOfP );
181 pbBuffer += cbModP;
182
183 //
184 // **** Always defer the creation of the Q modulus until the group generation or
185 // import of the modulus. This way it is always the fastest possible even when the caller
186 // specified nBitsOfQ = 0.
187 //
188 if (nBitsOfQ>0)
189 {
190 cbModQ = SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ );
191 }
192 else
193 {
194 cbModQ = cbModP;
195 }
196 SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP + cbModQ );
197 pDlgroup->pbQ = pbBuffer; // Set the aligned buffer
198 pDlgroup->pmQ = NULL;
199 pbBuffer += cbModQ;
200
202 SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP + cbModQ + cbModElement );
203 pDlgroup->peG = SymCryptModElementCreate( pbBuffer, cbModElement, pDlgroup->pmP );
204 pbBuffer += cbModElement;
205
206 pDlgroup->pbSeed = pbBuffer;
207
208 // Setting the magic
210
211cleanup:
212 return pDlgroup;
213}
#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_SET_MAGIC(p)
UINT32 cbModElement
UINT32 SYMCRYPT_CALL SymCryptSizeofModElementFromModulus(PCSYMCRYPT_MODULUS pmMod)
Definition: a_dispatch.c:658
PSYMCRYPT_MODELEMENT SYMCRYPT_CALL SymCryptModElementCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, _In_ PCSYMCRYPT_MODULUS pmMod)
Definition: a_dispatch.c:665

Referenced by SymCryptDlgroupAllocate().

◆ SymCryptDlgroupFree()

VOID SYMCRYPT_CALL SymCryptDlgroupFree ( _Out_ PSYMCRYPT_DLGROUP  pgObj)

Definition at line 73 of file dlgroup.c.

74{
75 SYMCRYPT_CHECK_MAGIC( pgObj );
76 SymCryptDlgroupWipe( pgObj );
77 SymCryptCallbackFree( pgObj );
78}
VOID SYMCRYPT_CALL SymCryptDlgroupWipe(_Out_ PSYMCRYPT_DLGROUP pgDst)
Definition: dlgroup.c:217
void SYMCRYPT_CALL SymCryptCallbackFree(void *ptr)
Definition: implglue.c:42
#define SYMCRYPT_CHECK_MAGIC(p)

◆ SymCryptDlgroupGenerate()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGenerate ( _In_ PCSYMCRYPT_HASH  hashAlgorithm,
_In_ SYMCRYPT_DLGROUP_FIPS  fipsStandard,
_Inout_ PSYMCRYPT_DLGROUP  pDlgroup 
)

Definition at line 850 of file dlgroup.c.

854{
855 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
856
857 PBYTE pbScratch = NULL;
858 SIZE_T cbScratch = 0;
859 PBYTE pbScratchInternal = NULL;
860 SIZE_T cbScratchInternal = 0;
861
862 UINT32 fPrimeQFound = 0;
863 UINT32 fPrimePFound = 0;
864
865 // A divisor equal to 2*Q will be needed for the generation of P
866 PSYMCRYPT_DIVISOR pdDivTwoQ = NULL;
867 UINT32 cbDivTwoQ = 0;
868 UINT32 ndDivTwoQ = 0;
869
870 UINT32 nBitsOfP = 0;
871 UINT32 nDigitsOfP = 0;
872 UINT32 nBitsOfQ = 0;
873 UINT32 nDigitsOfQ = 0;
874
875 PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext = NULL;
876
877 if (fipsStandard == SYMCRYPT_DLGROUP_FIPS_NONE)
878 {
879 fipsStandard = SYMCRYPT_DLGROUP_FIPS_LATEST;
880 }
881
882 // Numbered comments refer to the steps in the FIPS standard
883 // 1. Check that L,N is in the list of acceptable pairs
884 // => Skipped as SymCrypt supports more sizes
885
886 // 2. Check that seedlen >= N
887 // => Skipped as we always have seedlen == N (see below)
888
889
890 // Make sure that a hash algorithm is passed (if needed)
891 // and set the FIPS standard
892 if (fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
893 {
894 if (hashAlgorithm != NULL)
895 {
896 scError = SYMCRYPT_INVALID_ARGUMENT;
897 goto cleanup;
898 }
899
900 pDlgroup->eFipsStandard = fipsStandard;
901 hashAlgorithm = SymCryptSha1Algorithm;
902 }
903 else
904 {
905 if (hashAlgorithm == NULL)
906 {
907 scError = SYMCRYPT_INVALID_ARGUMENT;
908 goto cleanup;
909 }
910
911 pDlgroup->eFipsStandard = fipsStandard;
912 }
913
914 // If during allocation the caller didn't know the size of Q
915 // and set it to 0, pick the default bitsize here
916 // and fix all the zero parameters.
917 if (pDlgroup->nBitsOfQ == 0)
918 {
920
921 if (pDlgroup->nBitsOfQ > pDlgroup->nMaxBitsOfQ)
922 {
923 scError = SYMCRYPT_FIPS_FAILURE; // This hits when nMaxBitsOfQ = (nBitsOfP-1) <= 160
924 goto cleanup;
925 }
926
927 pDlgroup->cbPrimeQ = (pDlgroup->nBitsOfQ + 7)/8;
928 pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits( pDlgroup->nBitsOfQ );
929 pDlgroup->nDefaultBitsPriv = pDlgroup->nBitsOfQ;
930 pDlgroup->nBitsOfSeed = pDlgroup->nBitsOfQ;
931 pDlgroup->cbSeed = (pDlgroup->nBitsOfSeed+7)/8;
932 }
933
934 // Helper variables
935 nBitsOfP = pDlgroup->nBitsOfP;
936 nDigitsOfP = pDlgroup->nDigitsOfP;
937 nBitsOfQ = pDlgroup->nBitsOfQ;
938 nDigitsOfQ = pDlgroup->nDigitsOfQ;
939
940 // Create the modulus Q
942
943 // Conditions on the hash function output size
944 // The second condition is needed for generation of G in SymCrypt
945 // since it allows even very small sizes of P.
946 if ( (8*((UINT32)SymCryptHashResultSize( hashAlgorithm )) < nBitsOfQ) ||
947 (8*((UINT32)SymCryptHashResultSize( hashAlgorithm )) > nBitsOfP) )
948 {
949 scError = SYMCRYPT_INVALID_ARGUMENT;
950 goto cleanup;
951 }
952
953 // Set the group's hash algorithm
954 pDlgroup->pHashAlgorithm = hashAlgorithm;
955
956 // Calculate sizes for the 2*Q divisor
957 ndDivTwoQ = SymCryptDigitsFromBits(nBitsOfQ + 1);
958 cbDivTwoQ = SymCryptSizeofDivisorFromDigits(ndDivTwoQ);
959
960 // Scratch space
961 //
962 // From symcrypt_internal.h we have:
963 // - sizeof results are upper bounded by 2^19
964 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
965 // - SymCryptDlgroupScratchSpace_FIPS is bounded by 2^28.
966 //
967 // Thus the following calculation does not overflow cbScratch.
968 //
970 pbScratch = SymCryptCallbackAlloc(cbScratch);
971 if (pbScratch==NULL)
972 {
973 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
974 goto cleanup;
975 }
976
977 // Create a divisor 2*Q (needed for the generation of P)
978 pdDivTwoQ = SymCryptDivisorCreate( pbScratch, cbDivTwoQ, ndDivTwoQ );
979 pbScratchInternal = pbScratch + cbDivTwoQ;
980 cbScratchInternal = cbScratch - cbDivTwoQ;
981
982 // Create a trial division context for both P and Q
983 pTrialDivisionContext = SymCryptCreateTrialDivisionContext( pDlgroup->nDigitsOfP );
984 if (pTrialDivisionContext == NULL)
985 {
986 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
987 goto cleanup;
988 }
989
990 do
991 {
992 do
993 {
994 // Fill the seed buffer in the DLGroup with seedlen bits
995 scError = SymCryptCallbackRandom( pDlgroup->pbSeed, pDlgroup->cbSeed );
996 if (scError != SYMCRYPT_NO_ERROR)
997 {
998 goto cleanup;
999 }
1000
1001 // Zero-out the top bits if needed
1002 if ((pDlgroup->nBitsOfSeed)%8 != 0)
1003 {
1004 pDlgroup->pbSeed[0] &= ((BYTE)0xff >> (8 - (pDlgroup->nBitsOfSeed)%8));
1005 }
1006
1008 pDlgroup,
1009 pTrialDivisionContext,
1010 &fPrimeQFound,
1012 pdDivTwoQ,
1013 pbScratchInternal,
1014 cbScratchInternal );
1015 if (scError != SYMCRYPT_NO_ERROR)
1016 {
1017 goto cleanup;
1018 }
1019 }
1020 while (fPrimeQFound == 0);
1021
1023 pDlgroup,
1024 pdDivTwoQ,
1025 4*nBitsOfP - 1,
1026 pTrialDivisionContext,
1027 &fPrimePFound,
1029 &(pDlgroup->dwGenCounter),
1030 pbScratchInternal,
1031 cbScratchInternal );
1032 if (scError != SYMCRYPT_NO_ERROR)
1033 {
1034 goto cleanup;
1035 }
1036 }
1037 while (fPrimePFound == 0);
1038
1039 // Specify that we have a Q
1040 pDlgroup->fHasPrimeQ = TRUE;
1041
1042 // Convert both of P and Q to moduli
1043 // IntToModulus requirement:
1044 // Both P,Q > 0 since they are primes
1047 pDlgroup->pmP,
1048 1000*nBitsOfP, // Average operations
1050 pbScratch,
1051 cbScratch );
1052
1055 pDlgroup->pmQ,
1056 1000*nBitsOfP, // Average operations
1058 pbScratch,
1059 cbScratch );
1060
1061 // Generate G
1062 scError = SymCryptDlgroupGenerateGenG_FIPS( pDlgroup, pDlgroup->peG, pbScratch, cbScratch );
1063 if (scError != SYMCRYPT_NO_ERROR)
1064 {
1065 goto cleanup;
1066 }
1067
1068cleanup:
1069 if (pTrialDivisionContext!=NULL)
1070 {
1071 SymCryptFreeTrialDivisionContext( pTrialDivisionContext );
1072 }
1073
1074 if (pbScratch!=NULL)
1075 {
1076 SymCryptWipe( pbScratch, cbScratch );
1077 SymCryptCallbackFree( pbScratch );
1078 }
1079 return scError;
1080}
UINT32 SYMCRYPT_CALL SymCryptDlgroupCalculateBitsizeOfQ(UINT32 nBitsOfP)
Definition: dlgroup.c:28
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeP_FIPS(_In_ PSYMCRYPT_DLGROUP pDlgroup, _In_ PSYMCRYPT_DIVISOR pdDivTwoQ, _In_ UINT32 dwMaxCounter, _In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext, _Out_ PUINT32 pfPrimePFound, _Out_ PSYMCRYPT_INT piP, _Out_ PUINT32 pdwCounter, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: dlgroup.c:421
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeQ_FIPS(_In_ PSYMCRYPT_DLGROUP pDlgroup, _In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext, _Out_ PUINT32 pfPrimeQFound, _Out_ PSYMCRYPT_INT piQ, _Out_ PSYMCRYPT_DIVISOR pdDivTwoQ, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: dlgroup.c:268
UINT32 SYMCRYPT_CALL SymCryptDlgroupScratchSpace_FIPS(UINT32 nBitsOfP, UINT32 nBitsOfQ, PCSYMCRYPT_HASH pHashAlgorithm)
Definition: dlgroup.c:805
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGenerateGenG_FIPS(_In_ PSYMCRYPT_DLGROUP pDlgroup, _Out_ PSYMCRYPT_MODELEMENT peG, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: dlgroup.c:639
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCallbackRandom(BYTE *buf, SIZE_T size)
Definition: implglue.c:56
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
SIZE_T SYMCRYPT_CALL SymCryptHashResultSize(_In_ PCSYMCRYPT_HASH pHash)
Definition: hash.c:132
const PCSYMCRYPT_HASH SymCryptSha1Algorithm
Definition: sha1.c:29
#define SYMCRYPT_DLGROUP_FIPS_LATEST
Definition: symcrypt.h:7872
UINT32 nDigitsOfQ
SYMCRYPT_DIVISOR * PSYMCRYPT_DIVISOR
UINT32 nDigitsOfP
PCSYMCRYPT_TRIALDIVISION_CONTEXT SYMCRYPT_CALL SymCryptCreateTrialDivisionContext(UINT32 nDigits)
Definition: a_dispatch.c:1007
UINT32 SYMCRYPT_CALL SymCryptSizeofDivisorFromDigits(UINT32 nDigits)
Definition: a_dispatch.c:512
PSYMCRYPT_DIVISOR SYMCRYPT_CALL SymCryptDivisorCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nDigits)
Definition: a_dispatch.c:519
VOID SYMCRYPT_CALL SymCryptFreeTrialDivisionContext(PCSYMCRYPT_TRIALDIVISION_CONTEXT pContext)
Definition: a_dispatch.c:1025
unsigned char BYTE
Definition: xxhash.c:193

◆ SymCryptDlgroupGenerateGenG_FIPS()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGenerateGenG_FIPS ( _In_ PSYMCRYPT_DLGROUP  pDlgroup,
_Out_ PSYMCRYPT_MODELEMENT  peG,
_Out_writes_bytes_(cbScratch) PBYTE  pbScratch,
SIZE_T  cbScratch 
)

Definition at line 639 of file dlgroup.c.

645{
646 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
647
648 PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
650 UINT32 nDigitsOfP = pDlgroup->nDigitsOfP;
651 UINT32 nBitsOfP = pDlgroup->nBitsOfP;
653 UINT32 nDigitsOfQ = pDlgroup->nDigitsOfQ;
654 PBYTE pbSeed = pDlgroup->pbSeed;
655 UINT32 cbSeed = pDlgroup->cbSeed;
656 BYTE bIndexGenG = pDlgroup->bIndexGenG;
657
658 SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
659 SYMCRYPT_ASSERT( cbHash == hashAlgorithm->resultSize );
660 SIZE_T cbState = SymCryptHashStateSize( hashAlgorithm );
661 SYMCRYPT_ASSERT( cbState == hashAlgorithm->stateSize );
662
663 UINT16 count = 0;
664 BYTE bTmp = 0;
665
666 PSYMCRYPT_INT piExp = NULL;
667 PSYMCRYPT_INT piRem = NULL;
669 PBYTE pbState = NULL;
670 PBYTE pbW = NULL;
671
675
676 UINT32 borrow = 0;
677
678 // We will use internal scratch space at the start of pbScratch
679 // because cbHash is not necessarily aligned according
680 // to SYMCRYPT_ASYM_ALIGN_VALUE
681 PBYTE pbScratchInternal = 0;
682 SIZE_T cbScratchInternal = 0;
683
686
687 // Create temporaries
688 pbScratchInternal = pbScratch;
692 SYMCRYPT_ASSERT( cbScratch >= cbScratchInternal + cbExp + cbRem );
693 SYMCRYPT_ASSERT( cbScratch >= cbScratchInternal + cbExp + cbModElement + cbHash + cbState );
694 pbScratch += cbScratchInternal;
695
696 piExp = SymCryptIntCreate( pbScratch, cbExp, nDigitsOfP );
697 pbScratch += cbExp;
698
699 piRem = SymCryptIntCreate( pbScratch, cbRem, nDigitsOfQ );
700
701 // Calculate the exponent e = (p-1)/q
703 if (borrow!=0)
704 {
705 // The only way to get a borrow here is if the imported prime P
706 // is zero and we generate a G from P and Q.
707 scError = SYMCRYPT_INVALID_ARGUMENT;
708 goto cleanup;
709 }
710
712 piExp,
714 piExp,
715 piRem,
716 pbScratchInternal,
717 cbScratchInternal );
718
719 if ( !SymCryptIntIsEqualUint32(piRem, 0) )
720 {
721 // The only way to get a non-zero remainder is if Q does not divide P-1
722 scError = SYMCRYPT_INVALID_ARGUMENT;
723 goto cleanup;
724 }
725
726 // To reach here we have guaranteed that P and Q are odd, with bitlength >= 32b, and Q divides P-1.
727 // It follows that piExp >= 2, as it must be even and non-zero.
728
729 peOne = SymCryptModElementCreate( pbScratch, cbModElement, pmP);
730 pbScratch += cbModElement;
731
732 pbState = pbScratch;
733 pbScratch += cbState;
734
735 pbW = pbScratch;
736
737 // Initialize the hash state
738 SymCryptHashInit( hashAlgorithm, pbState );
739
740 // Set the modelement equal to one
741 SymCryptModElementSetValueUint32( 1, pmP, peOne, pbScratchInternal, cbScratchInternal );
742
743 do
744 {
745 count += 1;
746
747 if (count == 0)
748 {
749 scError = SYMCRYPT_FIPS_FAILURE;
750 goto cleanup;
751 }
752
753 // Hash the seed
754 SymCryptHashAppend( hashAlgorithm, pbState, pbSeed, cbSeed );
755
756 // Hash the "ggen" string
757 SymCryptHashAppend( hashAlgorithm, pbState, ggen, sizeof(ggen) );
758
759 // Hash the index
760 SymCryptHashAppend( hashAlgorithm, pbState, &bIndexGenG, sizeof(bIndexGenG) );
761
762 // Hash the count (in MSB)
763 bTmp = (BYTE)(count >> 8);
764 SymCryptHashAppend( hashAlgorithm, pbState, &bTmp, sizeof(bTmp) );
765 bTmp = (BYTE)count;
766 SymCryptHashAppend( hashAlgorithm, pbState, &bTmp, sizeof(bTmp) );
767
768 // Result into W
769 SymCryptHashResult( hashAlgorithm, pbState, pbW, cbHash );
770
771 // Set this into G
773 pbW,
774 cbHash,
776 pmP,
777 peG,
778 pbScratchInternal,
779 cbScratchInternal );
780 if (scError != SYMCRYPT_NO_ERROR)
781 {
782 goto cleanup;
783 }
784
785 // ModExp G in place
787 pmP,
788 peG,
789 piExp,
790 nBitsOfP,
792 peG,
793 pbScratchInternal,
794 cbScratchInternal );
795
797
798cleanup:
799 return scError;
800}
unsigned short UINT16
Definition: actypes.h:129
static const BYTE ggen[]
Definition: dlgroup.c:24
GLuint GLuint GLsizei count
Definition: gl.h:1545
VOID SYMCRYPT_CALL SymCryptHashAppend(_In_ PCSYMCRYPT_HASH pHash, _Inout_updates_bytes_(pHash->stateSize) PVOID pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: hash.c:182
VOID SYMCRYPT_CALL SymCryptHashInit(_In_ PCSYMCRYPT_HASH pHash, _Out_writes_bytes_(pHash->stateSize) PVOID pState)
Definition: hash.c:173
VOID SYMCRYPT_CALL SymCryptHashResult(_In_ PCSYMCRYPT_HASH pHash, _Inout_updates_bytes_(pHash->stateSize) PVOID pState, _Out_writes_(SYMCRYPT_MIN(cbResult, pHash->resultSize)) PBYTE pbResult, SIZE_T cbResult)
Definition: hash.c:193
SIZE_T SYMCRYPT_CALL SymCryptHashStateSize(_In_ PCSYMCRYPT_HASH pHash)
Definition: hash.c:147
BYTE bIndexGenG
SYMCRYPT_MODELEMENT * PSYMCRYPT_MODELEMENT
const SYMCRYPT_HASH * PCSYMCRYPT_HASH
#define SYMCRYPT_MAX(_a, _b)
PSYMCRYPT_MODULUS pmQ
UINT32 cbSeed
PSYMCRYPT_MODULUS pmP
const SYMCRYPT_MODULUS * PCSYMCRYPT_MODULUS
PSYMCRYPT_MODELEMENT peG
SYMCRYPT_MODULUS * PSYMCRYPT_MODULUS
PBYTE pbSeed
PSYMCRYPT_DIVISOR SYMCRYPT_CALL SymCryptDivisorFromModulus(_In_ PSYMCRYPT_MODULUS pmSrc)
Definition: a_dispatch.c:703
UINT32 SYMCRYPT_CALL SymCryptModElementIsZero(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc)
Definition: a_dispatch.c:828
#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD(_nSrcDigits, _nDivisorDigits)
UINT32 SYMCRYPT_CALL SymCryptModElementIsEqual(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc1, _In_ PCSYMCRYPT_MODELEMENT peSrc2)
Definition: a_dispatch.c:818
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptModElementSetValue(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_NUMBER_FORMAT format, PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:781
VOID SYMCRYPT_CALL SymCryptModElementSetValueUint32(UINT32 value, _In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:908
#define SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(_nDigits)
UINT32 SYMCRYPT_CALL SymCryptIntSubUint32(_In_ PCSYMCRYPT_INT piSrc1, UINT32 Src2, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:314
VOID SYMCRYPT_CALL SymCryptModExp(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peBase, _In_ PCSYMCRYPT_INT piExp, UINT32 nBitsExp, UINT32 flags, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:961
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
#define SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP(_nDigits)

Referenced by SymCryptDlgroupGenerate(), and SymCryptDlgroupSetValue().

◆ SymCryptDlgroupGeneratePrimeP_FIPS()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeP_FIPS ( _In_ PSYMCRYPT_DLGROUP  pDlgroup,
_In_ PSYMCRYPT_DIVISOR  pdDivTwoQ,
_In_ UINT32  dwMaxCounter,
_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT  pTrialDivisionContext,
_Out_ PUINT32  pfPrimePFound,
_Out_ PSYMCRYPT_INT  piP,
_Out_ PUINT32  pdwCounter,
_Out_writes_bytes_(cbScratch) PBYTE  pbScratch,
SIZE_T  cbScratch 
)

Definition at line 421 of file dlgroup.c.

433{
434 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
435
436 PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
437 UINT32 nBitsOfP = pDlgroup->nBitsOfP;
438 PBYTE pbSeed = pDlgroup->pbSeed;
439 UINT32 cbSeed = pDlgroup->cbSeed;
440 UINT32 nBitsOfSeed = pDlgroup->nBitsOfSeed;
441
442 SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
443
444 UINT32 counter = 0;
445
446 UINT32 ndDivTwoQ = SymCryptDivisorDigitsizeOfObject( pdDivTwoQ );
447 UINT32 cbIntTwoQ = SymCryptSizeofIntFromDigits( ndDivTwoQ );
448
449 PSYMCRYPT_INT piPersistent = NULL;
450 PSYMCRYPT_INT piRemainder = NULL;
451
452 PBYTE pbHashOutput = NULL;
453 PBYTE pbTempSeed = NULL;
454
455 PBYTE pbW = NULL;
456 UINT32 cbW = pDlgroup->cbPrimeP;
457
458 PBYTE pbWCurr = NULL;
459 SIZE_T cbWBytesLeft = 0;
460
461 UINT32 carry = 0;
462
463 // We will use internal scratch space at the start of pbScratch
464 // because cbHash, cbSeed and cbW are not necessarily aligned according
465 // to SYMCRYPT_ASYM_ALIGN_VALUE
466 PBYTE pbScratchInternal = 0;
467 SIZE_T cbScratchInternal = 0;
468
470 SYMCRYPT_ASSERT( cbScratch >= 2*cbIntTwoQ + cbHash + cbSeed + cbW +
473
474 // Create temporaries
475 pbScratchInternal = pbScratch;
476 cbScratchInternal = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pDlgroup->nDigitsOfP, ndDivTwoQ ),
478 pbScratch += cbScratchInternal;
479
480 piPersistent = SymCryptIntCreate( pbScratch, cbIntTwoQ, ndDivTwoQ );
481 pbScratch += cbIntTwoQ;
482
483 piRemainder = SymCryptIntCreate( pbScratch, cbIntTwoQ, ndDivTwoQ );
484 pbScratch += cbIntTwoQ;
485
486 pbHashOutput = pbScratch;
487 pbScratch += cbHash;
488
489 pbTempSeed = pbScratch;
490 pbScratch += cbSeed;
491
492 pbW = pbScratch;
493
494 // Set the value for the expression "domain_parameter_seed + offset + j"
496 if (scError != SYMCRYPT_NO_ERROR)
497 {
498 goto cleanup;
499 }
500
501 // If the standard is 186-2 add 1 since the starting offset is 2
502 if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
503 {
504 carry = SymCryptIntAddUint32( piPersistent, 1, piPersistent );
505 if (carry!=0)
506 {
507 // This should never happen as piPersistent has at least one more bit than
508 // seedLen == nBitsOfQ
509 scError = SYMCRYPT_FIPS_FAILURE;
510 goto cleanup;
511 }
512
513 // Mod 2^seedlen
514 SymCryptIntModPow2( piPersistent, nBitsOfSeed, piPersistent );
515 }
516
517 *pfPrimePFound = 0;
518
519 for (counter = 0; counter < dwMaxCounter+1; counter++)
520 {
521 cbWBytesLeft = cbW; // Bytes left to write
522 pbWCurr = pbW + cbW - SYMCRYPT_MIN(cbW,cbHash); // Position of the first hash chunk to write (if cbW < cbHash then we write only 1 chunk)
523
524 while (cbWBytesLeft > 0)
525 {
526 // Add 1 to piPersistent
527 // This can never generate a carry as piPersistent has at least one more bit than
528 // seedLen == nBitsOfQ and in the next step we always do mod 2^seedlen.
529 carry = SymCryptIntAddUint32( piPersistent, 1, piPersistent );
530 if (carry!=0)
531 {
532 scError = SYMCRYPT_FIPS_FAILURE;
533 goto cleanup;
534 }
535
536 // Mod 2^seedlen
537 SymCryptIntModPow2( piPersistent, nBitsOfSeed, piPersistent );
538
539 // Extract piPersistent into a byte array (this will always be equal to domain_parameter_seed + offset + j)
540 scError = SymCryptIntGetValue( piPersistent, pbTempSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST );
541 if (scError != SYMCRYPT_NO_ERROR)
542 {
543 goto cleanup;
544 }
545
546 // Hash it
547 SymCryptHash( hashAlgorithm, pbTempSeed, cbSeed, pbHashOutput, cbHash );
548
549 if (cbWBytesLeft >= cbHash)
550 {
551 // Move the entire hash output to the correct location in the pbW buffer
552 memcpy(pbWCurr, pbHashOutput, cbHash );
553 }
554 else
555 {
556 // Move only the last bytes of the hash output
557 memcpy(pbWCurr, pbHashOutput + cbHash - cbWBytesLeft, cbWBytesLeft );
558 }
559
560 // Update the positions on the W buffer
561 cbWBytesLeft -= SYMCRYPT_MIN(cbHash,cbWBytesLeft);
562 pbWCurr -= SYMCRYPT_MIN(cbHash,cbWBytesLeft);
563 }
564
565 // Import the W buffer into P
566 scError = SymCryptIntSetValue( pbW, cbW, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piP );
567 if (scError != SYMCRYPT_NO_ERROR)
568 {
569 goto cleanup;
570 }
571
572 // Zero-out the top bits of the integer
573 SymCryptIntModPow2( piP, nBitsOfP, piP );
574
575 // Set the most significant bit
576 SymCryptIntSetBits( piP, 1, nBitsOfP-1, 1);
577
578 // At this point piP = X = W + 2^{L-1}
579
580 // Calculate c = X mod 2Q
581 SymCryptIntDivMod( piP, pdDivTwoQ, NULL, piRemainder, pbScratchInternal, cbScratchInternal );
582
583 if (SymCryptIntIsEqualUint32(piRemainder, 0))
584 {
585 // Just add one to X
586 // We can never get a carry here because the remainder X mod 2Q
587 // is 0. Therefore X is even.
588 carry = SymCryptIntAddUint32( piP, 1, piP );
589 SYMCRYPT_ASSERT( carry==0 );
590 }
591 else
592 {
593 // Subtract 1 from c
594 // We can never get a borrow here because the remainder is not 0.
595 carry = SymCryptIntSubUint32( piRemainder, 1, piRemainder );
596 SYMCRYPT_ASSERT( carry==0 );
597
598 // X-(c-1)
599 // We can never get a borrow here because c is smaller
600 // or equal to X.
601 carry = SymCryptIntSubMixedSize( piP, piRemainder, piP );
602 SYMCRYPT_ASSERT( carry==0 );
603 }
604
605 // Check if smaller than 2^{L-1} by checking the L-1 bit
606 if (SymCryptIntGetBit( piP, nBitsOfP-1 ) == 0)
607 {
608 continue;
609 }
610
611 // Fast compositeness check
612 if (SymCryptIntFindSmallDivisor( pTrialDivisionContext, piP, NULL, 0 ))
613 {
614 continue;
615 }
616
617 // IntMillerRabinPrimalityTest requirement:
618 // piP > 3 since nBitsOfP is bounded by SYMCRYPT_DLGROUP_MIN_BITSIZE_P
620 piP,
621 nBitsOfP,
623 SYMCRYPT_FLAG_DATA_PUBLIC, // q and p will be public
624 pbScratchInternal,
625 cbScratchInternal );
626
627 if (*pfPrimePFound)
628 {
629 *pdwCounter = counter;
630 break;
631 }
632 }
633cleanup:
634 return scError;
635}
#define DLGROUP_MR_ITERATIONS
Definition: dlgroup.c:11
VOID SYMCRYPT_CALL SymCryptHash(_In_ PCSYMCRYPT_HASH pHash, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_MIN(cbResult, pHash->resultSize)) PBYTE pbResult, SIZE_T cbResult)
Definition: hash.c:155
UINT32 nBitsOfSeed
#define SYMCRYPT_MIN(_a, _b)
#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME(_nDigits)
UINT32 SYMCRYPT_CALL SymCryptIntMillerRabinPrimalityTest(_In_ PCSYMCRYPT_INT piSrc, UINT32 nBitsSrc, UINT32 nIterations, UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: primes.c:12
VOID SYMCRYPT_CALL SymCryptIntSetBits(_In_ PSYMCRYPT_INT piDst, UINT32 value, UINT32 iBit, UINT32 nBits)
Definition: a_dispatch.c:413
UINT32 SYMCRYPT_CALL SymCryptIntSubMixedSize(_In_ PCSYMCRYPT_INT piSrc1, _In_ PCSYMCRYPT_INT piSrc2, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:334
UINT32 SYMCRYPT_CALL SymCryptIntGetBit(_In_ PCSYMCRYPT_INT piSrc, UINT32 iBit)
Definition: a_dispatch.c:394
VOID SYMCRYPT_CALL SymCryptIntModPow2(_In_ PCSYMCRYPT_INT piSrc, SIZE_T exp, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:384
UINT32 SYMCRYPT_CALL SymCryptIntAddUint32(_In_ PCSYMCRYPT_INT piSrc1, UINT32 u32Src2, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:284
UINT32 SYMCRYPT_CALL SymCryptDivisorDigitsizeOfObject(_In_ PCSYMCRYPT_DIVISOR pdSrc)
Definition: a_dispatch.c:546
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
UINT32 SYMCRYPT_CALL SymCryptIntFindSmallDivisor(_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT pContext, _In_ PCSYMCRYPT_INT piSrc, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:1014

Referenced by SymCryptDlgroupGenerate(), and SymCryptDlgroupSetValue().

◆ SymCryptDlgroupGeneratePrimeQ_FIPS()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGeneratePrimeQ_FIPS ( _In_ PSYMCRYPT_DLGROUP  pDlgroup,
_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT  pTrialDivisionContext,
_Out_ PUINT32  pfPrimeQFound,
_Out_ PSYMCRYPT_INT  piQ,
_Out_ PSYMCRYPT_DIVISOR  pdDivTwoQ,
_Out_writes_bytes_(cbScratch) PBYTE  pbScratch,
SIZE_T  cbScratch 
)

Definition at line 268 of file dlgroup.c.

278{
279 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
280
281 PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
282 UINT32 nBitsOfQ = pDlgroup->nBitsOfQ;
283 UINT32 cbPrimeQ = pDlgroup->cbPrimeQ;
284 PBYTE pbSeed = pDlgroup->pbSeed;
285 UINT32 cbSeed = pDlgroup->cbSeed;
286
287 PSYMCRYPT_INT piDivTwoQ = SymCryptIntFromDivisor(pdDivTwoQ);
288
289 SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
290 PBYTE pbTrHash = NULL; // Pointer to the truncated hash value
291 PBYTE pbHashExtra = NULL; // Needed as temp buffer for 186-2
292
293 UINT32 dwShiftBits = (8-nBitsOfQ%8)%8; // When nBitsOfQ is a multiple of 8 -> dwShiftBits = 0;
294
295 UINT32 carry = 0;
296
300 2 * cbHash )) );
301 SYMCRYPT_ASSERT( cbHash >= cbPrimeQ );
302
303 // Hash the seed according to the standard specified
304 if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
305 {
306 SYMCRYPT_ASSERT( hashAlgorithm == SymCryptSha1Algorithm );
308
309 // Hash buffers
310 pbTrHash = pbScratch;
311 pbHashExtra = pbTrHash + cbHash;
312
313 // Prepare an int for SEED + 1
315 if (scError != SYMCRYPT_NO_ERROR)
316 {
317 goto cleanup;
318 }
319
320 // Add 1
321 carry = SymCryptIntAddUint32( piDivTwoQ, 1, piDivTwoQ );
322 if (carry > 0)
323 {
324 // This should never happen as the size of piDivTwoQ is at least one bit bigger than Q
325 scError = SYMCRYPT_FIPS_FAILURE;
326 goto cleanup;
327 }
328
329 // (SEED+1) Mod 2^nBitsOfSeed
330 SymCryptIntModPow2( piDivTwoQ, nBitsOfQ, piDivTwoQ );
331
332 // Get the value into pbTrHash (Notice the cbSeed size)
333 scError = SymCryptIntGetValue( piDivTwoQ, pbTrHash, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST );
334 if (scError != SYMCRYPT_NO_ERROR)
335 {
336 goto cleanup;
337 }
338
339 // Hash it into pbHashExtra
340 SymCryptHash( hashAlgorithm, pbTrHash, cbPrimeQ, pbHashExtra, cbHash );
341
342 // Hash the seed
343 SymCryptHash( hashAlgorithm, pbSeed, cbSeed, pbTrHash, cbHash );
344
345 // Xor the two
346 SymCryptXorBytes( pbTrHash, pbHashExtra, pbTrHash, cbHash );
347
348 }
349 else if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_3)
350 {
351 SYMCRYPT_ASSERT( cbScratch >= cbHash );
352 pbTrHash = pbScratch;
353 SymCryptHash( hashAlgorithm, pbSeed, cbSeed, pbTrHash, cbHash );
354 }
355 else
356 {
357 scError = SYMCRYPT_FIPS_FAILURE;
358 goto cleanup;
359 }
360
361 // Convert it to (2^{N-1} + (Hash mod 2^{N-1})) | 1
362 pbTrHash += (cbHash-cbPrimeQ); // Skip any leading zero bytes
363 pbTrHash[0] &= ((BYTE)0xff >> (dwShiftBits)); // Cut off top bits in the most significant byte
364 pbTrHash[0] |= ((BYTE)0x01 << (7 - dwShiftBits)); // Set the (N-1)-th bit
365 pbTrHash[cbPrimeQ-1] |= ((BYTE)0x01); // Make the entire number odd
366
367 // Set the value
369 if (scError != SYMCRYPT_NO_ERROR)
370 {
371 goto cleanup;
372 }
373
374 // Assume not a prime
375 *pfPrimeQFound = 0;
376
377 // Fast compositeness check
378 if (SymCryptIntFindSmallDivisor( pTrialDivisionContext, piQ, NULL, 0 ))
379 {
380 goto cleanup;
381 }
382
383 // IntMillerRabinPrimalityTest requirement:
384 // piQ > 3 since nBitsOfQ is bounded by SYMCRYPT_DLGROUP_MIN_BITSIZE_Q
386 piQ,
387 nBitsOfQ,
389 SYMCRYPT_FLAG_DATA_PUBLIC, // q and p will be public
390 pbScratch,
391 cbScratch );
392
393 // Set pdDivTwoQ
394 if (*pfPrimeQFound)
395 {
396 scError = SymCryptIntCopyMixedSize( piQ, piDivTwoQ );
397 if (scError != SYMCRYPT_NO_ERROR)
398 {
399 goto cleanup;
400 }
401
402 SymCryptIntMulPow2( piDivTwoQ, 1, piDivTwoQ );
403
404 // IntToDivisor requirement:
405 // Q is non-zero as prime --> 2*Q != 0
407 piDivTwoQ,
408 pdDivTwoQ,
409 4*pDlgroup->nBitsOfP, // 4*L
411 pbScratch,
412 cbScratch );
413 }
414
415cleanup:
416 return scError;
417}
VOID SYMCRYPT_CALL SymCryptXorBytes(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, _Out_writes_(cbBytes) PBYTE pbResult, SIZE_T cbBytes)
Definition: libmain.c:236
UINT32 cbPrimeQ
VOID SYMCRYPT_CALL SymCryptIntMulPow2(_In_ PCSYMCRYPT_INT piSrc, SIZE_T exp, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:354
VOID SYMCRYPT_CALL SymCryptIntToDivisor(_In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_DIVISOR pdDst, UINT32 totalOperations, UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:560
#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR(_nDigits)
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntFromDivisor(_In_ PSYMCRYPT_DIVISOR pdSrc)
Definition: a_dispatch.c:553

Referenced by SymCryptDlgroupGenerate(), and SymCryptDlgroupSetValue().

◆ SymCryptDlgroupGetSizes()

VOID SYMCRYPT_CALL SymCryptDlgroupGetSizes ( _In_ PCSYMCRYPT_DLGROUP  pDlgroup,
_Out_ SIZE_T *  pcbPrimeP,
_Out_ SIZE_T *  pcbPrimeQ,
_Out_ SIZE_T *  pcbGenG,
_Out_ SIZE_T *  pcbSeed 
)

Definition at line 1261 of file dlgroup.c.

1267{
1268 if (pcbPrimeP!=NULL)
1269 {
1270 *pcbPrimeP = pDlgroup->cbPrimeP;
1271 }
1272
1273 if (pcbPrimeQ!=NULL)
1274 {
1275 *pcbPrimeQ = pDlgroup->cbPrimeQ; // This returns 0 if the group does not have a prime Q
1276 }
1277
1278 if (pcbGenG!=NULL)
1279 {
1280 *pcbGenG = pDlgroup->cbPrimeP;
1281 }
1282
1283 if (pcbSeed!=NULL)
1284 {
1285 *pcbSeed = pDlgroup->cbSeed; // This returns 0 if the group does not have a prime Q
1286 }
1287}

◆ SymCryptDlgroupGetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupGetValue ( _In_ PCSYMCRYPT_DLGROUP  pDlgroup,
_Out_writes_bytes_(cbPrimeP) PBYTE  pbPrimeP,
SIZE_T  cbPrimeP,
_Out_writes_bytes_(cbPrimeQ) PBYTE  pbPrimeQ,
SIZE_T  cbPrimeQ,
_Out_writes_bytes_(cbGenG) PBYTE  pbGenG,
SIZE_T  cbGenG,
SYMCRYPT_NUMBER_FORMAT  numFormat,
_Out_ PCSYMCRYPT_HASH *  ppHashAlgorithm,
_Out_writes_bytes_(cbSeed) PBYTE  pbSeed,
SIZE_T  cbSeed,
_Out_ PUINT32  pGenCounter 
)

Definition at line 1901 of file dlgroup.c.

1914{
1915 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1916
1917 PBYTE pbScratch = NULL;
1918 SIZE_T cbScratch = 0;
1919
1920 if ( ((pbPrimeP==NULL)&&(cbPrimeP>0)) ||
1921 ((pbPrimeQ==NULL)&&(cbPrimeQ>0)) ||
1922 ((pbGenG==NULL)&&(cbGenG>0)) ||
1923 ((pbSeed==NULL)&&(cbSeed>0)) ||
1924 ((pbSeed!=NULL)&&(cbSeed!=pDlgroup->cbSeed)) )
1925 {
1926 scError = SYMCRYPT_INVALID_ARGUMENT;
1927 goto cleanup;
1928 }
1929
1930 if ((pbPrimeQ!=NULL) && (!pDlgroup->fHasPrimeQ))
1931 {
1932 scError = SYMCRYPT_INVALID_BLOB;
1933 goto cleanup;
1934 }
1935
1936 if (pbPrimeP!=NULL)
1937 {
1938 scError = SymCryptIntGetValue(
1940 pbPrimeP,
1941 cbPrimeP,
1942 numFormat );
1943 if (scError!=SYMCRYPT_NO_ERROR)
1944 {
1945 goto cleanup;
1946 }
1947 }
1948
1949 if (pbPrimeQ!=NULL)
1950 {
1951 scError = SymCryptIntGetValue(
1953 pbPrimeQ,
1954 cbPrimeQ,
1955 numFormat );
1956 if (scError!=SYMCRYPT_NO_ERROR)
1957 {
1958 goto cleanup;
1959 }
1960 }
1961
1962 if (pbGenG!=NULL)
1963 {
1964 // Scratch space is needed
1966 pbScratch = SymCryptCallbackAlloc( cbScratch );
1967 if (pbScratch==NULL)
1968 {
1969 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1970 goto cleanup;
1971 }
1972
1974 pDlgroup->pmP,
1975 pDlgroup->peG,
1976 pbGenG,
1977 cbGenG,
1978 numFormat,
1979 pbScratch,
1980 cbScratch );
1981 if (scError!=SYMCRYPT_NO_ERROR)
1982 {
1983 goto cleanup;
1984 }
1985 }
1986
1987 if (ppHashAlgorithm!=NULL)
1988 {
1989 if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
1990 {
1991 *ppHashAlgorithm = NULL;
1992 }
1993 else
1994 {
1995 *ppHashAlgorithm = pDlgroup->pHashAlgorithm;
1996 }
1997 }
1998
1999 if (pbSeed!=NULL && pDlgroup->pbSeed!=NULL)
2000 {
2001 memcpy( pbSeed, pDlgroup->pbSeed, pDlgroup->cbSeed);
2002 }
2003
2004 if (pGenCounter!=NULL)
2005 {
2006 *pGenCounter = pDlgroup->dwGenCounter;
2007 }
2008
2009cleanup:
2010 if (pbScratch!=NULL)
2011 {
2012 SymCryptWipe( pbScratch, cbScratch );
2013 SymCryptCallbackFree( pbScratch );
2014 }
2015 return scError;
2016}
UINT32 cbPrimeP
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptModElementGetValue(PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst, SYMCRYPT_NUMBER_FORMAT format, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:804

◆ SymCryptDlgroupIsSame()

BOOLEAN SYMCRYPT_CALL SymCryptDlgroupIsSame ( _In_ PCSYMCRYPT_DLGROUP  pDlgroup1,
_In_ PCSYMCRYPT_DLGROUP  pDlgroup2 
)

Definition at line 1233 of file dlgroup.c.

1236{
1237 BOOLEAN fIsSameGroup = FALSE;
1238
1239 if ( pDlgroup1 == pDlgroup2 )
1240 {
1241 fIsSameGroup = TRUE;
1242 goto cleanup;
1243 }
1244
1245 if ( (pDlgroup1->nBitsOfP != pDlgroup2->nBitsOfP) ||
1246 (pDlgroup1->nDigitsOfP != pDlgroup2->nDigitsOfP) ||
1247 !SymCryptIntIsEqual ( SymCryptIntFromModulus(pDlgroup1->pmP), SymCryptIntFromModulus(pDlgroup2->pmP) ) ||
1248 !SymCryptModElementIsEqual ( pDlgroup1->pmP, pDlgroup1->peG, pDlgroup2->peG ))
1249 {
1250 goto cleanup;
1251 }
1252
1253 fIsSameGroup = TRUE;
1254
1255cleanup:
1256 return fIsSameGroup;
1257}
unsigned char BOOLEAN
Definition: actypes.h:127

Referenced by SymCryptDhSecretAgreement().

◆ SymCryptDlgroupScratchSpace_FIPS()

UINT32 SYMCRYPT_CALL SymCryptDlgroupScratchSpace_FIPS ( UINT32  nBitsOfP,
UINT32  nBitsOfQ,
PCSYMCRYPT_HASH  pHashAlgorithm 
)

Definition at line 805 of file dlgroup.c.

806{
809 UINT32 ndDivTwoQ = SymCryptDigitsFromBits(nBitsOfQ + 1);
810
811 UINT32 cbPrimeP = (nBitsOfP+7)/8; // Note: The upper bound for nBitsOfP is enforced by SymCryptDigitsFromBits
812 UINT32 cbDivTwoQ = SymCryptSizeofDivisorFromDigits(ndDivTwoQ);
813 UINT32 cbIntTwoQ = SymCryptSizeofIntFromDigits( ndDivTwoQ );
814 UINT32 cbSeed = (nBitsOfQ+7)/8; // Note: The upper bound for nBitsOfP is enforced by SymCryptDigitsFromBits
815
819
822
823 //
824 // From symcrypt_internal.h we have:
825 // - sizeof results are upper bounded by 2^19
826 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
827 // Thus the following calculation does not overflow the result and is bounded by 2^28.
828 //
829 return SYMCRYPT_MAX( cbDivTwoQ + SYMCRYPT_MAX(
830 // Generate Q
833 2 * cbHash)),
834 // Generate P
835 2*cbIntTwoQ + cbHash + cbSeed + cbPrimeP +
839 // Convert P and Q to moduli
841 // Generate GenG
842 cbExp + SYMCRYPT_MAX(cbRem, cbModElement + cbState + cbHash) +
846}
PCSYMCRYPT_HASH pHashAlgorithm
#define SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(_nDigits)
#define SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS(_bitsize)

Referenced by SymCryptDlgroupGenerate(), and SymCryptDlgroupSetValue().

◆ SymCryptDlgroupSetValue()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupSetValue ( _In_reads_bytes_(cbPrimeP) PCBYTE  pbPrimeP,
SIZE_T  cbPrimeP,
_In_reads_bytes_(cbPrimeQ) PCBYTE  pbPrimeQ,
SIZE_T  cbPrimeQ,
_In_reads_bytes_(cbGenG) PCBYTE  pbGenG,
SIZE_T  cbGenG,
SYMCRYPT_NUMBER_FORMAT  numFormat,
_In_opt_ PCSYMCRYPT_HASH  pHashAlgorithm,
_In_reads_bytes_(cbSeed) PCBYTE  pbSeed,
SIZE_T  cbSeed,
UINT32  genCounter,
SYMCRYPT_DLGROUP_FIPS  fipsStandard,
_Inout_ PSYMCRYPT_DLGROUP  pDlgroup 
)

Definition at line 1410 of file dlgroup.c.

1424{
1425 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1426
1427 PBYTE pbScratch = NULL;
1428 SIZE_T cbScratch = 0;
1429 SIZE_T cbScratchVerify = 0;
1430
1431 PSYMCRYPT_INT piTemp = NULL;
1432
1433 UINT32 nBitsOfP = 0;
1434 UINT32 nBitsOfQ = 0;
1435
1436 UINT32 nMaxDigitsOfP = SymCryptDigitsFromBits(pDlgroup->nMaxBitsOfP);
1437 UINT32 nMaxDigitsOfQ = SymCryptDigitsFromBits(pDlgroup->nMaxBitsOfQ);
1438
1439 PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext = NULL;
1440
1441 // Make sure that the inputs make sense
1442 if ( (pbPrimeP==NULL) || (cbPrimeP==0) || // Prime P is needed
1443 ((pbGenG==NULL)&&(cbGenG>0)) ||
1444 ((pbPrimeQ==NULL)&&(cbPrimeQ>0)) ||
1445 ((pbGenG==NULL)&&(pbPrimeQ==NULL)) || // We can't have both Q and G missing
1446 ((pbSeed==NULL)&&(cbSeed>0)) )
1447 {
1448 scError = SYMCRYPT_INVALID_ARGUMENT;
1449 goto cleanup;
1450 }
1451
1452 // FIPS 186-4 verification is needed
1453 if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE)
1454 {
1455 // Make sure we have what we need
1456 if ((pbPrimeQ == NULL)||
1457 (cbPrimeQ == 0) ||
1458 (pbSeed == NULL) ||
1459 (cbSeed == 0) ||
1460 ((fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2) && (pHashAlgorithm != NULL)) ||
1461 ((fipsStandard != SYMCRYPT_DLGROUP_FIPS_186_2) && (pHashAlgorithm == NULL)) )
1462 {
1463 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1464 goto cleanup;
1465 }
1466 }
1467
1468 // Set the hashAlgorithm
1469 if ( (fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2) ||
1470 ((pHashAlgorithm==NULL) && (pbGenG == NULL)) )
1471 {
1472 // This hits either when:
1473 // - The FIPS standard is 186-2
1474 // - When we don't specify an algorithm or generator G (thus we need a hash algorithm to generate it
1475 // ourselves)
1476 pDlgroup->pHashAlgorithm = SymCryptSha1Algorithm;
1477 }
1478 else
1479 {
1480 pDlgroup->pHashAlgorithm = pHashAlgorithm;
1481 }
1482
1483 if ( (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE) || (pbGenG == NULL))
1484 {
1485 // The following is the scratch space for generation / verification
1486 // Notice that we take the maximum size possible so it can get relatively big.
1487 // Also, we will need some additional space for the computed parameters:
1488 // computedP, computedQ, and computedG.
1489 cbScratchVerify = SymCryptDlgroupScratchSpace_FIPS( pDlgroup->nMaxBitsOfP, pDlgroup->nMaxBitsOfQ, pDlgroup->pHashAlgorithm ) +
1492 2*SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS(nMaxDigitsOfP)));
1493 }
1494
1495 // Scratch space
1496 //
1497 // From symcrypt_internal.h we have:
1498 // - sizeof results are upper bounded by 2^19
1499 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
1500 // - SymCryptDlgroupScratchSpace_FIPS is bounded by 2^28.
1501 //
1502 // Thus the following calculation does not overflow cbScratch.
1503 //
1507 cbScratchVerify );
1508 pbScratch = SymCryptCallbackAlloc( cbScratch );
1509 if (pbScratch==NULL)
1510 {
1511 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1512 goto cleanup;
1513 }
1514
1515 //
1516 // Prime P
1517 //
1518
1519 // Set the prime P (this will fail if the number cannot fit in the object)
1520 scError = SymCryptIntSetValue( pbPrimeP, cbPrimeP, numFormat, SymCryptIntFromModulus(pDlgroup->pmP) );
1521 if (scError!=SYMCRYPT_NO_ERROR)
1522 {
1523 goto cleanup;
1524 }
1525
1526 // Check the bitsize of value
1528 if ( nBitsOfP > pDlgroup->nMaxBitsOfP)
1529 {
1530 scError = SYMCRYPT_INVALID_ARGUMENT;
1531 goto cleanup;
1532 }
1533
1535 {
1536 scError = SYMCRYPT_WRONG_KEY_SIZE;
1537 goto cleanup;
1538 }
1539
1540 // FIPS 186-4 verification is needed
1541 // Check genCounter is not too big
1542 if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE &&
1543 genCounter > 4*nBitsOfP-1 )
1544 {
1545 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1546 goto cleanup;
1547 }
1548
1550 {
1551 // P is even, when it should be a prime of at least 32 bits
1552 scError = SYMCRYPT_INVALID_ARGUMENT;
1553 goto cleanup;
1554 }
1555
1556 // Set the bitsize and bytesize of the value
1557 pDlgroup->nBitsOfP = nBitsOfP;
1558 pDlgroup->cbPrimeP = (nBitsOfP + 7)/8;
1559
1560 // IntToModulus requirement:
1561 // nBitsOfP >= SYMCRYPT_DLGROUP_MIN_BITSIZE_P --> P > 0
1564 pDlgroup->pmP,
1565 1000*nBitsOfP, // Average operations
1567 pbScratch,
1568 cbScratch );
1569
1570 //
1571 // Prime Q
1572 //
1573
1574 // Wiping of previous (optional) parameters related to Q
1575 if (pDlgroup->pmQ != NULL)
1576 {
1578 }
1579 if (pDlgroup->cbSeed != 0)
1580 {
1581 SymCryptWipe( pDlgroup->pbSeed, pDlgroup->cbSeed);
1582 }
1583
1584 if (pbPrimeQ != NULL)
1585 {
1586 // Create an integer piTemp
1587 piTemp = SymCryptIntCreate( pbScratch, cbScratch, nMaxDigitsOfQ );
1588
1589 // Set the prime Q (this will fail if the number cannot fit in the object)
1590 scError = SymCryptIntSetValue( pbPrimeQ, cbPrimeQ, numFormat, piTemp );
1591 if (scError!=SYMCRYPT_NO_ERROR)
1592 {
1593 goto cleanup;
1594 }
1595
1596 // Check the bitsize of value
1598 if ( nBitsOfQ > pDlgroup->nMaxBitsOfQ)
1599 {
1600 scError = SYMCRYPT_INVALID_ARGUMENT;
1601 goto cleanup;
1602 }
1603
1605 {
1606 scError = SYMCRYPT_WRONG_KEY_SIZE;
1607 goto cleanup;
1608 }
1609
1610 if( (SymCryptIntGetValueLsbits32( piTemp ) & 1) == 0 )
1611 {
1612 // Some of our modinv algorithms require odd inputs, and Q should be odd as it
1613 // claims to be a prime.
1614 // (Q can't be 2 as it must be at least 32 bits long.)
1615 scError = SYMCRYPT_INVALID_ARGUMENT;
1616 goto cleanup;
1617 }
1618
1619 // Set the bitsize and bytesize of the value
1620 pDlgroup->nBitsOfQ = nBitsOfQ;
1621 pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1623 pDlgroup->nDefaultBitsPriv = nBitsOfQ;
1624 pDlgroup->nBitsOfSeed = nBitsOfQ;
1625 pDlgroup->cbSeed = (nBitsOfQ+7)/8;
1626
1627 // Create the modulus Q
1628 pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ ), pDlgroup->nDigitsOfQ );
1629
1630 // Set the prime Q
1631 scError = SymCryptIntCopyMixedSize( piTemp, SymCryptIntFromModulus(pDlgroup->pmQ) );
1632 if (scError!=SYMCRYPT_NO_ERROR)
1633 {
1634 goto cleanup;
1635 }
1636
1637 // piTemp is not needed any more so we are free to re-use the scratch space
1638
1639 // IntToModulus requirement:
1640 // nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1643 pDlgroup->pmQ,
1644 1000*nBitsOfP, // Average operations
1646 pbScratch,
1647 cbScratch );
1648
1649 pDlgroup->fHasPrimeQ = TRUE;
1650 }
1651 else
1652 {
1653 // Clear all info about Q
1654 pDlgroup->cbPrimeQ = 0;
1655 pDlgroup->nBitsOfQ = 0;
1656 pDlgroup->nDigitsOfQ = 0;
1657
1658 pDlgroup->nDefaultBitsPriv = 0;
1659 pDlgroup->nBitsOfSeed = 0;
1660 pDlgroup->cbSeed = 0;
1661
1662 pDlgroup->pmQ = NULL;
1663 pDlgroup->fHasPrimeQ = FALSE;
1664 }
1665
1666 pDlgroup->isSafePrimeGroup = FALSE;
1667 pDlgroup->nMinBitsPriv = 0;
1668
1669 //
1670 // Provided Generator G
1671 //
1672 if (pbGenG != NULL)
1673 {
1674 // Set the generator G (this will fail if the number cannot fit in the object)
1675 scError = SymCryptModElementSetValue( pbGenG, cbGenG, numFormat, pDlgroup->pmP, pDlgroup->peG, pbScratch, cbScratch );
1676 if (scError!=SYMCRYPT_NO_ERROR)
1677 {
1678 goto cleanup;
1679 }
1680
1682 if (scError!=SYMCRYPT_NO_ERROR)
1683 {
1684 goto cleanup;
1685 }
1686
1687 // Successfully detected, validated and autocompleted named safe-prime group
1688 if (pDlgroup->isSafePrimeGroup)
1689 {
1690 goto cleanup;
1691 }
1692 }
1693
1694 //
1695 // Verification data (this has to be done before possibly generating G)
1696 //
1697
1698 // Set the FIPS standard
1699 pDlgroup->eFipsStandard = fipsStandard;
1700
1701 // Set the seed
1702 if (pbSeed != NULL)
1703 {
1704 if (cbSeed != pDlgroup->cbSeed)
1705 {
1706 scError = SYMCRYPT_INVALID_ARGUMENT;
1707 goto cleanup;
1708 }
1709 memcpy( pDlgroup->pbSeed, pbSeed, cbSeed );
1710 }
1711
1712 // Set the genCounter
1713 pDlgroup->dwGenCounter = genCounter;
1714
1715 //
1716 // Generator G
1717 //
1718
1719 if (pbGenG == NULL)
1720 {
1721 // Let's generate G here since none was given
1722
1723 // // We need Q (check at the beginning)
1724 // if (pbPrimeQ==NULL)
1725 // {
1726 // scError = SYMCRYPT_INVALID_ARGUMENT;
1727 // goto cleanup;
1728 // }
1729
1730 // If no seed was given let's generate our own
1731 if (pbSeed==NULL)
1732 {
1733 SymCryptCallbackRandom(pDlgroup->pbSeed, pDlgroup->cbSeed);
1734 }
1735
1737 pDlgroup,
1738 pDlgroup->peG,
1739 pbScratch,
1740 cbScratch );
1741 if (scError!=SYMCRYPT_NO_ERROR)
1742 {
1743 goto cleanup;
1744 }
1745 }
1746
1747
1748 // Verification
1749 if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE)
1750 {
1751 // Verification
1752 PBYTE pbScratchInternal = pbScratch;
1753 SIZE_T cbScratchInternal = cbScratch;
1754
1755 UINT32 ndDivTwoQ = 0;
1756 UINT32 cbDivTwoQ = 0;
1757 PSYMCRYPT_DIVISOR pdDivTwoQ = NULL;
1758
1759 UINT32 cbComputed = 0;
1760 PSYMCRYPT_INT piComputed = NULL;
1761 UINT32 fPrimeComputed = 0;
1762 UINT32 dwComputedCounter = 0;
1763
1764 PSYMCRYPT_MODELEMENT peComputed = NULL;
1765 PSYMCRYPT_MODELEMENT peOne = NULL;
1766
1767 // Step 3: Acceptable pairs of L,N => skipped
1768
1769 // Step 6: nBitsOfSeed < nBitsOfQ => skipped
1770
1771 // Create the divisor object
1772 ndDivTwoQ = SymCryptDigitsFromBits(pDlgroup->nBitsOfQ + 1);
1773 cbDivTwoQ = SymCryptSizeofDivisorFromDigits( ndDivTwoQ );
1774 pdDivTwoQ = SymCryptDivisorCreate( pbScratchInternal, cbDivTwoQ, ndDivTwoQ );
1775 pbScratchInternal += cbDivTwoQ;
1776 cbScratchInternal -= cbDivTwoQ;
1777
1778 // Create the temporary integer of size Q
1779 cbComputed = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfQ );
1780 piComputed = SymCryptIntCreate( pbScratchInternal, cbComputed, pDlgroup->nDigitsOfQ );
1781 pbScratchInternal += cbComputed;
1782 cbScratchInternal -= cbComputed;
1783
1784 // Create a trial division context for both P and Q
1785 pTrialDivisionContext = SymCryptCreateTrialDivisionContext( pDlgroup->nDigitsOfP );
1786 if (pTrialDivisionContext == NULL)
1787 {
1788 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1789 goto cleanup;
1790 }
1791
1792 // Steps 8,9: Check if computed_q is prime and equal to q
1794 pDlgroup,
1795 pTrialDivisionContext,
1796 &fPrimeComputed,
1797 piComputed,
1798 pdDivTwoQ,
1799 pbScratchInternal,
1800 cbScratchInternal );
1801 if (scError != SYMCRYPT_NO_ERROR)
1802 {
1803 scError = SYMCRYPT_AUTHENTICATION_FAILURE; // Overwrite any possible error
1804 goto cleanup;
1805 }
1806
1807 if ((!fPrimeComputed)||(!SymCryptIntIsEqual( piComputed, SymCryptIntFromModulus(pDlgroup->pmQ))))
1808 {
1809 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1810 goto cleanup;
1811 }
1812
1813 // Create the temporary integer of size P
1814 pbScratchInternal -= cbComputed;
1815 cbScratchInternal += cbComputed;
1816 cbComputed = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfP );
1817 piComputed = SymCryptIntCreate( pbScratchInternal, cbComputed, pDlgroup->nDigitsOfP );
1818 pbScratchInternal += cbComputed;
1819 cbScratchInternal -= cbComputed;
1820
1821 // Steps 10-14: Check if computed_p is prime and equal to p
1823 pDlgroup,
1824 pdDivTwoQ,
1825 pDlgroup->dwGenCounter, // Go up to this
1826 pTrialDivisionContext,
1827 &fPrimeComputed,
1828 piComputed,
1829 &dwComputedCounter,
1830 pbScratchInternal,
1831 cbScratchInternal );
1832 if (scError != SYMCRYPT_NO_ERROR)
1833 {
1834 scError = SYMCRYPT_AUTHENTICATION_FAILURE; // Overwrite any possible error
1835 goto cleanup;
1836 }
1837
1838 if ((!fPrimeComputed)||(dwComputedCounter!=pDlgroup->dwGenCounter)||(!SymCryptIntIsEqual( piComputed, SymCryptIntFromModulus(pDlgroup->pmP))))
1839 {
1840 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1841 goto cleanup;
1842 }
1843
1844 // Validation of G
1845
1846 // Create the temporary modelement mod P
1847 pbScratchInternal -= cbComputed;
1848 cbScratchInternal += cbComputed;
1849 cbComputed = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
1850 peOne = SymCryptModElementCreate( pbScratchInternal, cbComputed, pDlgroup->pmP );
1851 pbScratchInternal += cbComputed;
1852 cbScratchInternal -= cbComputed;
1853 peComputed = SymCryptModElementCreate( pbScratchInternal, cbComputed, pDlgroup->pmP );
1854 pbScratchInternal += cbComputed;
1855 cbScratchInternal -= cbComputed;
1856
1857 // Step 2: Verify that 2<= G <= p-1
1858 SymCryptModElementSetValueUint32( 1, pDlgroup->pmP, peOne, pbScratchInternal, cbScratchInternal ); // Set the temporary to 1
1859
1860 if ((SymCryptModElementIsZero(pDlgroup->pmP, pDlgroup->peG)) || (SymCryptModElementIsEqual(pDlgroup->pmP, pDlgroup->peG, peOne)))
1861 {
1862 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1863 goto cleanup;
1864 }
1865
1866 // Step 3: Verify that G^Q == 1
1868 pDlgroup->pmP,
1869 pDlgroup->peG,
1871 nBitsOfQ,
1873 peComputed,
1874 pbScratchInternal,
1875 cbScratchInternal );
1876
1877 if (!SymCryptModElementIsEqual(pDlgroup->pmP, peComputed, peOne))
1878 {
1879 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1880 goto cleanup;
1881 }
1882
1883 }
1884
1885cleanup:
1886 if (pTrialDivisionContext!=NULL)
1887 {
1888 SymCryptFreeTrialDivisionContext( pTrialDivisionContext );
1889 }
1890
1891 if (pbScratch!=NULL)
1892 {
1893 SymCryptWipe( pbScratch, cbScratch );
1894 SymCryptCallbackFree( pbScratch );
1895 }
1896 return scError;
1897}
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupAutoCompleteNamedSafePrimeGroup(_Inout_ PSYMCRYPT_DLGROUP pDlgroup, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: dlgroup.c:1291
UINT32 SYMCRYPT_CALL SymCryptIntGetValueLsbits32(_In_ PCSYMCRYPT_INT piSrc)
Definition: a_dispatch.c:270
VOID SYMCRYPT_CALL SymCryptModulusWipe(_Out_ PSYMCRYPT_MODULUS pmObj)
Definition: a_dispatch.c:618
UINT32 SYMCRYPT_CALL SymCryptIntBitsizeOfValue(_In_ PCSYMCRYPT_INT piSrc)
Definition: a_dispatch.c:223

◆ SymCryptDlgroupSetValueSafePrime()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlgroupSetValueSafePrime ( SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE  dhSafePrimeType,
_Inout_ PSYMCRYPT_DLGROUP  pDlgroup 
)

Definition at line 1084 of file dlgroup.c.

1087{
1088 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1089
1090 PBYTE pbScratch = NULL;
1091 SIZE_T cbScratch = 0;
1092
1094
1095 UINT32 i;
1097
1098 // Given we know nBitsOfP = nBitsOfQ+1 for all safe-prime groups, this specifies a tight bound when selecting a group
1099 UINT32 nMaxBitsOfP = SYMCRYPT_MIN(pDlgroup->nMaxBitsOfP, pDlgroup->nMaxBitsOfQ+1);
1100 UINT32 nMaxDigitsOfP;
1101
1102 if ( dhSafePrimeType == SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE_NONE )
1103 {
1104 scError = SYMCRYPT_INVALID_ARGUMENT;
1105 goto cleanup;
1106 }
1107
1108 // Iterate through all named safe-prime groups until we find one which fits the requested parameters
1109 // We can definitely do something smarter here, but we have only 10 values to check so do the dumb thing for now
1110 // Relies on the fact the SymCryptNamedSafePrimeGroups is ordered from largest to smallest
1112 {
1113 if ( SymCryptNamedSafePrimeGroups[i]->eDhSafePrimeType == dhSafePrimeType &&
1115 {
1116 safePrimeParams = SymCryptNamedSafePrimeGroups[i];
1117 break;
1118 }
1119 }
1120
1121 if (safePrimeParams == NULL)
1122 {
1123 scError = SYMCRYPT_INVALID_ARGUMENT;
1124 goto cleanup;
1125 }
1126
1127 nMaxDigitsOfP = SymCryptDigitsFromBits(safePrimeParams->nBitsOfP);
1128
1129 // Scratch space
1130 //
1131 // From symcrypt_internal.h we have:
1132 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
1133 //
1134 // Thus the following calculation does not overflow cbScratch.
1135 //
1138 pbScratch = SymCryptCallbackAlloc( cbScratch );
1139 if (pbScratch==NULL)
1140 {
1141 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1142 goto cleanup;
1143 }
1144
1145 // Set fields marking the Dlgroup as being a named safe-prime group
1146 pDlgroup->isSafePrimeGroup = TRUE;
1147 pDlgroup->eFipsStandard = SYMCRYPT_DLGROUP_FIPS_NONE;
1148 pDlgroup->nMinBitsPriv = safePrimeParams->nMinBitsPriv;
1149 pDlgroup->nDefaultBitsPriv = safePrimeParams->nDefaultBitsPriv;
1150
1151 // Ensure that fields which don't apply to named safe-prime groups are cleared
1152 pDlgroup->pHashAlgorithm = NULL;
1153 pDlgroup->dwGenCounter = 0;
1154
1155 pDlgroup->nBitsOfSeed = 0;
1156 pDlgroup->pbSeed = NULL;
1157 pDlgroup->cbSeed = 0;
1158
1159 // Set the bitsize and bytesize of P
1160 pDlgroup->nBitsOfP = safePrimeParams->nBitsOfP;
1161 pDlgroup->cbPrimeP = (safePrimeParams->nBitsOfP + 7)/ 8;
1162 pDlgroup->nDigitsOfP = SymCryptDigitsFromBits(safePrimeParams->nBitsOfP);
1163
1164 // Set the bitsize and bytesize of Q
1165 nBitsOfQ = pDlgroup->nBitsOfP - 1;
1166 pDlgroup->nBitsOfQ = nBitsOfQ;
1167 pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1169 pDlgroup->fHasPrimeQ = TRUE;
1170
1171 //
1172 // Prime P
1173 //
1174
1175 // Recreate the modulus P
1176 // (this will set nDigits in the modulus object appropriately, which is necessary for use of SymCryptIntShr1 below)
1178
1180 if (scError!=SYMCRYPT_NO_ERROR)
1181 {
1182 goto cleanup;
1183 }
1184
1185 // IntToModulus requirement:
1186 // nBitsOfP >= SYMCRYPT_DLGROUP_MIN_BITSIZE_P --> P > 0
1189 pDlgroup->pmP,
1190 1000*pDlgroup->nBitsOfP, // Average operations
1192 pbScratch,
1193 cbScratch );
1194
1195 //
1196 // Prime Q
1197 //
1198
1199 // Create the modulus Q
1200 pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ ), pDlgroup->nDigitsOfQ );
1201
1202 // Q = floor( P / 2 )
1204
1205 // IntToModulus requirement:
1206 // nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1209 pDlgroup->pmQ,
1210 1000*nBitsOfQ, // Average operations
1212 pbScratch,
1213 cbScratch );
1214
1215 //
1216 // Generator G
1217 //
1218
1219 // G to 2
1220 SymCryptModElementSetValueUint32( 2, pDlgroup->pmP, pDlgroup->peG, pbScratch, cbScratch );
1221
1222cleanup:
1223 if (pbScratch!=NULL)
1224 {
1225 SymCryptWipe( pbScratch, cbScratch );
1226 SymCryptCallbackFree( pbScratch );
1227 }
1228 return scError;
1229}
@ SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE_NONE
Definition: symcrypt.h:262
UINT32 nMaxBitsOfP

◆ SymCryptDlgroupWipe()

VOID SYMCRYPT_CALL SymCryptDlgroupWipe ( _Out_ PSYMCRYPT_DLGROUP  pgDst)

Definition at line 217 of file dlgroup.c.

218{
219 SymCryptWipe( (PBYTE) pgDst, pgDst->cbTotalSize );
220}

Referenced by SymCryptDlgroupFree().

◆ SymCryptSizeofDlgroupFromBitsizes()

UINT32 SYMCRYPT_CALL SymCryptSizeofDlgroupFromBitsizes ( UINT32  nBitsOfP,
UINT32  nBitsOfQ 
)

Definition at line 82 of file dlgroup.c.

83{
84 UINT32 cbSeed = 0;
85
86 if (nBitsOfQ == 0)
87 {
88 nBitsOfQ = nBitsOfP-1; // Default to the maximum possible size for Q
89 }
90
91 // Invalid parameters
94 (nBitsOfP < nBitsOfQ) )
95 {
96 return 0;
97 }
98
99 if ( nBitsOfP == nBitsOfQ )
100 {
101 nBitsOfQ--;
102 }
103
104 // Calculate the (tight) bytesize of the seed
105 cbSeed = (nBitsOfQ+7)/8;
106
107 return sizeof(SYMCRYPT_DLGROUP) +
111 ((cbSeed + SYMCRYPT_ASYM_ALIGN_VALUE - 1)/SYMCRYPT_ASYM_ALIGN_VALUE)*SYMCRYPT_ASYM_ALIGN_VALUE; // Make sure that the entire structure is ASYM_ALIGNED.
112}
#define SYMCRYPT_ASYM_ALIGN_VALUE
#define SYMCRYPT_SIZEOF_MODULUS_FROM_BITS(_bitsize)

Referenced by SymCryptDlgroupAllocate(), and SymCryptDlgroupCreate().

Variable Documentation

◆ g_nBitsOfQ_Cutoffs

const struct _DSA_NBITSOFQ_CUTOFFS g_nBitsOfQ_Cutoffs[]
static
Initial value:
= {
{ 1024, 160 },
{ 2048, 256 },
{ UINT32_MAX, 256 },
}
#define UINT32_MAX
Definition: stdint.h:85

Referenced by SymCryptDlgroupCalculateBitsizeOfQ().

◆ ggen

const BYTE ggen[] = { 'g', 'g', 'e', 'n' }
static

Definition at line 24 of file dlgroup.c.

Referenced by SymCryptDlgroupGenerateGenG_FIPS().