/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 | | |