Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/dlgroup.c
Line
Count
Source (jump to first uncovered line)
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 iterarions for prime generation
11
0
#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
0
{
30
0
    UINT32 i = 0;
31
0
    while ( (i<SYMCRYPT_ARRAY_SIZE(g_nBitsOfQ_Cutoffs) - 1) &&
32
0
            (g_nBitsOfQ_Cutoffs[i].nBitsOfP < nBitsOfP) )
33
0
    {
34
0
        i++;
35
0
    };
36
37
0
    return g_nBitsOfQ_Cutoffs[i].nBitsOfQ;
38
0
}
39
40
PSYMCRYPT_DLGROUP
41
SYMCRYPT_CALL
42
SymCryptDlgroupAllocate( UINT32  nBitsOfP, UINT32  nBitsOfQ )
43
0
{
44
0
    PVOID               p;
45
0
    SIZE_T              cb;
46
0
    PSYMCRYPT_DLGROUP   res = NULL;
47
48
    // Invalid parameters
49
0
    if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
50
0
         ((nBitsOfQ > 0) && (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)) ||
51
0
         (nBitsOfP < nBitsOfQ) )
52
0
    {
53
0
        goto cleanup;
54
0
    }
55
56
0
    cb = SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ );
57
58
0
    p = SymCryptCallbackAlloc( cb );
59
60
0
    if ( p==NULL )
61
0
    {
62
0
        goto cleanup;
63
0
    }
64
65
0
    res = SymCryptDlgroupCreate( p, cb, nBitsOfP, nBitsOfQ );
66
67
0
cleanup:
68
0
    return res;
69
0
}
70
71
VOID
72
SYMCRYPT_CALL
73
SymCryptDlgroupFree( _Out_ PSYMCRYPT_DLGROUP pgObj )
74
0
{
75
0
    SYMCRYPT_CHECK_MAGIC( pgObj );
76
0
    SymCryptDlgroupWipe( pgObj );
77
0
    SymCryptCallbackFree( pgObj );
78
0
}
79
80
UINT32
81
SYMCRYPT_CALL
82
SymCryptSizeofDlgroupFromBitsizes( UINT32 nBitsOfP, UINT32 nBitsOfQ )
83
0
{
84
0
    UINT32 cbSeed = 0;
85
86
0
    if (nBitsOfQ == 0)
87
0
    {
88
0
        nBitsOfQ = nBitsOfP-1;        // Default to the maximum possible size for Q
89
0
    }
90
91
    // Invalid parameters
92
0
    if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
93
0
         (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q) ||
94
0
         (nBitsOfP < nBitsOfQ) )
95
0
    {
96
0
        return 0;
97
0
    }
98
99
0
    if ( nBitsOfP == nBitsOfQ )
100
0
    {
101
0
        nBitsOfQ--;
102
0
    }
103
104
    // Calculate the (tight) bytesize of the seed
105
0
    cbSeed = (nBitsOfQ+7)/8;
106
107
0
    return  sizeof(SYMCRYPT_DLGROUP) +
108
0
            SYMCRYPT_SIZEOF_MODULUS_FROM_BITS( nBitsOfP ) +
109
0
            SYMCRYPT_SIZEOF_MODULUS_FROM_BITS( nBitsOfQ ) +
110
0
            SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( nBitsOfP ) +
111
0
            ((cbSeed + SYMCRYPT_ASYM_ALIGN_VALUE - 1)/SYMCRYPT_ASYM_ALIGN_VALUE)*SYMCRYPT_ASYM_ALIGN_VALUE;    // Make sure that the entire structure is ASYM_ALIGNED.
112
0
}
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
0
{
122
0
    PSYMCRYPT_DLGROUP       pDlgroup = NULL;
123
124
0
    UINT32                  cbModP;
125
0
    UINT32                  cbModQ;
126
0
    UINT32                  cbModElement;
127
128
0
    SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ ) );
129
0
    UNREFERENCED_PARAMETER( cbBuffer );     // only referenced in ASSERTs...
130
0
    SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
131
132
    // Invalid parameters
133
0
    if ( (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P) ||
134
0
         ((nBitsOfQ > 0) && (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)) ||
135
0
         (nBitsOfP < nBitsOfQ) )
136
0
    {
137
0
        goto cleanup;
138
0
    }
139
140
0
    if ( nBitsOfP == nBitsOfQ )
141
0
    {
142
0
        nBitsOfQ--;
143
0
    }
144
145
0
    pDlgroup = (PSYMCRYPT_DLGROUP) pbBuffer;
146
147
0
    SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) );
148
149
    // DLGROUP parameters
150
0
    pDlgroup->cbTotalSize = SymCryptSizeofDlgroupFromBitsizes( nBitsOfP, nBitsOfQ );
151
0
    pDlgroup->fHasPrimeQ = FALSE;
152
153
0
    pDlgroup->nBitsOfP = nBitsOfP;
154
0
    pDlgroup->cbPrimeP = (nBitsOfP+7)/8;
155
0
    pDlgroup->nDigitsOfP = SymCryptDigitsFromBits( nBitsOfP );
156
0
    pDlgroup->nMaxBitsOfP = nBitsOfP;
157
158
0
    pDlgroup->nBitsOfQ = nBitsOfQ;                                             // 0 value possible
159
0
    pDlgroup->cbPrimeQ = (nBitsOfQ+7)/8;                                       // 0 value possible
160
0
    pDlgroup->nDigitsOfQ = (nBitsOfQ>0)?SymCryptDigitsFromBits( nBitsOfQ ):0;  // 0 value possible
161
0
    pDlgroup->nMaxBitsOfQ = (nBitsOfQ==0)?(nBitsOfP-1):nBitsOfQ;
162
163
0
    pDlgroup->isSafePrimeGroup = FALSE;
164
0
    pDlgroup->nMinBitsPriv = 0;
165
0
    pDlgroup->nDefaultBitsPriv = nBitsOfQ;                                     // 0 value possible
166
167
0
    pDlgroup->nBitsOfSeed = nBitsOfQ;                                          // 0 value possible
168
0
    pDlgroup->cbSeed = (pDlgroup->nBitsOfSeed+7)/8;                            // 0 value possible
169
170
0
    pDlgroup->eFipsStandard = SYMCRYPT_DLGROUP_FIPS_NONE;       // This will be set either on generate or import
171
0
    pDlgroup->pHashAlgorithm = NULL;            // Like-wise
172
0
    pDlgroup->dwGenCounter = 0;                 // Like-wise
173
0
    pDlgroup->bIndexGenG = 1;                   // Default: 1
174
175
    // Create SymCrypt objects
176
0
    pbBuffer += sizeof(SYMCRYPT_DLGROUP);
177
178
0
    cbModP = SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfP );
179
0
    SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP );
180
0
    pDlgroup->pmP = SymCryptModulusCreate( pbBuffer, cbModP, pDlgroup->nDigitsOfP );
181
0
    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
0
    if (nBitsOfQ>0)
189
0
    {
190
0
        cbModQ = SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ );
191
0
    }
192
0
    else
193
0
    {
194
0
        cbModQ = cbModP;
195
0
    }
196
0
    SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP + cbModQ );
197
0
    pDlgroup->pbQ = pbBuffer;      // Set the aligned buffer
198
0
    pDlgroup->pmQ = NULL;
199
0
    pbBuffer += cbModQ;
200
201
0
    cbModElement = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
202
0
    SYMCRYPT_ASSERT( cbBuffer > sizeof(SYMCRYPT_DLGROUP) + cbModP + cbModQ + cbModElement );
203
0
    pDlgroup->peG = SymCryptModElementCreate( pbBuffer, cbModElement, pDlgroup->pmP );
204
0
    pbBuffer += cbModElement;
205
206
0
    pDlgroup->pbSeed = pbBuffer;
207
208
    // Setting the magic
209
0
    SYMCRYPT_SET_MAGIC( pDlgroup );
210
211
0
cleanup:
212
0
    return pDlgroup;
213
0
}
214
215
VOID
216
SYMCRYPT_CALL
217
SymCryptDlgroupWipe( _Out_ PSYMCRYPT_DLGROUP pgDst )
218
0
{
219
0
    SymCryptWipe( (PBYTE) pgDst, pgDst->cbTotalSize );
220
0
}
221
222
VOID
223
SYMCRYPT_CALL
224
SymCryptDlgroupCopy(
225
    _In_    PCSYMCRYPT_DLGROUP   pgSrc,
226
    _Out_   PSYMCRYPT_DLGROUP    pgDst )
227
0
{
228
    //
229
    // in-place copy is somewhat common...
230
    //
231
0
    if( pgSrc != pgDst )
232
0
    {
233
0
        pgDst->cbTotalSize = pgSrc->cbTotalSize;
234
0
        pgDst->fHasPrimeQ = pgSrc->fHasPrimeQ;
235
236
0
        pgDst->nBitsOfP = pgSrc->nBitsOfP;
237
0
        pgDst->cbPrimeP = pgSrc->cbPrimeP;
238
0
        pgDst->nDigitsOfP = pgSrc->nDigitsOfP;
239
0
        pgDst->nMaxBitsOfP = pgSrc->nMaxBitsOfP;
240
241
0
        pgDst->nBitsOfQ = pgSrc->nBitsOfQ;
242
0
        pgDst->cbPrimeQ = pgSrc->cbPrimeQ;
243
0
        pgDst->nDigitsOfQ = pgSrc->nDigitsOfQ;
244
0
        pgDst->nMaxBitsOfQ = pgSrc->nMaxBitsOfQ;
245
246
0
        pgDst->isSafePrimeGroup = pgSrc->isSafePrimeGroup;
247
0
        pgDst->nMinBitsPriv = pgSrc->nMinBitsPriv;
248
0
        pgDst->nDefaultBitsPriv = pgSrc->nDefaultBitsPriv;
249
250
0
        pgDst->nBitsOfSeed = pgSrc->nBitsOfSeed;
251
0
        pgDst->cbSeed = pgSrc->cbSeed;
252
253
0
        pgDst->eFipsStandard = pgSrc->eFipsStandard;
254
0
        pgDst->pHashAlgorithm = pgSrc->pHashAlgorithm;
255
0
        pgDst->dwGenCounter = pgSrc->dwGenCounter;
256
0
        pgDst->bIndexGenG = pgSrc->bIndexGenG;
257
0
        pgDst->pbQ = pgSrc->pbQ;
258
259
0
        memcpy( (PBYTE)pgDst + sizeof(SYMCRYPT_DLGROUP), (PCBYTE)pgSrc + sizeof(SYMCRYPT_DLGROUP), pgSrc->cbTotalSize - sizeof(SYMCRYPT_DLGROUP) );
260
0
    }
261
0
}
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
0
{
279
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
280
281
0
    PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
282
0
    UINT32 nBitsOfQ = pDlgroup->nBitsOfQ;
283
0
    UINT32 cbPrimeQ = pDlgroup->cbPrimeQ;
284
0
    PBYTE pbSeed = pDlgroup->pbSeed;
285
0
    UINT32 cbSeed = pDlgroup->cbSeed;
286
287
0
    PSYMCRYPT_INT piDivTwoQ = SymCryptIntFromDivisor(pdDivTwoQ);
288
289
0
    SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
290
0
    PBYTE pbTrHash = NULL;          // Pointer to the truncated hash value
291
0
    PBYTE pbHashExtra = NULL;       // Needed as temp buffer for 186-2
292
293
0
    UINT32 dwShiftBits = (8-nBitsOfQ%8)%8;              // When nBitsOfQ is a multiple of 8 -> dwShiftBits = 0;
294
295
0
    UINT32 carry = 0;
296
297
0
    UNREFERENCED_PARAMETER( cbScratch );
298
0
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR(SymCryptDigitsFromBits(nBitsOfQ+1)),
299
0
                                  SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME(pDlgroup->nDigitsOfQ),
300
0
                                       2 * cbHash )) );
301
0
    SYMCRYPT_ASSERT( cbHash >= cbPrimeQ );
302
303
    // Hash the seed according to the standard specified
304
0
    if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
305
0
    {
306
0
        SYMCRYPT_ASSERT( hashAlgorithm == SymCryptSha1Algorithm );
307
0
        SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX(2*cbHash, cbSeed) );
308
309
        // Hash buffers
310
0
        pbTrHash = pbScratch;
311
0
        pbHashExtra = pbTrHash + cbHash;
312
313
        // Prepare an int for SEED + 1
314
0
        scError = SymCryptIntSetValue( pbSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piDivTwoQ );
315
0
        if (scError != SYMCRYPT_NO_ERROR)
316
0
        {
317
0
            goto cleanup;
318
0
        }
319
320
        // Add 1
321
0
        carry = SymCryptIntAddUint32( piDivTwoQ, 1, piDivTwoQ );
322
0
        if (carry > 0)
323
0
        {
324
            // This should never happen as the size of piDivTwoQ is at least one bit bigger than Q
325
0
            scError = SYMCRYPT_FIPS_FAILURE;
326
0
            goto cleanup;
327
0
        }
328
329
        // (SEED+1) Mod 2^nBitsOfSeed
330
0
        SymCryptIntModPow2( piDivTwoQ, nBitsOfQ, piDivTwoQ );
331
332
        // Get the value into pbTrHash (Notice the cbSeed size)
333
0
        scError = SymCryptIntGetValue( piDivTwoQ, pbTrHash, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST );
334
0
        if (scError != SYMCRYPT_NO_ERROR)
335
0
        {
336
0
            goto cleanup;
337
0
        }
338
339
        // Hash it into pbHashExtra
340
0
        SymCryptHash( hashAlgorithm, pbTrHash, cbPrimeQ, pbHashExtra, cbHash );
341
342
        // Hash the seed
343
0
        SymCryptHash( hashAlgorithm, pbSeed, cbSeed, pbTrHash, cbHash );
344
345
        // Xor the two
346
0
        SymCryptXorBytes( pbTrHash, pbHashExtra, pbTrHash, cbHash );
347
348
0
    }
349
0
    else if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_3)
350
0
    {
351
0
        SYMCRYPT_ASSERT( cbScratch >= cbHash );
352
0
        pbTrHash = pbScratch;
353
0
        SymCryptHash( hashAlgorithm, pbSeed, cbSeed, pbTrHash, cbHash );
354
0
    }
355
0
    else
356
0
    {
357
0
        scError = SYMCRYPT_FIPS_FAILURE;
358
0
        goto cleanup;
359
0
    }
360
361
    // Convert it to (2^{N-1} + (Hash mod 2^{N-1})) | 1
362
0
    pbTrHash += (cbHash-cbPrimeQ);                      // Skip any leading zero bytes
363
0
    pbTrHash[0] &= ((BYTE)0xff >> (dwShiftBits));       // Cut off top bits in the most significant byte
364
0
    pbTrHash[0] |= ((BYTE)0x01 << (7 - dwShiftBits));   // Set the (N-1)-th bit
365
0
    pbTrHash[cbPrimeQ-1] |= ((BYTE)0x01);               // Make the entire number odd
366
367
    // Set the value
368
0
    scError = SymCryptIntSetValue( pbTrHash, cbPrimeQ, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piQ );
369
0
    if (scError != SYMCRYPT_NO_ERROR)
370
0
    {
371
0
        goto cleanup;
372
0
    }
373
374
    // Assume not a prime
375
0
    *pfPrimeQFound = 0;
376
377
    // Fast compositeness check
378
0
    if (SymCryptIntFindSmallDivisor( pTrialDivisionContext, piQ, NULL, 0 ))
379
0
    {
380
0
        goto cleanup;
381
0
    }
382
383
    // IntMillerRabinPrimalityTest requirement:
384
    //      piQ > 3 since nBitsOfQ is bounded by SYMCRYPT_DLGROUP_MIN_BITSIZE_Q
385
0
    *pfPrimeQFound = SymCryptIntMillerRabinPrimalityTest(
386
0
                        piQ,
387
0
                        nBitsOfQ,
388
0
                        DLGROUP_MR_ITERATIONS,
389
0
                        SYMCRYPT_FLAG_DATA_PUBLIC,      // q and p will be public
390
0
                        pbScratch,
391
0
                        cbScratch );
392
393
    // Set pdDivTwoQ
394
0
    if (*pfPrimeQFound)
395
0
    {
396
0
        scError = SymCryptIntCopyMixedSize( piQ, piDivTwoQ );
397
0
        if (scError != SYMCRYPT_NO_ERROR)
398
0
        {
399
0
            goto cleanup;
400
0
        }
401
402
0
        SymCryptIntMulPow2( piDivTwoQ, 1, piDivTwoQ );
403
404
        // IntToDivisor requirement:
405
        //      Q is non-zero as prime --> 2*Q != 0
406
0
        SymCryptIntToDivisor(
407
0
            piDivTwoQ,
408
0
            pdDivTwoQ,
409
0
            4*pDlgroup->nBitsOfP,              // 4*L
410
0
            SYMCRYPT_FLAG_DATA_PUBLIC,
411
0
            pbScratch,
412
0
            cbScratch );
413
0
    }
414
415
0
cleanup:
416
0
    return scError;
417
0
}
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
0
{
434
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
435
436
0
    PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
437
0
    UINT32 nBitsOfP = pDlgroup->nBitsOfP;
438
0
    PBYTE pbSeed = pDlgroup->pbSeed;
439
0
    UINT32 cbSeed = pDlgroup->cbSeed;
440
0
    UINT32 nBitsOfSeed = pDlgroup->nBitsOfSeed;
441
442
0
    SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
443
444
0
    UINT32 counter = 0;
445
446
0
    UINT32 ndDivTwoQ = SymCryptDivisorDigitsizeOfObject( pdDivTwoQ );
447
0
    UINT32 cbIntTwoQ = SymCryptSizeofIntFromDigits( ndDivTwoQ );
448
449
0
    PSYMCRYPT_INT piPersistent = NULL;
450
0
    PSYMCRYPT_INT piRemainder = NULL;
451
452
0
    PBYTE pbHashOutput = NULL;
453
0
    PBYTE pbTempSeed = NULL;
454
455
0
    PBYTE pbW = NULL;
456
0
    UINT32 cbW = pDlgroup->cbPrimeP;
457
458
0
    PBYTE pbWCurr = NULL;
459
0
    SIZE_T cbWBytesLeft = 0;
460
461
0
    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
0
    PBYTE pbScratchInternal = 0;
467
0
    SIZE_T cbScratchInternal = 0;
468
469
0
    UNREFERENCED_PARAMETER( cbScratch );
470
0
    SYMCRYPT_ASSERT( cbScratch >= 2*cbIntTwoQ + cbHash + cbSeed + cbW +
471
0
                                  SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pDlgroup->nDigitsOfP, ndDivTwoQ ),
472
0
                                       SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pDlgroup->nDigitsOfP )) );
473
474
    // Create temporaries
475
0
    pbScratchInternal = pbScratch;
476
0
    cbScratchInternal = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pDlgroup->nDigitsOfP, ndDivTwoQ ),
477
0
                             SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pDlgroup->nDigitsOfP ) );
478
0
    pbScratch += cbScratchInternal;
479
480
0
    piPersistent = SymCryptIntCreate( pbScratch, cbIntTwoQ, ndDivTwoQ );
481
0
    pbScratch += cbIntTwoQ;
482
483
0
    piRemainder = SymCryptIntCreate( pbScratch, cbIntTwoQ, ndDivTwoQ );
484
0
    pbScratch += cbIntTwoQ;
485
486
0
    pbHashOutput = pbScratch;
487
0
    pbScratch += cbHash;
488
489
0
    pbTempSeed = pbScratch;
490
0
    pbScratch += cbSeed;
491
492
0
    pbW = pbScratch;
493
494
    // Set the value for the expression "domain_parameter_seed + offset + j"
495
0
    scError = SymCryptIntSetValue( pbSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piPersistent );
496
0
    if (scError != SYMCRYPT_NO_ERROR)
497
0
    {
498
0
        goto cleanup;
499
0
    }
500
501
    // If the standard is 186-2 add 1 since the strating offset is 2
502
0
    if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
503
0
    {
504
0
        carry = SymCryptIntAddUint32( piPersistent, 1, piPersistent );
505
0
        if (carry!=0)
506
0
        {
507
            // This should never happen as piPersistent has at least one more bit than
508
            // seedLen == nBitsOfQ
509
0
            scError = SYMCRYPT_FIPS_FAILURE;
510
0
            goto cleanup;
511
0
        }
512
513
        // Mod 2^seedlen
514
0
        SymCryptIntModPow2( piPersistent, nBitsOfSeed, piPersistent );
515
0
    }
516
517
0
    *pfPrimePFound = 0;
518
519
0
    for (counter = 0; counter < dwMaxCounter+1; counter++)
520
0
    {
521
0
        cbWBytesLeft = cbW;                         // Bytes left to write
522
0
        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
0
        while (cbWBytesLeft > 0)
525
0
        {
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
0
            carry = SymCryptIntAddUint32( piPersistent, 1, piPersistent );
530
0
            if (carry!=0)
531
0
            {
532
0
                scError = SYMCRYPT_FIPS_FAILURE;
533
0
                goto cleanup;
534
0
            }
535
536
            // Mod 2^seedlen
537
0
            SymCryptIntModPow2( piPersistent, nBitsOfSeed, piPersistent );
538
539
            // Extract piPersistent into a byte array (this will always be equal to domain_parameter_seed + offset + j)
540
0
            scError = SymCryptIntGetValue( piPersistent, pbTempSeed, cbSeed, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST );
541
0
            if (scError != SYMCRYPT_NO_ERROR)
542
0
            {
543
0
                goto cleanup;
544
0
            }
545
546
            // Hash it
547
0
            SymCryptHash( hashAlgorithm, pbTempSeed, cbSeed, pbHashOutput, cbHash );
548
549
0
            if (cbWBytesLeft >= cbHash)
550
0
            {
551
                // Move the entire hash output to the correct location in the pbW buffer
552
0
                memcpy(pbWCurr, pbHashOutput, cbHash );
553
0
            }
554
0
            else
555
0
            {
556
                // Move only the last bytes of the hash output
557
0
                memcpy(pbWCurr, pbHashOutput + cbHash - cbWBytesLeft, cbWBytesLeft );
558
0
            }
559
560
            // Update the positions on the W buffer
561
0
            cbWBytesLeft -= SYMCRYPT_MIN(cbHash,cbWBytesLeft);
562
0
            pbWCurr -= SYMCRYPT_MIN(cbHash,cbWBytesLeft);
563
0
        }
564
565
        // Import the W buffer into P
566
0
        scError = SymCryptIntSetValue( pbW, cbW, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piP );
567
0
        if (scError != SYMCRYPT_NO_ERROR)
568
0
        {
569
0
            goto cleanup;
570
0
        }
571
572
        // Zero-out the top bits of the integer
573
0
        SymCryptIntModPow2( piP, nBitsOfP, piP );
574
575
        // Set the most significant bit
576
0
        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
0
        SymCryptIntDivMod( piP, pdDivTwoQ, NULL, piRemainder, pbScratchInternal, cbScratchInternal );
582
583
0
        if (SymCryptIntIsEqualUint32(piRemainder, 0))
584
0
        {
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
0
            carry = SymCryptIntAddUint32( piP, 1, piP );
589
0
            SYMCRYPT_ASSERT( carry==0 );
590
0
        }
591
0
        else
592
0
        {
593
            // Subtract 1 from c
594
            // We can never get a borrow here because the remainder is not 0.
595
0
            carry = SymCryptIntSubUint32( piRemainder, 1, piRemainder );
596
0
            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
0
            carry = SymCryptIntSubMixedSize( piP, piRemainder, piP );
602
0
            SYMCRYPT_ASSERT( carry==0 );
603
0
        }
604
605
        // Check if smaller than 2^{L-1} by checking the L-1 bit
606
0
        if (SymCryptIntGetBit( piP, nBitsOfP-1 ) == 0)
607
0
        {
608
0
            continue;
609
0
        }
610
611
        // Fast compositeness check
612
0
        if (SymCryptIntFindSmallDivisor( pTrialDivisionContext, piP, NULL, 0 ))
613
0
        {
614
0
            continue;
615
0
        }
616
617
        // IntMillerRabinPrimalityTest requirement:
618
        //      piP > 3 since nBitsOfP is bounded by SYMCRYPT_DLGROUP_MIN_BITSIZE_P
619
0
        *pfPrimePFound = SymCryptIntMillerRabinPrimalityTest(
620
0
                        piP,
621
0
                        nBitsOfP,
622
0
                        DLGROUP_MR_ITERATIONS,
623
0
                        SYMCRYPT_FLAG_DATA_PUBLIC,      // q and p will be public
624
0
                        pbScratchInternal,
625
0
                        cbScratchInternal );
626
627
0
        if (*pfPrimePFound)
628
0
        {
629
0
            *pdwCounter = counter;
630
0
            break;
631
0
        }
632
0
    }
633
0
cleanup:
634
0
    return scError;
635
0
}
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
0
{
646
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
647
648
0
    PCSYMCRYPT_HASH hashAlgorithm = pDlgroup->pHashAlgorithm;
649
0
    PCSYMCRYPT_MODULUS pmP = pDlgroup->pmP;
650
0
    UINT32 nDigitsOfP = pDlgroup->nDigitsOfP;
651
0
    UINT32 nBitsOfP = pDlgroup->nBitsOfP;
652
0
    PCSYMCRYPT_MODULUS pmQ = pDlgroup->pmQ;
653
0
    UINT32 nDigitsOfQ = pDlgroup->nDigitsOfQ;
654
0
    PBYTE pbSeed = pDlgroup->pbSeed;
655
0
    UINT32 cbSeed = pDlgroup->cbSeed;
656
0
    BYTE bIndexGenG = pDlgroup->bIndexGenG;
657
658
0
    SIZE_T cbHash = SymCryptHashResultSize( hashAlgorithm );
659
0
    SYMCRYPT_ASSERT( cbHash == hashAlgorithm->resultSize );
660
0
    SIZE_T cbState = SymCryptHashStateSize( hashAlgorithm );
661
0
    SYMCRYPT_ASSERT( cbState == hashAlgorithm->stateSize );
662
663
0
    UINT16 count = 0;
664
0
    BYTE bTmp = 0;
665
666
0
    PSYMCRYPT_INT piExp = NULL;
667
0
    PSYMCRYPT_INT piRem = NULL;
668
0
    PSYMCRYPT_MODELEMENT peOne = NULL;
669
0
    PBYTE pbState = NULL;
670
0
    PBYTE pbW = NULL;
671
672
0
    UINT32 cbExp = SymCryptSizeofIntFromDigits( nDigitsOfP );
673
0
    UINT32 cbRem = SymCryptSizeofIntFromDigits( nDigitsOfQ );
674
0
    UINT32 cbModElement = SymCryptSizeofModElementFromModulus( pmP );
675
676
0
    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
0
    PBYTE pbScratchInternal = 0;
682
0
    SIZE_T cbScratchInternal = 0;
683
684
0
    UNREFERENCED_PARAMETER( cbScratch );
685
0
    UNREFERENCED_PARAMETER( nDigitsOfQ );
686
687
    // Create temporaries
688
0
    pbScratchInternal = pbScratch;
689
0
    cbScratchInternal = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( nDigitsOfP ),
690
0
                        SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, nDigitsOfQ ),
691
0
                             SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ) ));
692
0
    SYMCRYPT_ASSERT( cbScratch >= cbScratchInternal + cbExp + cbRem );
693
0
    SYMCRYPT_ASSERT( cbScratch >= cbScratchInternal + cbExp + cbModElement + cbHash + cbState );
694
0
    pbScratch += cbScratchInternal;
695
696
0
    piExp = SymCryptIntCreate( pbScratch, cbExp, nDigitsOfP );
697
0
    pbScratch += cbExp;
698
699
0
    piRem = SymCryptIntCreate( pbScratch, cbRem, nDigitsOfQ );
700
701
    // Calculate the exponent e = (p-1)/q
702
0
    borrow = SymCryptIntSubUint32( SymCryptIntFromModulus((PSYMCRYPT_MODULUS)pmP), 1, piExp );
703
0
    if (borrow!=0)
704
0
    {
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
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
708
0
        goto cleanup;
709
0
    }
710
711
0
    SymCryptIntDivMod(
712
0
            piExp,
713
0
            SymCryptDivisorFromModulus( (PSYMCRYPT_MODULUS)pmQ ),
714
0
            piExp,
715
0
            piRem,
716
0
            pbScratchInternal,
717
0
            cbScratchInternal );
718
719
0
    if ( !SymCryptIntIsEqualUint32(piRem, 0) )
720
0
    {
721
        // The only way to get a non-zero remainder is if Q does not divide P-1
722
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
723
0
        goto cleanup;
724
0
    }
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
0
    peOne = SymCryptModElementCreate( pbScratch, cbModElement, pmP);
730
0
    pbScratch += cbModElement;
731
732
0
    pbState = pbScratch;
733
0
    pbScratch += cbState;
734
735
0
    pbW = pbScratch;
736
737
    // Initialize the hash state
738
0
    SymCryptHashInit( hashAlgorithm, pbState );
739
740
    // Set the modelement equal to one
741
0
    SymCryptModElementSetValueUint32( 1, pmP, peOne, pbScratchInternal, cbScratchInternal );
742
743
0
    do
744
0
    {
745
0
        count += 1;
746
747
0
        if (count == 0)
748
0
        {
749
0
            scError = SYMCRYPT_FIPS_FAILURE;
750
0
            goto cleanup;
751
0
        }
752
753
        // Hash the seed
754
0
        SymCryptHashAppend( hashAlgorithm, pbState, pbSeed, cbSeed );
755
756
        // Hash the "ggen" string
757
0
        SymCryptHashAppend( hashAlgorithm, pbState, ggen, sizeof(ggen) );
758
759
        // Hash the index
760
0
        SymCryptHashAppend( hashAlgorithm, pbState, &bIndexGenG, sizeof(bIndexGenG) );
761
762
        // Hash the count (in MSB)
763
0
        bTmp = (BYTE)(count >> 8);
764
0
        SymCryptHashAppend( hashAlgorithm, pbState, &bTmp, sizeof(bTmp) );
765
0
        bTmp = (BYTE)count;
766
0
        SymCryptHashAppend( hashAlgorithm, pbState, &bTmp, sizeof(bTmp) );
767
768
        // Result into W
769
0
        SymCryptHashResult( hashAlgorithm, pbState, pbW, cbHash );
770
771
        // Set this into G
772
0
        scError = SymCryptModElementSetValue(
773
0
                        pbW,
774
0
                        cbHash,
775
0
                        SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
776
0
                        pmP,
777
0
                        peG,
778
0
                        pbScratchInternal,
779
0
                        cbScratchInternal );
780
0
        if (scError != SYMCRYPT_NO_ERROR)
781
0
        {
782
0
            goto cleanup;
783
0
        }
784
785
        // ModExp G in place
786
0
        SymCryptModExp(
787
0
            pmP,
788
0
            peG,
789
0
            piExp,
790
0
            nBitsOfP,
791
0
            SYMCRYPT_FLAG_DATA_PUBLIC,
792
0
            peG,
793
0
            pbScratchInternal,
794
0
            cbScratchInternal );
795
796
0
    } while (SymCryptModElementIsZero( pmP, peG ) || SymCryptModElementIsEqual( pmP, peG, peOne ));
797
798
0
cleanup:
799
0
    return scError;
800
0
}
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
0
{
807
0
    UINT32 nDigitsOfP = SymCryptDigitsFromBits( nBitsOfP );
808
0
    UINT32 nDigitsOfQ = SymCryptDigitsFromBits( nBitsOfQ );
809
0
    UINT32 ndDivTwoQ = SymCryptDigitsFromBits(nBitsOfQ + 1);
810
811
0
    UINT32 cbPrimeP = (nBitsOfP+7)/8;   // Note: The upper bound for nBitsOfP is enforced by SymCryptDigitsFromBits
812
0
    UINT32 cbDivTwoQ = SymCryptSizeofDivisorFromDigits(ndDivTwoQ);
813
0
    UINT32 cbIntTwoQ = SymCryptSizeofIntFromDigits( ndDivTwoQ );
814
0
    UINT32 cbSeed = (nBitsOfQ+7)/8;     // Note: The upper bound for nBitsOfP is enforced by SymCryptDigitsFromBits
815
816
0
    UINT32 cbExp = SymCryptSizeofIntFromDigits( nDigitsOfP );
817
0
    UINT32 cbRem = SymCryptSizeofIntFromDigits( nDigitsOfQ );
818
0
    UINT32 cbModElement = SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( nBitsOfP );
819
820
0
    UINT32 cbHash = (UINT32)SymCryptHashResultSize( pHashAlgorithm );
821
0
    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
0
    return SYMCRYPT_MAX( cbDivTwoQ + SYMCRYPT_MAX(
830
                            // Generate Q
831
0
                            SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( ndDivTwoQ ),
832
0
                            SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( nDigitsOfQ ),
833
0
                                 2 * cbHash)),
834
                            // Generate P
835
0
                            2*cbIntTwoQ + cbHash + cbSeed + cbPrimeP +
836
0
                            SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, ndDivTwoQ ),
837
0
                                 SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( nDigitsOfP )) ),
838
0
           SYMCRYPT_MAX(
839
                // Convert P and Q to moduli
840
0
                SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS( nDigitsOfP ),
841
                // Generate GenG
842
0
                cbExp + SYMCRYPT_MAX(cbRem, cbModElement + cbState + cbHash) +
843
0
                SYMCRYPT_MAX(SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( nDigitsOfP ),
844
0
                SYMCRYPT_MAX(SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( nDigitsOfP, nDigitsOfQ ),
845
0
                    SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ) )) ));
846
0
}
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
0
{
855
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
856
857
0
    PBYTE pbScratch = NULL;
858
0
    SIZE_T cbScratch = 0;
859
0
    PBYTE pbScratchInternal = NULL;
860
0
    SIZE_T cbScratchInternal = 0;
861
862
0
    UINT32 fPrimeQFound = 0;
863
0
    UINT32 fPrimePFound = 0;
864
865
    // A divisor equal to 2*Q will be needed for the generation of P
866
0
    PSYMCRYPT_DIVISOR pdDivTwoQ = NULL;
867
0
    UINT32 cbDivTwoQ = 0;
868
0
    UINT32 ndDivTwoQ = 0;
869
870
0
    UINT32 nBitsOfP = 0;
871
0
    UINT32 nDigitsOfP = 0;
872
0
    UINT32 nBitsOfQ = 0;
873
0
    UINT32 nDigitsOfQ = 0;
874
875
0
    PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext = NULL;
876
877
0
    if (fipsStandard == SYMCRYPT_DLGROUP_FIPS_NONE)
878
0
    {
879
0
        fipsStandard = SYMCRYPT_DLGROUP_FIPS_LATEST;
880
0
    }
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
0
    if (fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
893
0
    {
894
0
        if (hashAlgorithm != NULL)
895
0
        {
896
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
897
0
            goto cleanup;
898
0
        }
899
900
0
        pDlgroup->eFipsStandard = fipsStandard;
901
0
        hashAlgorithm = SymCryptSha1Algorithm;
902
0
    }
903
0
    else
904
0
    {
905
0
        if (hashAlgorithm == NULL)
906
0
        {
907
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
908
0
            goto cleanup;
909
0
        }
910
911
0
        pDlgroup->eFipsStandard = fipsStandard;
912
0
    }
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
0
    if (pDlgroup->nBitsOfQ == 0)
918
0
    {
919
0
        pDlgroup->nBitsOfQ = SymCryptDlgroupCalculateBitsizeOfQ(pDlgroup->nBitsOfP);
920
921
0
        if (pDlgroup->nBitsOfQ > pDlgroup->nMaxBitsOfQ)
922
0
        {
923
0
            scError = SYMCRYPT_FIPS_FAILURE;        // This hits when nMaxBitsOfQ = (nBitsOfP-1) <= 160
924
0
            goto cleanup;
925
0
        }
926
927
0
        pDlgroup->cbPrimeQ = (pDlgroup->nBitsOfQ + 7)/8;
928
0
        pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits( pDlgroup->nBitsOfQ );
929
0
        pDlgroup->nDefaultBitsPriv = pDlgroup->nBitsOfQ;
930
0
        pDlgroup->nBitsOfSeed = pDlgroup->nBitsOfQ;
931
0
        pDlgroup->cbSeed = (pDlgroup->nBitsOfSeed+7)/8;
932
0
    }
933
934
    // Helper variables
935
0
    nBitsOfP = pDlgroup->nBitsOfP;
936
0
    nDigitsOfP = pDlgroup->nDigitsOfP;
937
0
    nBitsOfQ = pDlgroup->nBitsOfQ;
938
0
    nDigitsOfQ = pDlgroup->nDigitsOfQ;
939
940
    // Create the modulus Q
941
0
    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
0
    if ( (8*((UINT32)SymCryptHashResultSize( hashAlgorithm )) < nBitsOfQ) ||
947
0
         (8*((UINT32)SymCryptHashResultSize( hashAlgorithm )) > nBitsOfP) )
948
0
    {
949
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
950
0
        goto cleanup;
951
0
    }
952
953
    // Set the group's hash algorithm
954
0
    pDlgroup->pHashAlgorithm = hashAlgorithm;
955
956
    // Calculate sizes for the 2*Q divisor
957
0
    ndDivTwoQ = SymCryptDigitsFromBits(nBitsOfQ + 1);
958
0
    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
0
    cbScratch = SymCryptDlgroupScratchSpace_FIPS( nBitsOfP, nBitsOfQ, hashAlgorithm );
970
0
    pbScratch = SymCryptCallbackAlloc(cbScratch);
971
0
    if (pbScratch==NULL)
972
0
    {
973
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
974
0
        goto cleanup;
975
0
    }
976
977
    // Create a divisor 2*Q (needed for the generation of P)
978
0
    pdDivTwoQ = SymCryptDivisorCreate( pbScratch, cbDivTwoQ, ndDivTwoQ );
979
0
    pbScratchInternal = pbScratch + cbDivTwoQ;
980
0
    cbScratchInternal = cbScratch - cbDivTwoQ;
981
982
    // Create a trial division context for both P and Q
983
0
    pTrialDivisionContext = SymCryptCreateTrialDivisionContext( pDlgroup->nDigitsOfP );
984
0
    if (pTrialDivisionContext == NULL)
985
0
    {
986
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
987
0
        goto cleanup;
988
0
    }
989
990
0
    do
991
0
    {
992
0
        do
993
0
        {
994
            // Fill the seed buffer in the DLGroup with seedlen bits
995
0
            scError = SymCryptCallbackRandom( pDlgroup->pbSeed, pDlgroup->cbSeed );
996
0
            if (scError != SYMCRYPT_NO_ERROR)
997
0
            {
998
0
                goto cleanup;
999
0
            }
1000
1001
            // Zero-out the top bits if needed
1002
0
            if ((pDlgroup->nBitsOfSeed)%8 != 0)
1003
0
            {
1004
0
                pDlgroup->pbSeed[0] &= ((BYTE)0xff >> (8 - (pDlgroup->nBitsOfSeed)%8));
1005
0
            }
1006
1007
0
            scError = SymCryptDlgroupGeneratePrimeQ_FIPS(
1008
0
                            pDlgroup,
1009
0
                            pTrialDivisionContext,
1010
0
                            &fPrimeQFound,
1011
0
                            SymCryptIntFromModulus(pDlgroup->pmQ),
1012
0
                            pdDivTwoQ,
1013
0
                            pbScratchInternal,
1014
0
                            cbScratchInternal );
1015
0
            if (scError != SYMCRYPT_NO_ERROR)
1016
0
            {
1017
0
                goto cleanup;
1018
0
            }
1019
0
        }
1020
0
        while (fPrimeQFound == 0);
1021
1022
0
        scError = SymCryptDlgroupGeneratePrimeP_FIPS(
1023
0
                        pDlgroup,
1024
0
                        pdDivTwoQ,
1025
0
                        4*nBitsOfP - 1,
1026
0
                        pTrialDivisionContext,
1027
0
                        &fPrimePFound,
1028
0
                        SymCryptIntFromModulus(pDlgroup->pmP),
1029
0
                        &(pDlgroup->dwGenCounter),
1030
0
                        pbScratchInternal,
1031
0
                        cbScratchInternal );
1032
0
        if (scError != SYMCRYPT_NO_ERROR)
1033
0
        {
1034
0
            goto cleanup;
1035
0
        }
1036
0
    }
1037
0
    while (fPrimePFound == 0);
1038
1039
    // Specify that we have a Q
1040
0
    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
0
    SymCryptIntToModulus(
1046
0
        SymCryptIntFromModulus( pDlgroup->pmP ),
1047
0
        pDlgroup->pmP,
1048
0
        1000*nBitsOfP,        // Average operations
1049
0
        SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1050
0
        pbScratch,
1051
0
        cbScratch );
1052
1053
0
    SymCryptIntToModulus(
1054
0
        SymCryptIntFromModulus( pDlgroup->pmQ ),
1055
0
        pDlgroup->pmQ,
1056
0
        1000*nBitsOfP,        // Average operations
1057
0
        SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1058
0
        pbScratch,
1059
0
        cbScratch );
1060
1061
    // Generate G
1062
0
    scError = SymCryptDlgroupGenerateGenG_FIPS( pDlgroup, pDlgroup->peG, pbScratch, cbScratch );
1063
0
    if (scError != SYMCRYPT_NO_ERROR)
1064
0
    {
1065
0
        goto cleanup;
1066
0
    }
1067
1068
0
cleanup:
1069
0
    if (pTrialDivisionContext!=NULL)
1070
0
    {
1071
0
        SymCryptFreeTrialDivisionContext( pTrialDivisionContext );
1072
0
    }
1073
1074
0
    if (pbScratch!=NULL)
1075
0
    {
1076
0
        SymCryptWipe( pbScratch, cbScratch );
1077
0
        SymCryptCallbackFree( pbScratch );
1078
0
    }
1079
0
    return scError;
1080
0
}
1081
1082
SYMCRYPT_ERROR
1083
SYMCRYPT_CALL
1084
SymCryptDlgroupSetValueSafePrime(
1085
            SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE   dhSafePrimeType,
1086
    _Inout_ PSYMCRYPT_DLGROUP                   pDlgroup )
1087
0
{
1088
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1089
1090
0
    PBYTE pbScratch = NULL;
1091
0
    SIZE_T cbScratch = 0;
1092
1093
0
    PCSYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS safePrimeParams = NULL;
1094
1095
0
    UINT32 i;
1096
0
    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
0
    UINT32 nMaxBitsOfP = SYMCRYPT_MIN(pDlgroup->nMaxBitsOfP, pDlgroup->nMaxBitsOfQ+1);
1100
0
    UINT32 nMaxDigitsOfP;
1101
1102
0
    if ( dhSafePrimeType == SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE_NONE )
1103
0
    {
1104
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1105
0
        goto cleanup;
1106
0
    }
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
0
    for ( i=0; i<SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT; i++ )
1112
0
    {
1113
0
        if ( SymCryptNamedSafePrimeGroups[i]->eDhSafePrimeType == dhSafePrimeType &&
1114
0
             SymCryptNamedSafePrimeGroups[i]->nBitsOfP <= nMaxBitsOfP )
1115
0
        {
1116
0
            safePrimeParams = SymCryptNamedSafePrimeGroups[i];
1117
0
            break;
1118
0
        }
1119
0
    }
1120
1121
0
    if (safePrimeParams == NULL)
1122
0
    {
1123
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1124
0
        goto cleanup;
1125
0
    }
1126
1127
0
    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
0
    cbScratch = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(nMaxDigitsOfP),
1137
0
        SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(nMaxDigitsOfP) );
1138
0
    pbScratch = SymCryptCallbackAlloc( cbScratch );
1139
0
    if (pbScratch==NULL)
1140
0
    {
1141
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1142
0
        goto cleanup;
1143
0
    }
1144
1145
    // Set fields marking the Dlgroup as being a named safe-prime group
1146
0
    pDlgroup->isSafePrimeGroup  = TRUE;
1147
0
    pDlgroup->eFipsStandard     = SYMCRYPT_DLGROUP_FIPS_NONE;
1148
0
    pDlgroup->nMinBitsPriv      = safePrimeParams->nMinBitsPriv;
1149
0
    pDlgroup->nDefaultBitsPriv  = safePrimeParams->nDefaultBitsPriv;
1150
1151
    // Ensure that fields which don't apply to named safe-prime groups are cleared
1152
0
    pDlgroup->pHashAlgorithm = NULL;
1153
0
    pDlgroup->dwGenCounter = 0;
1154
1155
0
    pDlgroup->nBitsOfSeed = 0;
1156
0
    pDlgroup->pbSeed = NULL;
1157
0
    pDlgroup->cbSeed = 0;
1158
1159
    // Set the bitsize and bytesize of P
1160
0
    pDlgroup->nBitsOfP = safePrimeParams->nBitsOfP;
1161
0
    pDlgroup->cbPrimeP = (safePrimeParams->nBitsOfP + 7)/ 8;
1162
0
    pDlgroup->nDigitsOfP = SymCryptDigitsFromBits(safePrimeParams->nBitsOfP);
1163
1164
    // Set the bitsize and bytesize of Q
1165
0
    nBitsOfQ = pDlgroup->nBitsOfP - 1;
1166
0
    pDlgroup->nBitsOfQ = nBitsOfQ;
1167
0
    pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1168
0
    pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
1169
0
    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
0
    pDlgroup->pmP = SymCryptModulusCreate( (PBYTE) pDlgroup->pmP, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfP ), pDlgroup->nDigitsOfP );
1178
1179
0
    scError = SymCryptIntSetValue( safePrimeParams->pcbPrimeP, pDlgroup->cbPrimeP, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, SymCryptIntFromModulus(pDlgroup->pmP) );
1180
0
    if (scError!=SYMCRYPT_NO_ERROR)
1181
0
    {
1182
0
        goto cleanup;
1183
0
    }
1184
1185
    // IntToModulus requirement:
1186
    //      nBitsOfP >= SYMCRYPT_DLGROUP_MIN_BITSIZE_P --> P > 0
1187
0
    SymCryptIntToModulus(
1188
0
        SymCryptIntFromModulus( pDlgroup->pmP ),
1189
0
        pDlgroup->pmP,
1190
0
        1000*pDlgroup->nBitsOfP,        // Average operations
1191
0
        SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1192
0
        pbScratch,
1193
0
        cbScratch );
1194
1195
    //
1196
    // Prime Q
1197
    //
1198
1199
    // Create the modulus Q
1200
0
    pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ ), pDlgroup->nDigitsOfQ );
1201
1202
    // Q = floor( P / 2 )
1203
0
    SymCryptIntShr1( 0, SymCryptIntFromModulus(pDlgroup->pmP), SymCryptIntFromModulus(pDlgroup->pmQ) );
1204
1205
    // IntToModulus requirement:
1206
    //      nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1207
0
    SymCryptIntToModulus(
1208
0
        SymCryptIntFromModulus( pDlgroup->pmQ ),
1209
0
        pDlgroup->pmQ,
1210
0
        1000*nBitsOfQ,        // Average operations
1211
0
        SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1212
0
        pbScratch,
1213
0
        cbScratch );
1214
1215
    //
1216
    // Generator G
1217
    //
1218
1219
    // G to 2
1220
0
    SymCryptModElementSetValueUint32( 2, pDlgroup->pmP, pDlgroup->peG, pbScratch, cbScratch );
1221
1222
0
cleanup:
1223
0
    if (pbScratch!=NULL)
1224
0
    {
1225
0
        SymCryptWipe( pbScratch, cbScratch );
1226
0
        SymCryptCallbackFree( pbScratch );
1227
0
    }
1228
0
    return scError;
1229
0
}
1230
1231
BOOLEAN
1232
SYMCRYPT_CALL
1233
SymCryptDlgroupIsSame(
1234
    _In_    PCSYMCRYPT_DLGROUP  pDlgroup1,
1235
    _In_    PCSYMCRYPT_DLGROUP  pDlgroup2 )
1236
0
{
1237
0
    BOOLEAN fIsSameGroup = FALSE;
1238
1239
0
    if ( pDlgroup1 == pDlgroup2 )
1240
0
    {
1241
0
        fIsSameGroup = TRUE;
1242
0
        goto cleanup;
1243
0
    }
1244
1245
0
    if ( (pDlgroup1->nBitsOfP != pDlgroup2->nBitsOfP) ||
1246
0
         (pDlgroup1->nDigitsOfP != pDlgroup2->nDigitsOfP) ||
1247
0
         !SymCryptIntIsEqual ( SymCryptIntFromModulus(pDlgroup1->pmP), SymCryptIntFromModulus(pDlgroup2->pmP) ) ||
1248
0
         !SymCryptModElementIsEqual ( pDlgroup1->pmP, pDlgroup1->peG, pDlgroup2->peG ))
1249
0
    {
1250
0
        goto cleanup;
1251
0
    }
1252
1253
0
    fIsSameGroup = TRUE;
1254
1255
0
cleanup:
1256
0
    return fIsSameGroup;
1257
0
}
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
0
{
1268
0
    if (pcbPrimeP!=NULL)
1269
0
    {
1270
0
        *pcbPrimeP = pDlgroup->cbPrimeP;
1271
0
    }
1272
1273
0
    if (pcbPrimeQ!=NULL)
1274
0
    {
1275
0
        *pcbPrimeQ = pDlgroup->cbPrimeQ;     // This returns 0 if the group does not have a prime Q
1276
0
    }
1277
1278
0
    if (pcbGenG!=NULL)
1279
0
    {
1280
0
        *pcbGenG = pDlgroup->cbPrimeP;
1281
0
    }
1282
1283
0
    if (pcbSeed!=NULL)
1284
0
    {
1285
0
        *pcbSeed = pDlgroup->cbSeed;        // This returns 0 if the group does not have a prime Q
1286
0
    }
1287
0
}
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
0
{
1296
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1297
1298
0
    PBYTE  pbScratchInternal;
1299
0
    SIZE_T cbScratchInternal;
1300
1301
0
    PSYMCRYPT_INT piTemp = NULL;
1302
0
    UINT32 cbTemp;
1303
0
    UINT32 i;
1304
0
    UINT32 nBitsOfQ;
1305
0
    PCSYMCRYPT_DLGROUP_DH_SAFEPRIME_PARAMS safePrimeParams = NULL;
1306
1307
    // Check whether bottom 64b of P all 1 - as first cheap check
1308
0
    if ( SymCryptIntGetValueLsbits64( SymCryptIntFromModulus(pDlgroup->pmP) ) != ((UINT64) -1) )
1309
0
    {
1310
0
        goto cleanup; // Not a named safe-prime group
1311
0
    }
1312
1313
0
    cbTemp = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfP );
1314
0
    SYMCRYPT_ASSERT( cbScratch >= cbTemp );
1315
1316
    // Create an integer piTemp
1317
0
    piTemp = SymCryptIntCreate( pbScratch, cbTemp, pDlgroup->nDigitsOfP );
1318
0
    pbScratchInternal = pbScratch + cbTemp;
1319
0
    cbScratchInternal = cbScratch - cbTemp;
1320
1321
    // Set piTemp to the generator G (this will fail if the number cannot fit in the object)
1322
0
    SymCryptModElementToInt( pDlgroup->pmP, pDlgroup->peG, piTemp, pbScratchInternal, cbScratchInternal );
1323
1324
    // Generator must be 2 mod P
1325
0
    if ( !SymCryptIntIsEqualUint32( piTemp, 2 ) )
1326
0
    {
1327
0
        goto cleanup; // Not a named safe-prime group
1328
0
    }
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
0
    for ( i=0; i<SYMCRYPT_DH_SAFEPRIME_GROUP_COUNT; i++ )
1333
0
    {
1334
0
        if ( SymCryptNamedSafePrimeGroups[i]->nBitsOfP == pDlgroup->nBitsOfP )
1335
0
        {
1336
            // Set piTemp to the named safe-prime group's P (this will fail if the number cannot fit in the object)
1337
0
            SymCryptIntSetValue( SymCryptNamedSafePrimeGroups[i]->pcbPrimeP, pDlgroup->cbPrimeP, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTemp );
1338
1339
0
            if ( SymCryptIntIsEqual( piTemp, SymCryptIntFromModulus(pDlgroup->pmP) ) )
1340
0
            {
1341
0
                safePrimeParams = SymCryptNamedSafePrimeGroups[i];
1342
0
                break;
1343
0
            }
1344
0
        }
1345
0
    }
1346
1347
    // If we found a match in the previous loop, auto-populate appropriate fields in pDlGroup
1348
0
    if (safePrimeParams != NULL)
1349
0
    {
1350
0
        if ( pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2 ||
1351
0
             pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_3 )
1352
0
        {
1353
            // Inappropriate use of named safe-prime groups
1354
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
1355
0
            goto cleanup;
1356
0
        }
1357
1358
        // Set fields marking the Dlgroup as being a named safe-prime group
1359
0
        pDlgroup->isSafePrimeGroup  = TRUE;
1360
0
        pDlgroup->eFipsStandard     = SYMCRYPT_DLGROUP_FIPS_NONE;
1361
0
        pDlgroup->nMinBitsPriv      = safePrimeParams->nMinBitsPriv;
1362
0
        pDlgroup->nDefaultBitsPriv  = safePrimeParams->nDefaultBitsPriv;
1363
1364
        // Ensure that fields which don't apply to named safe-prime groups are cleared
1365
0
        pDlgroup->pHashAlgorithm = NULL;
1366
0
        pDlgroup->dwGenCounter = 0;
1367
1368
0
        pDlgroup->nBitsOfSeed = 0;
1369
0
        pDlgroup->pbSeed = NULL;
1370
0
        pDlgroup->cbSeed = 0;
1371
1372
        // Set the bitsize and bytesize of Q
1373
0
        nBitsOfQ = pDlgroup->nBitsOfP - 1;
1374
0
        pDlgroup->nBitsOfQ = nBitsOfQ;
1375
0
        pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1376
0
        pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
1377
1378
        // Create the modulus Q
1379
0
        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
0
        SymCryptIntShr1( 0, piTemp, piTemp );
1383
1384
        // Set the prime Q
1385
0
        scError = SymCryptIntCopyMixedSize( piTemp, SymCryptIntFromModulus(pDlgroup->pmQ) );
1386
0
        if (scError!=SYMCRYPT_NO_ERROR)
1387
0
        {
1388
0
            goto cleanup;
1389
0
        }
1390
1391
        // IntToModulus requirement:
1392
        //      nBitsOfQ >= SYMCRYPT_DLGROUP_MIN_BITSIZE_Q --> Q > 0
1393
0
        SymCryptIntToModulus(
1394
0
            SymCryptIntFromModulus( pDlgroup->pmQ ),
1395
0
            pDlgroup->pmQ,
1396
0
            1000*nBitsOfQ,        // Average operations
1397
0
            SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1398
0
            pbScratch,
1399
0
            cbScratch );
1400
1401
0
        pDlgroup->fHasPrimeQ = TRUE;
1402
0
    }
1403
1404
0
cleanup:
1405
0
    return scError;
1406
0
}
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
0
{
1425
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1426
1427
0
    PBYTE pbScratch = NULL;
1428
0
    SIZE_T cbScratch = 0;
1429
0
    SIZE_T cbScratchVerify = 0;
1430
1431
0
    PSYMCRYPT_INT piTemp = NULL;
1432
1433
0
    UINT32 nBitsOfP = 0;
1434
0
    UINT32 nBitsOfQ = 0;
1435
1436
0
    UINT32 nMaxDigitsOfP = SymCryptDigitsFromBits(pDlgroup->nMaxBitsOfP);
1437
0
    UINT32 nMaxDigitsOfQ = SymCryptDigitsFromBits(pDlgroup->nMaxBitsOfQ);
1438
1439
0
    PCSYMCRYPT_TRIALDIVISION_CONTEXT pTrialDivisionContext = NULL;
1440
1441
    // Make sure that the inputs make sense
1442
0
    if ( (pbPrimeP==NULL) || (cbPrimeP==0) ||       // Prime P is needed
1443
0
         ((pbGenG==NULL)&&(cbGenG>0)) ||
1444
0
         ((pbPrimeQ==NULL)&&(cbPrimeQ>0)) ||
1445
0
         ((pbGenG==NULL)&&(pbPrimeQ==NULL)) ||      // We can't have both Q and G missing
1446
0
         ((pbSeed==NULL)&&(cbSeed>0)) )
1447
0
    {
1448
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1449
0
        goto cleanup;
1450
0
    }
1451
1452
    // FIPS 186-4 verification is needed
1453
0
    if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE)
1454
0
    {
1455
        // Make sure we have what we need
1456
0
        if ((pbPrimeQ == NULL)||
1457
0
            (cbPrimeQ == 0) ||
1458
0
            (pbSeed == NULL) ||
1459
0
            (cbSeed == 0) ||
1460
0
            ((fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2) && (pHashAlgorithm != NULL)) ||
1461
0
            ((fipsStandard != SYMCRYPT_DLGROUP_FIPS_186_2) && (pHashAlgorithm == NULL)) )
1462
0
        {
1463
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1464
0
            goto cleanup;
1465
0
        }
1466
0
    }
1467
1468
    // Set the hashAlgorithm
1469
0
    if ( (fipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2) ||
1470
0
         ((pHashAlgorithm==NULL) && (pbGenG == NULL)) )
1471
0
    {
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
0
        pDlgroup->pHashAlgorithm = SymCryptSha1Algorithm;
1477
0
    }
1478
0
    else
1479
0
    {
1480
0
        pDlgroup->pHashAlgorithm = pHashAlgorithm;
1481
0
    }
1482
1483
0
    if ( (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE) || (pbGenG == NULL))
1484
0
    {
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
0
        cbScratchVerify = SymCryptDlgroupScratchSpace_FIPS( pDlgroup->nMaxBitsOfP, pDlgroup->nMaxBitsOfQ, pDlgroup->pHashAlgorithm ) +
1490
0
                          SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfP),
1491
0
                          SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfQ),
1492
0
                               2*SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS(nMaxDigitsOfP)));
1493
0
    }
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
0
    cbScratch = SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(nMaxDigitsOfP) +
1505
0
                    SYMCRYPT_MAX( SymCryptSizeofIntFromDigits(nMaxDigitsOfQ),
1506
0
                    SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(nMaxDigitsOfP) ),
1507
0
                     cbScratchVerify );
1508
0
    pbScratch = SymCryptCallbackAlloc( cbScratch );
1509
0
    if (pbScratch==NULL)
1510
0
    {
1511
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1512
0
        goto cleanup;
1513
0
    }
1514
1515
    //
1516
    // Prime P
1517
    //
1518
1519
    // Set the prime P (this will fail if the number cannot fit in the object)
1520
0
    scError = SymCryptIntSetValue( pbPrimeP, cbPrimeP, numFormat, SymCryptIntFromModulus(pDlgroup->pmP) );
1521
0
    if (scError!=SYMCRYPT_NO_ERROR)
1522
0
    {
1523
0
        goto cleanup;
1524
0
    }
1525
1526
    // Check the bitsize of value
1527
0
    nBitsOfP = SymCryptIntBitsizeOfValue(SymCryptIntFromModulus(pDlgroup->pmP));
1528
0
    if ( nBitsOfP > pDlgroup->nMaxBitsOfP)
1529
0
    {
1530
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1531
0
        goto cleanup;
1532
0
    }
1533
1534
0
    if (nBitsOfP < SYMCRYPT_DLGROUP_MIN_BITSIZE_P)
1535
0
    {
1536
0
        scError = SYMCRYPT_WRONG_KEY_SIZE;
1537
0
        goto cleanup;
1538
0
    }
1539
1540
    // FIPS 186-4 verification is needed
1541
    // Check genCounter is not too big
1542
0
    if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE &&
1543
0
        genCounter > 4*nBitsOfP-1 )
1544
0
    {
1545
0
        scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1546
0
        goto cleanup;
1547
0
    }
1548
1549
0
    if( (SymCryptIntGetValueLsbits32( SymCryptIntFromModulus( pDlgroup->pmP ) ) & 1) == 0 )
1550
0
    {
1551
        // P is even, when it should be a prime of at least 32 bits
1552
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1553
0
        goto cleanup;
1554
0
    }
1555
1556
    // Set the bitsize and bytesize of the value
1557
0
    pDlgroup->nBitsOfP = nBitsOfP;
1558
0
    pDlgroup->cbPrimeP = (nBitsOfP + 7)/8;
1559
1560
    // IntToModulus requirement:
1561
    //      nBitsOfP >= SYMCRYPT_DLGROUP_MIN_BITSIZE_P --> P > 0
1562
0
    SymCryptIntToModulus(
1563
0
        SymCryptIntFromModulus( pDlgroup->pmP ),
1564
0
        pDlgroup->pmP,
1565
0
        1000*nBitsOfP,        // Average operations
1566
0
        SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1567
0
        pbScratch,
1568
0
        cbScratch );
1569
1570
    //
1571
    // Prime Q
1572
    //
1573
1574
    // Wiping of previous (optional) parameters related to Q
1575
0
    if (pDlgroup->pmQ != NULL)
1576
0
    {
1577
0
        SymCryptModulusWipe( pDlgroup->pmQ );
1578
0
    }
1579
0
    if (pDlgroup->cbSeed != 0)
1580
0
    {
1581
0
        SymCryptWipe( pDlgroup->pbSeed, pDlgroup->cbSeed);
1582
0
    }
1583
1584
0
    if (pbPrimeQ != NULL)
1585
0
    {
1586
        // Create an integer piTemp
1587
0
        piTemp = SymCryptIntCreate( pbScratch, cbScratch, nMaxDigitsOfQ );
1588
1589
        // Set the prime Q (this will fail if the number cannot fit in the object)
1590
0
        scError = SymCryptIntSetValue( pbPrimeQ, cbPrimeQ, numFormat, piTemp );
1591
0
        if (scError!=SYMCRYPT_NO_ERROR)
1592
0
        {
1593
0
            goto cleanup;
1594
0
        }
1595
1596
        // Check the bitsize of value
1597
0
        nBitsOfQ = SymCryptIntBitsizeOfValue(piTemp);
1598
0
        if ( nBitsOfQ > pDlgroup->nMaxBitsOfQ)
1599
0
        {
1600
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
1601
0
            goto cleanup;
1602
0
        }
1603
1604
0
        if (nBitsOfQ < SYMCRYPT_DLGROUP_MIN_BITSIZE_Q)
1605
0
        {
1606
0
            scError = SYMCRYPT_WRONG_KEY_SIZE;
1607
0
            goto cleanup;
1608
0
        }
1609
1610
0
        if( (SymCryptIntGetValueLsbits32( piTemp ) & 1) == 0 )
1611
0
        {
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
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
1616
0
            goto cleanup;
1617
0
        }
1618
1619
        // Set the bitsize and bytesize of the value
1620
0
        pDlgroup->nBitsOfQ = nBitsOfQ;
1621
0
        pDlgroup->cbPrimeQ = (nBitsOfQ + 7)/8;
1622
0
        pDlgroup->nDigitsOfQ = SymCryptDigitsFromBits(nBitsOfQ);
1623
0
        pDlgroup->nDefaultBitsPriv = nBitsOfQ;
1624
0
        pDlgroup->nBitsOfSeed = nBitsOfQ;
1625
0
        pDlgroup->cbSeed = (nBitsOfQ+7)/8;
1626
1627
        // Create the modulus Q
1628
0
        pDlgroup->pmQ = SymCryptModulusCreate( pDlgroup->pbQ, SymCryptSizeofModulusFromDigits( pDlgroup->nDigitsOfQ ), pDlgroup->nDigitsOfQ );
1629
1630
        // Set the prime Q
1631
0
        scError = SymCryptIntCopyMixedSize( piTemp, SymCryptIntFromModulus(pDlgroup->pmQ) );
1632
0
        if (scError!=SYMCRYPT_NO_ERROR)
1633
0
        {
1634
0
            goto cleanup;
1635
0
        }
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
0
        SymCryptIntToModulus(
1642
0
            SymCryptIntFromModulus( pDlgroup->pmQ ),
1643
0
            pDlgroup->pmQ,
1644
0
            1000*nBitsOfP,        // Average operations
1645
0
            SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
1646
0
            pbScratch,
1647
0
            cbScratch );
1648
1649
0
        pDlgroup->fHasPrimeQ = TRUE;
1650
0
    }
1651
0
    else
1652
0
    {
1653
        // Clear all info about Q
1654
0
        pDlgroup->cbPrimeQ = 0;
1655
0
        pDlgroup->nBitsOfQ = 0;
1656
0
        pDlgroup->nDigitsOfQ = 0;
1657
1658
0
        pDlgroup->nDefaultBitsPriv = 0;
1659
0
        pDlgroup->nBitsOfSeed = 0;
1660
0
        pDlgroup->cbSeed = 0;
1661
1662
0
        pDlgroup->pmQ = NULL;
1663
0
        pDlgroup->fHasPrimeQ = FALSE;
1664
0
    }
1665
1666
0
    pDlgroup->isSafePrimeGroup = FALSE;
1667
0
    pDlgroup->nMinBitsPriv = 0;
1668
1669
    //
1670
    // Provided Generator G
1671
    //
1672
0
    if (pbGenG != NULL)
1673
0
    {
1674
        // Set the generator G (this will fail if the number cannot fit in the object)
1675
0
        scError = SymCryptModElementSetValue( pbGenG, cbGenG, numFormat, pDlgroup->pmP, pDlgroup->peG, pbScratch, cbScratch );
1676
0
        if (scError!=SYMCRYPT_NO_ERROR)
1677
0
        {
1678
0
            goto cleanup;
1679
0
        }
1680
1681
0
        scError = SymCryptDlgroupAutoCompleteNamedSafePrimeGroup( pDlgroup, pbScratch, cbScratch );
1682
0
        if (scError!=SYMCRYPT_NO_ERROR)
1683
0
        {
1684
0
            goto cleanup;
1685
0
        }
1686
1687
        // Successfully detected, validated and autocompleted named safe-prime group
1688
0
        if (pDlgroup->isSafePrimeGroup)
1689
0
        {
1690
0
            goto cleanup;
1691
0
        }
1692
0
    }
1693
1694
    //
1695
    //  Verification data (this has to be done before possibly generating G)
1696
    //
1697
1698
    // Set the FIPS standard
1699
0
    pDlgroup->eFipsStandard = fipsStandard;
1700
1701
    // Set the seed
1702
0
    if (pbSeed != NULL)
1703
0
    {
1704
0
        if (cbSeed != pDlgroup->cbSeed)
1705
0
        {
1706
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
1707
0
            goto cleanup;
1708
0
        }
1709
0
        memcpy( pDlgroup->pbSeed, pbSeed, cbSeed );
1710
0
    }
1711
1712
    // Set the genCounter
1713
0
    pDlgroup->dwGenCounter = genCounter;
1714
1715
    //
1716
    // Generator G
1717
    //
1718
1719
0
    if (pbGenG == NULL)
1720
0
    {
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
0
        if (pbSeed==NULL)
1732
0
        {
1733
0
            SymCryptCallbackRandom(pDlgroup->pbSeed, pDlgroup->cbSeed);
1734
0
        }
1735
1736
0
        scError = SymCryptDlgroupGenerateGenG_FIPS(
1737
0
                        pDlgroup,
1738
0
                        pDlgroup->peG,
1739
0
                        pbScratch,
1740
0
                        cbScratch );
1741
0
        if (scError!=SYMCRYPT_NO_ERROR)
1742
0
        {
1743
0
            goto cleanup;
1744
0
        }
1745
0
    }
1746
1747
1748
    // Verification
1749
0
    if (fipsStandard != SYMCRYPT_DLGROUP_FIPS_NONE)
1750
0
    {
1751
        // Verification
1752
0
        PBYTE pbScratchInternal = pbScratch;
1753
0
        SIZE_T cbScratchInternal = cbScratch;
1754
1755
0
        UINT32 ndDivTwoQ = 0;
1756
0
        UINT32 cbDivTwoQ = 0;
1757
0
        PSYMCRYPT_DIVISOR pdDivTwoQ = NULL;
1758
1759
0
        UINT32 cbComputed = 0;
1760
0
        PSYMCRYPT_INT piComputed = NULL;
1761
0
        UINT32 fPrimeComputed = 0;
1762
0
        UINT32 dwComputedCounter = 0;
1763
1764
0
        PSYMCRYPT_MODELEMENT peComputed = NULL;
1765
0
        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
0
        ndDivTwoQ = SymCryptDigitsFromBits(pDlgroup->nBitsOfQ + 1);
1773
0
        cbDivTwoQ = SymCryptSizeofDivisorFromDigits( ndDivTwoQ );
1774
0
        pdDivTwoQ = SymCryptDivisorCreate( pbScratchInternal, cbDivTwoQ, ndDivTwoQ );
1775
0
        pbScratchInternal += cbDivTwoQ;
1776
0
        cbScratchInternal -= cbDivTwoQ;
1777
1778
        // Create the temporary integer of size Q
1779
0
        cbComputed = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfQ );
1780
0
        piComputed = SymCryptIntCreate( pbScratchInternal, cbComputed, pDlgroup->nDigitsOfQ );
1781
0
        pbScratchInternal += cbComputed;
1782
0
        cbScratchInternal -= cbComputed;
1783
1784
        // Create a trial division context for both P and Q
1785
0
        pTrialDivisionContext = SymCryptCreateTrialDivisionContext( pDlgroup->nDigitsOfP );
1786
0
        if (pTrialDivisionContext == NULL)
1787
0
        {
1788
0
            scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1789
0
            goto cleanup;
1790
0
        }
1791
1792
        // Steps 8,9: Check if computed_q is prime and equal to q
1793
0
        scError = SymCryptDlgroupGeneratePrimeQ_FIPS(
1794
0
                            pDlgroup,
1795
0
                            pTrialDivisionContext,
1796
0
                            &fPrimeComputed,
1797
0
                            piComputed,
1798
0
                            pdDivTwoQ,
1799
0
                            pbScratchInternal,
1800
0
                            cbScratchInternal );
1801
0
        if (scError != SYMCRYPT_NO_ERROR)
1802
0
        {
1803
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;  // Overwrite any possible error
1804
0
            goto cleanup;
1805
0
        }
1806
1807
0
        if ((!fPrimeComputed)||(!SymCryptIntIsEqual( piComputed, SymCryptIntFromModulus(pDlgroup->pmQ))))
1808
0
        {
1809
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1810
0
            goto cleanup;
1811
0
        }
1812
1813
        // Create the temporary integer of size P
1814
0
        pbScratchInternal -= cbComputed;
1815
0
        cbScratchInternal += cbComputed;
1816
0
        cbComputed = SymCryptSizeofIntFromDigits( pDlgroup->nDigitsOfP );
1817
0
        piComputed = SymCryptIntCreate( pbScratchInternal, cbComputed, pDlgroup->nDigitsOfP );
1818
0
        pbScratchInternal += cbComputed;
1819
0
        cbScratchInternal -= cbComputed;
1820
1821
        // Steps 10-14: Check if computed_p is prime and equal to p
1822
0
        scError = SymCryptDlgroupGeneratePrimeP_FIPS(
1823
0
                        pDlgroup,
1824
0
                        pdDivTwoQ,
1825
0
                        pDlgroup->dwGenCounter,     // Go up to this
1826
0
                        pTrialDivisionContext,
1827
0
                        &fPrimeComputed,
1828
0
                        piComputed,
1829
0
                        &dwComputedCounter,
1830
0
                        pbScratchInternal,
1831
0
                        cbScratchInternal );
1832
0
        if (scError != SYMCRYPT_NO_ERROR)
1833
0
        {
1834
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;  // Overwrite any possible error
1835
0
            goto cleanup;
1836
0
        }
1837
1838
0
        if ((!fPrimeComputed)||(dwComputedCounter!=pDlgroup->dwGenCounter)||(!SymCryptIntIsEqual( piComputed, SymCryptIntFromModulus(pDlgroup->pmP))))
1839
0
        {
1840
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1841
0
            goto cleanup;
1842
0
        }
1843
1844
        // Validation of G
1845
1846
        // Create the temporary modelement mod P
1847
0
        pbScratchInternal -= cbComputed;
1848
0
        cbScratchInternal += cbComputed;
1849
0
        cbComputed = SymCryptSizeofModElementFromModulus( pDlgroup->pmP );
1850
0
        peOne = SymCryptModElementCreate( pbScratchInternal, cbComputed, pDlgroup->pmP );
1851
0
        pbScratchInternal += cbComputed;
1852
0
        cbScratchInternal -= cbComputed;
1853
0
        peComputed = SymCryptModElementCreate( pbScratchInternal, cbComputed, pDlgroup->pmP );
1854
0
        pbScratchInternal += cbComputed;
1855
0
        cbScratchInternal -= cbComputed;
1856
1857
        // Step 2: Verify that 2<= G <= p-1
1858
0
        SymCryptModElementSetValueUint32( 1, pDlgroup->pmP, peOne, pbScratchInternal, cbScratchInternal );     // Set the temporary to 1
1859
1860
0
        if ((SymCryptModElementIsZero(pDlgroup->pmP, pDlgroup->peG)) || (SymCryptModElementIsEqual(pDlgroup->pmP, pDlgroup->peG, peOne)))
1861
0
        {
1862
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1863
0
            goto cleanup;
1864
0
        }
1865
1866
        // Step 3: Verify that G^Q == 1
1867
0
        SymCryptModExp(
1868
0
            pDlgroup->pmP,
1869
0
            pDlgroup->peG,
1870
0
            SymCryptIntFromModulus(pDlgroup->pmQ),
1871
0
            nBitsOfQ,
1872
0
            SYMCRYPT_FLAG_DATA_PUBLIC,
1873
0
            peComputed,
1874
0
            pbScratchInternal,
1875
0
            cbScratchInternal );
1876
1877
0
        if (!SymCryptModElementIsEqual(pDlgroup->pmP, peComputed, peOne))
1878
0
        {
1879
0
            scError = SYMCRYPT_AUTHENTICATION_FAILURE;
1880
0
            goto cleanup;
1881
0
        }
1882
1883
0
    }
1884
1885
0
cleanup:
1886
0
    if (pTrialDivisionContext!=NULL)
1887
0
    {
1888
0
        SymCryptFreeTrialDivisionContext( pTrialDivisionContext );
1889
0
    }
1890
1891
0
    if (pbScratch!=NULL)
1892
0
    {
1893
0
        SymCryptWipe( pbScratch, cbScratch );
1894
0
        SymCryptCallbackFree( pbScratch );
1895
0
    }
1896
0
    return scError;
1897
0
}
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
0
{
1915
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1916
1917
0
    PBYTE pbScratch = NULL;
1918
0
    SIZE_T cbScratch = 0;
1919
1920
0
    if ( ((pbPrimeP==NULL)&&(cbPrimeP>0)) ||
1921
0
         ((pbPrimeQ==NULL)&&(cbPrimeQ>0)) ||
1922
0
         ((pbGenG==NULL)&&(cbGenG>0)) ||
1923
0
         ((pbSeed==NULL)&&(cbSeed>0)) ||
1924
0
         ((pbSeed!=NULL)&&(cbSeed!=pDlgroup->cbSeed)) )
1925
0
    {
1926
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1927
0
        goto cleanup;
1928
0
    }
1929
1930
0
    if ((pbPrimeQ!=NULL) && (!pDlgroup->fHasPrimeQ))
1931
0
    {
1932
0
        scError = SYMCRYPT_INVALID_BLOB;
1933
0
        goto cleanup;
1934
0
    }
1935
1936
0
    if (pbPrimeP!=NULL)
1937
0
    {
1938
0
        scError = SymCryptIntGetValue(
1939
0
                        SymCryptIntFromModulus(pDlgroup->pmP),
1940
0
                        pbPrimeP,
1941
0
                        cbPrimeP,
1942
0
                        numFormat );
1943
0
        if (scError!=SYMCRYPT_NO_ERROR)
1944
0
        {
1945
0
            goto cleanup;
1946
0
        }
1947
0
    }
1948
1949
0
    if (pbPrimeQ!=NULL)
1950
0
    {
1951
0
        scError = SymCryptIntGetValue(
1952
0
                        SymCryptIntFromModulus(pDlgroup->pmQ),
1953
0
                        pbPrimeQ,
1954
0
                        cbPrimeQ,
1955
0
                        numFormat );
1956
0
        if (scError!=SYMCRYPT_NO_ERROR)
1957
0
        {
1958
0
            goto cleanup;
1959
0
        }
1960
0
    }
1961
1962
0
    if (pbGenG!=NULL)
1963
0
    {
1964
        // Scratch space is needed
1965
0
        cbScratch = SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pDlgroup->nDigitsOfP);
1966
0
        pbScratch = SymCryptCallbackAlloc( cbScratch );
1967
0
        if (pbScratch==NULL)
1968
0
        {
1969
0
            scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1970
0
            goto cleanup;
1971
0
        }
1972
1973
0
        scError = SymCryptModElementGetValue(
1974
0
                        pDlgroup->pmP,
1975
0
                        pDlgroup->peG,
1976
0
                        pbGenG,
1977
0
                        cbGenG,
1978
0
                        numFormat,
1979
0
                        pbScratch,
1980
0
                        cbScratch );
1981
0
        if (scError!=SYMCRYPT_NO_ERROR)
1982
0
        {
1983
0
            goto cleanup;
1984
0
        }
1985
0
    }
1986
1987
0
    if (ppHashAlgorithm!=NULL)
1988
0
    {
1989
0
        if (pDlgroup->eFipsStandard == SYMCRYPT_DLGROUP_FIPS_186_2)
1990
0
        {
1991
0
            *ppHashAlgorithm = NULL;
1992
0
        }
1993
0
        else
1994
0
        {
1995
0
            *ppHashAlgorithm = pDlgroup->pHashAlgorithm;
1996
0
        }
1997
0
    }
1998
1999
0
    if (pbSeed!=NULL && pDlgroup->pbSeed!=NULL)
2000
0
    {
2001
0
        memcpy( pbSeed, pDlgroup->pbSeed, pDlgroup->cbSeed);
2002
0
    }
2003
2004
0
    if (pGenCounter!=NULL)
2005
0
    {
2006
0
        *pGenCounter = pDlgroup->dwGenCounter;
2007
0
    }
2008
2009
0
cleanup:
2010
0
    if (pbScratch!=NULL)
2011
0
    {
2012
0
        SymCryptWipe( pbScratch, cbScratch );
2013
0
        SymCryptCallbackFree( pbScratch );
2014
0
    }
2015
0
    return scError;
2016
0
}
2017