Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/dlgroup.c
15010 views
1
//
2
// dlgroup.c Dlgroup functions
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
// Miller-Rabin iterations for prime generation
11
#define DLGROUP_MR_ITERATIONS (64)
12
13
// Default size for Q according to FIPS 186-3
14
static const struct _DSA_NBITSOFQ_CUTOFFS {
15
UINT32 nBitsOfP;
16
UINT32 nBitsOfQ;
17
} g_nBitsOfQ_Cutoffs[] = {
18
{ 1024, 160 },
19
{ 2048, 256 },
20
{ UINT32_MAX, 256 },
21
};
22
23
// Const label for the generation of generator G according to FIPS 186-3
24
static const BYTE ggen[] = { 'g', 'g', 'e', 'n' };
25
26
UINT32
27
SYMCRYPT_CALL
28
SymCryptDlgroupCalculateBitsizeOfQ( UINT32 nBitsOfP )
29
{
30
UINT32 i = 0;
31
while ( (i<SYMCRYPT_ARRAY_SIZE(g_nBitsOfQ_Cutoffs) - 1) &&
32
(g_nBitsOfQ_Cutoffs[i].nBitsOfP < nBitsOfP) )
33
{
34
i++;
35
};
36
37
return g_nBitsOfQ_Cutoffs[i].nBitsOfQ;
38
}
39
40
PSYMCRYPT_DLGROUP
41
SYMCRYPT_CALL
42
SymCryptDlgroupAllocate( UINT32 nBitsOfP, UINT32 nBitsOfQ )
43
{
44
PVOID p;
45
SIZE_T cb;
46
PSYMCRYPT_DLGROUP res = NULL;
47
48
// Invalid parameters
49
if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
50
((nBitsOfQ > 0) && (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)) ||
51
(nBitsOfP < nBitsOfQ) )
52
{
53
goto cleanup;
54
}
55
56
cb = SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ );
57
58
p = SymCryptCallbackAlloc( cb );
59
60
if ( p==NULL )
61
{
62
goto cleanup;
63
}
64
65
res = SymCryptDlgroupCreate( p, cb, nBitsOfP, nBitsOfQ );
66
67
cleanup:
68
return res;
69
}
70
71
VOID
72
SYMCRYPT_CALL
73
SymCryptDlgroupFree( _Out_ PSYMCRYPT_DLGROUP pgObj )
74
{
75
SYMCRYPT_CHECK_MAGIC( pgObj );
76
SymCryptDlgroupWipe( pgObj );
77
SymCryptCallbackFree( pgObj );
78
}
79
80
UINT32
81
SYMCRYPT_CALL
82
SymCryptSizeofDlgroupFromBitsizes( UINT32 nBitsOfP, UINT32 nBitsOfQ )
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
92
if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
93
(nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q) ||
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) +
108
SYMCRYPT_SIZEOF_MODULUS_FROM_BITS( nBitsOfP ) +
109
SYMCRYPT_SIZEOF_MODULUS_FROM_BITS( nBitsOfQ ) +
110
SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( nBitsOfP ) +
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
}
113
114
PSYMCRYPT_DLGROUP
115
SYMCRYPT_CALL
116
SymCryptDlgroupCreate(
117
_Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer,
118
SIZE_T cbBuffer,
119
UINT32 nBitsOfP,
120
UINT32 nBitsOfQ )
121
{
122
PSYMCRYPT_DLGROUP pDlgroup = NULL;
123
124
UINT32 cbModP;
125
UINT32 cbModQ;
126
UINT32 cbModElement;
127
128
SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ ) );
129
UNREFERENCED_PARAMETER( cbBuffer ); // only referenced in ASSERTs...
130
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
131
132
// Invalid parameters
133
if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
134
((nBitsOfQ > 0) && (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)) ||
135
(nBitsOfP < nBitsOfQ) )
136
{
137
goto cleanup;
138
}
139
140
if ( nBitsOfP == nBitsOfQ )
141
{
142
nBitsOfQ--;
143
}
144
145
pDlgroup = (PSYMCRYPT_DLGROUP) pbBuffer;
146
147
SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) );
148
149
// DLGROUP parameters
150
pDlgroup->cbTotalSize = SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ );
151
pDlgroup->fHasPrimeQ = FALSE;
152
153
pDlgroup->nBitsOfP = nBitsOfP;
154
pDlgroup->cbPrimeP = (nBitsOfP+7)/8;
155
pDlgroup->nDigitsOfP = SymCryptDigitsFromBits( nBitsOfP );
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
201
cbModElement = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
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
209
SYMCRYPT_SET_MAGIC( pDlgroup );
210
211
cleanup:
212
return pDlgroup;
213
}
214
215
VOID
216
SYMCRYPT_CALL
217
SymCryptDlgroupWipe( _Out_ PSYMCRYPT_DLGROUP pgDst )
218
{
219
SymCryptWipe( (PBYTE) pgDst, pgDst->cbTotalSize );
220
}
221
222
VOID
223
SYMCRYPT_CALL
224
SymCryptDlgroupCopy(
225
_In_ PCSYMCRYPT_DLGROUP pgSrc,
226
_Out_ PSYMCRYPT_DLGROUP pgDst )
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
}
262
263
264
// DLGROUP-specific functions
265
266
SYMCRYPT_ERROR
267
SYMCRYPT_CALL
268
SymCryptDlgroupGeneratePrimeQ_FIPS(
269
_In_ PSYMCRYPT_DLGROUP pDlgroup,
270
_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT
271
pTrialDivisionContext,
272
_Out_ PUINT32 pfPrimeQFound,
273
_Out_ PSYMCRYPT_INT piQ,
274
_Out_ PSYMCRYPT_DIVISOR pdDivTwoQ,
275
_Out_writes_bytes_( cbScratch )
276
PBYTE pbScratch,
277
SIZE_T cbScratch )
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
297
UNREFERENCED_PARAMETER( cbScratch );
298
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR(SymCryptDigitsFromBits(nBitsOfQ+1)),
299
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME(pDlgroup->nDigitsOfQ),
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 );
307
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX(2*cbHash, cbSeed) );
308
309
// Hash buffers
310
pbTrHash = pbScratch;
311
pbHashExtra = pbTrHash + cbHash;
312
313
// Prepare an int for SEED + 1
314
scError = SymCryptIntSetValue( pbSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piDivTwoQ );
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
368
scError = SymCryptIntSetValue( pbTrHash, cbPrimeQ, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piQ );
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
385
*pfPrimeQFound = SymCryptIntMillerRabinPrimalityTest(
386
piQ,
387
nBitsOfQ,
388
DLGROUP_MR_ITERATIONS,
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
406
SymCryptIntToDivisor(
407
piDivTwoQ,
408
pdDivTwoQ,
409
4*pDlgroup->nBitsOfP, // 4*L
410
SYMCRYPT_FLAG_DATA_PUBLIC,
411
pbScratch,
412
cbScratch );
413
}
414
415
cleanup:
416
return scError;
417
}
418
419
SYMCRYPT_ERROR
420
SYMCRYPT_CALL
421
SymCryptDlgroupGeneratePrimeP_FIPS(
422
_In_ PSYMCRYPT_DLGROUP pDlgroup,
423
_In_ PSYMCRYPT_DIVISOR pdDivTwoQ,
424
_In_ UINT32 dwMaxCounter, // Maximum value of counter (used in validation)
425
_In_ PCSYMCRYPT_TRIALDIVISION_CONTEXT
426
pTrialDivisionContext,
427
_Out_ PUINT32 pfPrimePFound,
428
_Out_ PSYMCRYPT_INT piP,
429
_Out_ PUINT32 pdwCounter,
430
_Out_writes_bytes_( cbScratch )
431
PBYTE pbScratch,
432
SIZE_T cbScratch )
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
469
UNREFERENCED_PARAMETER( cbScratch );
470
SYMCRYPT_ASSERT( cbScratch >= 2*cbIntTwoQ + cbHash + cbSeed + cbW +
471
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pDlgroup->nDigitsOfP, ndDivTwoQ ),
472
SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pDlgroup->nDigitsOfP )) );
473
474
// Create temporaries
475
pbScratchInternal = pbScratch;
476
cbScratchInternal = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pDlgroup->nDigitsOfP, ndDivTwoQ ),
477
SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pDlgroup->nDigitsOfP ) );
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"
495
scError = SymCryptIntSetValue( pbSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piPersistent );
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
619
*pfPrimePFound = SymCryptIntMillerRabinPrimalityTest(
620
piP,
621
nBitsOfP,
622
DLGROUP_MR_ITERATIONS,
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
}
633
cleanup:
634
return scError;
635
}
636
637
SYMCRYPT_ERROR
638
SYMCRYPT_CALL
639
SymCryptDlgroupGenerateGenG_FIPS(
640
_In_ PSYMCRYPT_DLGROUP pDlgroup,
641
_Out_ PSYMCRYPT_MODELEMENT peG,
642
_Out_writes_bytes_( cbScratch )
643
PBYTE pbScratch,
644
SIZE_T cbScratch )
645
{
646
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
647
648
PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
649
PCSYMCRYPT_MODULUS pmP = pDlgroup->pmP;
650
UINT32 nDigitsOfP = pDlgroup->nDigitsOfP;
651
UINT32 nBitsOfP = pDlgroup->nBitsOfP;
652
PCSYMCRYPT_MODULUS pmQ = pDlgroup->pmQ;
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;
668
PSYMCRYPT_MODELEMENT peOne = NULL;
669
PBYTE pbState = NULL;
670
PBYTE pbW = NULL;
671
672
UINT32 cbExp = SymCryptSizeofIntFromDigits( nDigitsOfP );
673
UINT32 cbRem = SymCryptSizeofIntFromDigits( nDigitsOfQ );
674
UINT32 cbModElement = SymCryptSizeofModElementFromModulus( pmP );
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
684
UNREFERENCED_PARAMETER( cbScratch );
685
UNREFERENCED_PARAMETER( nDigitsOfQ );
686
687
// Create temporaries
688
pbScratchInternal = pbScratch;
689
cbScratchInternal = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( nDigitsOfP ),
690
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, nDigitsOfQ ),
691
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ) ));
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
702
borrow = SymCryptIntSubUint32( SymCryptIntFromModulus((PSYMCRYPT_MODULUS)pmP), 1, piExp );
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
711
SymCryptIntDivMod(
712
piExp,
713
SymCryptDivisorFromModulus( (PSYMCRYPT_MODULUS)pmQ ),
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
772
scError = SymCryptModElementSetValue(
773
pbW,
774
cbHash,
775
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
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
786
SymCryptModExp(
787
pmP,
788
peG,
789
piExp,
790
nBitsOfP,
791
SYMCRYPT_FLAG_DATA_PUBLIC,
792
peG,
793
pbScratchInternal,
794
cbScratchInternal );
795
796
} while (SymCryptModElementIsZero( pmP, peG ) || SymCryptModElementIsEqual( pmP, peG, peOne ));
797
798
cleanup:
799
return scError;
800
}
801
802
// Scratch space requirements for the entire FIPS standards generation of P,Q,G
803
UINT32
804
SYMCRYPT_CALL
805
SymCryptDlgroupScratchSpace_FIPS( UINT32 nBitsOfP, UINT32 nBitsOfQ, PCSYMCRYPT_HASH pHashAlgorithm )
806
{
807
UINT32 nDigitsOfP = SymCryptDigitsFromBits( nBitsOfP );
808
UINT32 nDigitsOfQ = SymCryptDigitsFromBits( nBitsOfQ );
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
816
UINT32 cbExp = SymCryptSizeofIntFromDigits( nDigitsOfP );
817
UINT32 cbRem = SymCryptSizeofIntFromDigits( nDigitsOfQ );
818
UINT32 cbModElement = SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( nBitsOfP );
819
820
UINT32 cbHash = (UINT32)SymCryptHashResultSize( pHashAlgorithm );
821
UINT32 cbState = (UINT32) SymCryptHashStateSize( pHashAlgorithm );
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
831
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( ndDivTwoQ ),
832
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( nDigitsOfQ ),
833
2 * cbHash)),
834
// Generate P
835
2*cbIntTwoQ + cbHash + cbSeed + cbPrimeP +
836
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, ndDivTwoQ ),
837
SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( nDigitsOfP )) ),
838
SYMCRYPT_MAX(
839
// Convert P and Q to moduli
840
SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS( nDigitsOfP ),
841
// Generate GenG
842
cbExp + SYMCRYPT_MAX(cbRem, cbModElement + cbState + cbHash) +
843
SYMCRYPT_MAX(SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( nDigitsOfP ),
844
SYMCRYPT_MAX(SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, nDigitsOfQ ),
845
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ) )) ));
846
}
847
848
SYMCRYPT_ERROR
849
SYMCRYPT_CALL
850
SymCryptDlgroupGenerate(
851
_In_ PCSYMCRYPT_HASH hashAlgorithm,
852
_In_ SYMCRYPT_DLGROUP_FIPS fipsStandard,
853
_Inout_ PSYMCRYPT_DLGROUP pDlgroup )
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
{
919
pDlgroup->nBitsOfQ = SymCryptDlgroupCalculateBitsizeOfQ(pDlgroup->nBitsOfP);
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
941
pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( nDigitsOfQ ), nDigitsOfQ );
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
//
969
cbScratch = SymCryptDlgroupScratchSpace_FIPS( nBitsOfP, nBitsOfQ, hashAlgorithm );
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
1007
scError = SymCryptDlgroupGeneratePrimeQ_FIPS(
1008
pDlgroup,
1009
pTrialDivisionContext,
1010
&fPrimeQFound,
1011
SymCryptIntFromModulus(pDlgroup->pmQ),
1012
pdDivTwoQ,
1013
pbScratchInternal,
1014
cbScratchInternal );
1015
if (scError != SYMCRYPT_NO_ERROR)
1016
{
1017
goto cleanup;
1018
}
1019
}
1020
while (fPrimeQFound == 0);
1021
1022
scError = SymCryptDlgroupGeneratePrimeP_FIPS(
1023
pDlgroup,
1024
pdDivTwoQ,
1025
4*nBitsOfP - 1,
1026
pTrialDivisionContext,
1027
&fPrimePFound,
1028
SymCryptIntFromModulus(pDlgroup->pmP),
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
1045
SymCryptIntToModulus(
1046
SymCryptIntFromModulus( pDlgroup->pmP ),
1047
pDlgroup->pmP,
1048
1000*nBitsOfP, // Average operations
1049
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1050
pbScratch,
1051
cbScratch );
1052
1053
SymCryptIntToModulus(
1054
SymCryptIntFromModulus( pDlgroup->pmQ ),
1055
pDlgroup->pmQ,
1056
1000*nBitsOfP, // Average operations
1057
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
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
1068
cleanup:
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
}
1081
1082
SYMCRYPT_ERROR
1083
SYMCRYPT_CALL
1084
SymCryptDlgroupSetValueSafePrime(
1085
SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE dhSafePrimeType,
1086
_Inout_ PSYMCRYPT_DLGROUP pDlgroup )
1087
{
1088
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1089
1090
PBYTE pbScratch = NULL;
1091
SIZE_T cbScratch = 0;
1092
1093
PCSYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS safePrimeParams = NULL;
1094
1095
UINT32 i;
1096
UINT32 nBitsOfQ;
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
1111
for ( i=0; i<SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT; i++ )
1112
{
1113
if ( SymCryptNamedSafePrimeGroups[i]->eDhSafePrimeType == dhSafePrimeType &&
1114
SymCryptNamedSafePrimeGroups[i]->nBitsOfP <= nMaxBitsOfP )
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
//
1136
cbScratch = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(nMaxDigitsOfP),
1137
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(nMaxDigitsOfP) );
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;
1168
pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
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)
1177
pDlgroup->pmP = SymCryptModulusCreate( (PBYTE) pDlgroup->pmP, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfP ), pDlgroup->nDigitsOfP );
1178
1179
scError = SymCryptIntSetValue( safePrimeParams->pcbPrimeP, pDlgroup->cbPrimeP, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, SymCryptIntFromModulus(pDlgroup->pmP) );
1180
if (scError!=SYMCRYPT_NO_ERROR)
1181
{
1182
goto cleanup;
1183
}
1184
1185
// IntToModulus requirement:
1186
// nBitsOfP >= SYMCRYPT_DLGROUP_MIN_BITSIZE_P --> P > 0
1187
SymCryptIntToModulus(
1188
SymCryptIntFromModulus( pDlgroup->pmP ),
1189
pDlgroup->pmP,
1190
1000*pDlgroup->nBitsOfP, // Average operations
1191
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
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 )
1203
SymCryptIntShr1( 0, SymCryptIntFromModulus(pDlgroup->pmP), SymCryptIntFromModulus(pDlgroup->pmQ) );
1204
1205
// IntToModulus requirement:
1206
// nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1207
SymCryptIntToModulus(
1208
SymCryptIntFromModulus( pDlgroup->pmQ ),
1209
pDlgroup->pmQ,
1210
1000*nBitsOfQ, // Average operations
1211
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
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
1222
cleanup:
1223
if (pbScratch!=NULL)
1224
{
1225
SymCryptWipe( pbScratch, cbScratch );
1226
SymCryptCallbackFree( pbScratch );
1227
}
1228
return scError;
1229
}
1230
1231
BOOLEAN
1232
SYMCRYPT_CALL
1233
SymCryptDlgroupIsSame(
1234
_In_ PCSYMCRYPT_DLGROUP pDlgroup1,
1235
_In_ PCSYMCRYPT_DLGROUP pDlgroup2 )
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
1255
cleanup:
1256
return fIsSameGroup;
1257
}
1258
1259
VOID
1260
SYMCRYPT_CALL
1261
SymCryptDlgroupGetSizes(
1262
_In_ PCSYMCRYPT_DLGROUP pDlgroup,
1263
_Out_ SIZE_T* pcbPrimeP,
1264
_Out_ SIZE_T* pcbPrimeQ,
1265
_Out_ SIZE_T* pcbGenG,
1266
_Out_ SIZE_T* pcbSeed )
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
}
1288
1289
SYMCRYPT_ERROR
1290
SYMCRYPT_CALL
1291
SymCryptDlgroupAutoCompleteNamedSafePrimeGroup(
1292
_Inout_ PSYMCRYPT_DLGROUP pDlgroup,
1293
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
1294
SIZE_T cbScratch )
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;
1304
UINT32 nBitsOfQ;
1305
PCSYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS safePrimeParams = NULL;
1306
1307
// Check whether bottom 64b of P all 1 - as first cheap check
1308
if ( SymCryptIntGetValueLsbits64( SymCryptIntFromModulus(pDlgroup->pmP) ) != ((UINT64) -1) )
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
1332
for ( i=0; i<SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT; i++ )
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)
1337
SymCryptIntSetValue( SymCryptNamedSafePrimeGroups[i]->pcbPrimeP, pDlgroup->cbPrimeP, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTemp );
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;
1376
pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
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
1393
SymCryptIntToModulus(
1394
SymCryptIntFromModulus( pDlgroup->pmQ ),
1395
pDlgroup->pmQ,
1396
1000*nBitsOfQ, // Average operations
1397
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1398
pbScratch,
1399
cbScratch );
1400
1401
pDlgroup->fHasPrimeQ = TRUE;
1402
}
1403
1404
cleanup:
1405
return scError;
1406
}
1407
1408
SYMCRYPT_ERROR
1409
SYMCRYPT_CALL
1410
SymCryptDlgroupSetValue(
1411
_In_reads_bytes_( cbPrimeP ) PCBYTE pbPrimeP,
1412
SIZE_T cbPrimeP,
1413
_In_reads_bytes_( cbPrimeQ ) PCBYTE pbPrimeQ,
1414
SIZE_T cbPrimeQ,
1415
_In_reads_bytes_( cbGenG ) PCBYTE pbGenG,
1416
SIZE_T cbGenG,
1417
SYMCRYPT_NUMBER_FORMAT numFormat,
1418
_In_opt_ PCSYMCRYPT_HASH pHashAlgorithm,
1419
_In_reads_bytes_( cbSeed ) PCBYTE pbSeed,
1420
SIZE_T cbSeed,
1421
UINT32 genCounter,
1422
SYMCRYPT_DLGROUP_FIPS fipsStandard,
1423
_Inout_ PSYMCRYPT_DLGROUP pDlgroup )
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 ) +
1490
SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfP),
1491
SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfQ),
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
//
1504
cbScratch = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(nMaxDigitsOfP) +
1505
SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfQ),
1506
SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(nMaxDigitsOfP) ),
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
1527
nBitsOfP = SymCryptIntBitsizeOfValue(SymCryptIntFromModulus(pDlgroup->pmP));
1528
if ( nBitsOfP > pDlgroup->nMaxBitsOfP)
1529
{
1530
scError = SYMCRYPT_INVALID_ARGUMENT;
1531
goto cleanup;
1532
}
1533
1534
if (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P)
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
1549
if( (SymCryptIntGetValueLsbits32( SymCryptIntFromModulus( pDlgroup->pmP ) ) & 1) == 0 )
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
1562
SymCryptIntToModulus(
1563
SymCryptIntFromModulus( pDlgroup->pmP ),
1564
pDlgroup->pmP,
1565
1000*nBitsOfP, // Average operations
1566
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
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
{
1577
SymCryptModulusWipe( pDlgroup->pmQ );
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
1597
nBitsOfQ = SymCryptIntBitsizeOfValue(piTemp);
1598
if ( nBitsOfQ > pDlgroup->nMaxBitsOfQ)
1599
{
1600
scError = SYMCRYPT_INVALID_ARGUMENT;
1601
goto cleanup;
1602
}
1603
1604
if (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)
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;
1622
pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
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
1641
SymCryptIntToModulus(
1642
SymCryptIntFromModulus( pDlgroup->pmQ ),
1643
pDlgroup->pmQ,
1644
1000*nBitsOfP, // Average operations
1645
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
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
1681
scError = SymCryptDlgroupAutoCompleteNamedSafePrimeGroup( pDlgroup, pbScratch, cbScratch );
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
1736
scError = SymCryptDlgroupGenerateGenG_FIPS(
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
1793
scError = SymCryptDlgroupGeneratePrimeQ_FIPS(
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
1822
scError = SymCryptDlgroupGeneratePrimeP_FIPS(
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
1867
SymCryptModExp(
1868
pDlgroup->pmP,
1869
pDlgroup->peG,
1870
SymCryptIntFromModulus(pDlgroup->pmQ),
1871
nBitsOfQ,
1872
SYMCRYPT_FLAG_DATA_PUBLIC,
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
1885
cleanup:
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
}
1898
1899
SYMCRYPT_ERROR
1900
SYMCRYPT_CALL
1901
SymCryptDlgroupGetValue(
1902
_In_ PCSYMCRYPT_DLGROUP pDlgroup,
1903
_Out_writes_bytes_( cbPrimeP ) PBYTE pbPrimeP,
1904
SIZE_T cbPrimeP,
1905
_Out_writes_bytes_( cbPrimeQ ) PBYTE pbPrimeQ,
1906
SIZE_T cbPrimeQ,
1907
_Out_writes_bytes_( cbGenG ) PBYTE pbGenG,
1908
SIZE_T cbGenG,
1909
SYMCRYPT_NUMBER_FORMAT numFormat,
1910
_Out_ PCSYMCRYPT_HASH * ppHashAlgorithm,
1911
_Out_writes_bytes_( cbSeed ) PBYTE pbSeed,
1912
SIZE_T cbSeed,
1913
_Out_ PUINT32 pGenCounter )
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(
1939
SymCryptIntFromModulus(pDlgroup->pmP),
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(
1952
SymCryptIntFromModulus(pDlgroup->pmQ),
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
1965
cbScratch = SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pDlgroup->nDigitsOfP);
1966
pbScratch = SymCryptCallbackAlloc( cbScratch );
1967
if (pbScratch==NULL)
1968
{
1969
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1970
goto cleanup;
1971
}
1972
1973
scError = SymCryptModElementGetValue(
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
2009
cleanup:
2010
if (pbScratch!=NULL)
2011
{
2012
SymCryptWipe( pbScratch, cbScratch );
2013
SymCryptCallbackFree( pbScratch );
2014
}
2015
return scError;
2016
}
2017
2018