/src/SymCrypt/lib/fdef_mod.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // fdef_int.c INT functions for default number format |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | #include "precomp.h" |
8 | | |
9 | | PSYMCRYPT_MODULUS |
10 | | SYMCRYPT_CALL |
11 | | SymCryptFdefModulusAllocate( UINT32 nDigits ) |
12 | 0 | { |
13 | 0 | PVOID p = NULL; |
14 | 0 | UINT32 cb; |
15 | 0 | PSYMCRYPT_MODULUS res = NULL; |
16 | | |
17 | | // |
18 | | // The nDigits requirements are enforced by SymCryptFdefSizeofModulusFromDigits. Thus |
19 | | // the result does not overflow and is upper bounded by 2^19. |
20 | | // |
21 | 0 | cb = SymCryptFdefSizeofModulusFromDigits( nDigits ); |
22 | |
|
23 | 0 | if( cb != 0 ) |
24 | 0 | { |
25 | 0 | p = SymCryptCallbackAlloc( cb ); |
26 | 0 | } |
27 | |
|
28 | 0 | if( p == NULL ) |
29 | 0 | { |
30 | 0 | goto cleanup; |
31 | 0 | } |
32 | | |
33 | 0 | res = SymCryptFdefModulusCreate( p, cb, nDigits ); |
34 | |
|
35 | 0 | cleanup: |
36 | 0 | return res; |
37 | 0 | } |
38 | | |
39 | | VOID |
40 | | SYMCRYPT_CALL |
41 | | SymCryptFdefModulusFree( _Out_ PSYMCRYPT_MODULUS pmObj ) |
42 | 0 | { |
43 | 0 | SymCryptModulusWipe( pmObj ); |
44 | 0 | SymCryptCallbackFree( pmObj ); |
45 | 0 | } |
46 | | |
47 | | UINT32 |
48 | | SYMCRYPT_CALL |
49 | | SymCryptFdefSizeofModulusFromDigits( UINT32 nDigits ) |
50 | 3.78k | { |
51 | 3.78k | SYMCRYPT_ASSERT( nDigits != 0 ); |
52 | 3.78k | SYMCRYPT_ASSERT( nDigits <= SYMCRYPT_FDEF_UPB_DIGITS ); |
53 | | |
54 | | // Ensure we do not overflow the following calculation when provided with invalid inputs |
55 | 3.78k | if( nDigits == 0 || nDigits > SYMCRYPT_FDEF_UPB_DIGITS ) |
56 | 0 | { |
57 | 0 | return 0; |
58 | 0 | } |
59 | | |
60 | | // Room for the Modulus structure, the Divisor, the negated divisor, and the R^2 Montgomery factor |
61 | | // |
62 | 3.78k | return SYMCRYPT_FIELD_OFFSET( SYMCRYPT_MODULUS, Divisor ) + SymCryptFdefSizeofDivisorFromDigits( nDigits ) + (2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE); |
63 | 3.78k | } |
64 | | |
65 | | PSYMCRYPT_MODULUS |
66 | | SYMCRYPT_CALL |
67 | | SymCryptFdefModulusCreate( |
68 | | _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, |
69 | | SIZE_T cbBuffer, |
70 | | UINT32 nDigits ) |
71 | 1.89k | { |
72 | 1.89k | PSYMCRYPT_MODULUS pmMod = NULL; |
73 | 1.89k | UINT32 cb = SymCryptFdefSizeofModulusFromDigits( nDigits ); |
74 | | |
75 | 1.89k | const UINT32 offset = SYMCRYPT_FIELD_OFFSET( SYMCRYPT_MODULUS, Divisor ); |
76 | | |
77 | 1.89k | SYMCRYPT_ASSERT( cb >= sizeof(SYMCRYPT_MODULUS) ); |
78 | 1.89k | SYMCRYPT_ASSERT( cbBuffer >= cb ); |
79 | 1.89k | if( (cb == 0) || (cbBuffer < cb) ) |
80 | 0 | { |
81 | 0 | goto cleanup; // return NULL |
82 | 0 | } |
83 | | |
84 | 1.89k | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer ); |
85 | 1.89k | pmMod = (PSYMCRYPT_MODULUS) pbBuffer; |
86 | | |
87 | 1.89k | pmMod->type = 'gM' << 16; |
88 | 1.89k | pmMod->nDigits = nDigits; |
89 | | |
90 | | // |
91 | | // The nDigits requirements are enforced by SymCryptFdefSizeofModulusFromDigits. Thus |
92 | | // the result does not overflow and is upper bounded by 2^19. |
93 | | // |
94 | 1.89k | pmMod->cbSize = cb; |
95 | 1.89k | pmMod->flags = 0; |
96 | | |
97 | | // The following is bounded by 2^17 |
98 | 1.89k | pmMod->cbModElement = nDigits * SYMCRYPT_FDEF_DIGIT_SIZE; |
99 | | |
100 | 1.89k | SymCryptFdefDivisorCreate( pbBuffer + offset, cbBuffer - offset, nDigits ); |
101 | | |
102 | | // We don't have a modulus value yet, so we don't create/initialize any implementation-specific things. |
103 | | |
104 | 1.89k | SYMCRYPT_SET_MAGIC( pmMod ); |
105 | | |
106 | 1.89k | cleanup: |
107 | 1.89k | return pmMod; |
108 | 1.89k | } |
109 | | |
110 | | VOID |
111 | | SYMCRYPT_CALL |
112 | | SymCryptFdefModulusInitGeneric( |
113 | | _Inout_ PSYMCRYPT_MODULUS pmMod, |
114 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
115 | | SIZE_T cbScratch ) |
116 | 946 | { |
117 | 946 | UNREFERENCED_PARAMETER( pmMod ); |
118 | 946 | UNREFERENCED_PARAMETER( pbScratch ); |
119 | 946 | UNREFERENCED_PARAMETER( cbScratch ); |
120 | 946 | } |
121 | | |
122 | | |
123 | | VOID |
124 | | SymCryptFdefModulusCopy( |
125 | | _In_ PCSYMCRYPT_MODULUS pmSrc, |
126 | | _Out_ PSYMCRYPT_MODULUS pmDst ) |
127 | 0 | { |
128 | 0 | SYMCRYPT_ASSERT( pmSrc->nDigits == pmDst->nDigits ); |
129 | |
|
130 | 0 | if( pmSrc != pmDst ) |
131 | 0 | { |
132 | 0 | memcpy( pmDst, pmSrc, pmDst->cbSize ); |
133 | |
|
134 | 0 | SymCryptFdefDivisorCopyFixup( &pmSrc->Divisor, &pmDst->Divisor ); |
135 | | |
136 | | // Copy the type-specific fields |
137 | 0 | SYMCRYPT_MOD_CALL( pmSrc ) modulusCopyFixup( pmSrc, pmDst ); |
138 | |
|
139 | 0 | SYMCRYPT_SET_MAGIC( pmDst ); |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | | VOID |
144 | | SYMCRYPT_CALL |
145 | | SymCryptFdefModulusCopyFixupGeneric( |
146 | | _In_ PCSYMCRYPT_MODULUS pmSrc, |
147 | | _Out_ PSYMCRYPT_MODULUS pmDst ) |
148 | 0 | { |
149 | | // Only have to handle the type-specific fields, which we don't have any of. |
150 | 0 | UNREFERENCED_PARAMETER( pmSrc ); |
151 | 0 | UNREFERENCED_PARAMETER( pmDst ); |
152 | 0 | } |
153 | | |
154 | | |
155 | | PSYMCRYPT_MODELEMENT |
156 | | SYMCRYPT_CALL |
157 | | SymCryptFdefModElementAllocate( _In_ PCSYMCRYPT_MODULUS pmMod ) |
158 | 0 | { |
159 | 0 | PVOID p; |
160 | 0 | UINT32 cb; |
161 | 0 | PSYMCRYPT_MODELEMENT res = NULL; |
162 | | |
163 | | // |
164 | | // The nDigits requirements are enforced by the modulus object. Thus |
165 | | // the result does not overflow and is upper bounded by 2^17. |
166 | | // |
167 | 0 | cb = SymCryptFdefSizeofModElementFromModulus( pmMod ); |
168 | |
|
169 | 0 | p = SymCryptCallbackAlloc( cb ); |
170 | |
|
171 | 0 | if( p == NULL ) |
172 | 0 | { |
173 | 0 | goto cleanup; |
174 | 0 | } |
175 | | |
176 | 0 | res = SymCryptFdefModElementCreate( p, cb, pmMod ); |
177 | |
|
178 | 0 | cleanup: |
179 | 0 | return res; |
180 | 0 | } |
181 | | |
182 | | VOID |
183 | | SYMCRYPT_CALL |
184 | | SymCryptFdefModElementFree( |
185 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
186 | | _Out_ PSYMCRYPT_MODELEMENT peObj ) |
187 | 0 | { |
188 | 0 | SymCryptFdefModElementWipe( pmMod, peObj ); |
189 | 0 | SymCryptCallbackFree( peObj ); |
190 | 0 | } |
191 | | |
192 | | UINT32 |
193 | | SYMCRYPT_CALL |
194 | | SymCryptFdefSizeofModElementFromModulus( PCSYMCRYPT_MODULUS pmMod ) |
195 | 2.43M | { |
196 | | // Upper bounded by 2^17 since the modulus is up to SYMCRYPT_INT_MAXBITS = 2^20 bits. |
197 | 2.43M | return pmMod->cbModElement; |
198 | 2.43M | } |
199 | | |
200 | | PSYMCRYPT_MODELEMENT |
201 | | SYMCRYPT_CALL |
202 | | SymCryptFdefModElementCreate( |
203 | | _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, |
204 | | SIZE_T cbBuffer, |
205 | | PCSYMCRYPT_MODULUS pmMod ) |
206 | 2.34M | { |
207 | 2.34M | PSYMCRYPT_MODELEMENT pDst = (PSYMCRYPT_MODELEMENT) pbBuffer; |
208 | | |
209 | 2.34M | UNREFERENCED_PARAMETER( pmMod ); |
210 | 2.34M | UNREFERENCED_PARAMETER( cbBuffer ); |
211 | | |
212 | 2.34M | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer ); |
213 | 2.34M | SYMCRYPT_ASSERT( cbBuffer >= SymCryptFdefSizeofModElementFromModulus( pmMod ) ); |
214 | 2.34M | SYMCRYPT_ASSERT( cbBuffer >= pmMod->nDigits*SYMCRYPT_FDEF_DIGIT_SIZE ); |
215 | | |
216 | | // |
217 | | // We have various optimizations where we use only part of the last digit |
218 | | // Simple and fast solution: always wipe the last digit |
219 | | // |
220 | 2.34M | #if (SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM64) |
221 | 2.34M | UINT32 nDigits = pmMod->nDigits; |
222 | | |
223 | 2.34M | SymCryptWipeKnownSize( pbBuffer + (nDigits-1) * SYMCRYPT_FDEF_DIGIT_SIZE, SYMCRYPT_FDEF_DIGIT_SIZE ); |
224 | 2.34M | #endif |
225 | | |
226 | | // There is nothing to initialize... |
227 | | |
228 | 2.34M | return pDst; |
229 | 2.34M | } |
230 | | |
231 | | VOID |
232 | | SYMCRYPT_CALL |
233 | | SymCryptFdefModElementWipe( |
234 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
235 | | _Out_ PSYMCRYPT_MODELEMENT peDst ) |
236 | 0 | { |
237 | 0 | SymCryptWipe( peDst, pmMod->cbModElement ); |
238 | 0 | } |
239 | | |
240 | | VOID |
241 | | SymCryptFdefModElementCopy( |
242 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
243 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
244 | | _Out_ PSYMCRYPT_MODELEMENT peDst ) |
245 | 57.5k | { |
246 | 57.5k | if( peSrc != peDst ) |
247 | 57.5k | { |
248 | 57.5k | memcpy( peDst, peSrc, pmMod->cbModElement ); |
249 | 57.5k | } |
250 | 57.5k | } |
251 | | |
252 | | VOID |
253 | | SymCryptFdefModElementMaskedCopy( |
254 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
255 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
256 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
257 | | UINT32 mask ) |
258 | 82.7k | { |
259 | 82.7k | SymCryptFdefMaskedCopy( (PCBYTE) peSrc, (PBYTE) peDst, pmMod->nDigits, mask ); |
260 | 82.7k | } |
261 | | |
262 | | |
263 | | PSYMCRYPT_DIVISOR |
264 | | SYMCRYPT_CALL |
265 | | SymCryptFdefDivisorFromModulus( _In_ PSYMCRYPT_MODULUS pmSrc ) |
266 | 603 | { |
267 | 603 | return &pmSrc->Divisor; |
268 | 603 | } |
269 | | |
270 | | VOID |
271 | | SymCryptFdefModElementConditionalSwap( |
272 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
273 | | _Inout_ PSYMCRYPT_MODELEMENT peData1, |
274 | | _Inout_ PSYMCRYPT_MODELEMENT peData2, |
275 | | _In_ UINT32 cond ) |
276 | 0 | { |
277 | 0 | SymCryptFdefConditionalSwap( (PBYTE) &peData1->d.uint32[0], (PBYTE) &peData2->d.uint32[0], pmMod->nDigits, cond ); |
278 | 0 | } |
279 | | |
280 | | PSYMCRYPT_INT |
281 | | SYMCRYPT_CALL |
282 | | SymCryptFdefIntFromModulus( _In_ PSYMCRYPT_MODULUS pmSrc ) |
283 | 8.22k | { |
284 | | |
285 | 8.22k | return SymCryptFdefIntFromDivisor( &pmSrc->Divisor ); |
286 | 8.22k | } |
287 | | |
288 | | UINT32 |
289 | | SYMCRYPT_CALL |
290 | | SymCryptFdefDecideModulusType( PCSYMCRYPT_INT piSrc, UINT32 nDigits, UINT32 averageOperations, UINT32 flags ) |
291 | 1.89k | { |
292 | 1.89k | UINT32 res = 0; |
293 | 1.89k | BOOLEAN disableMontgomery = 0; |
294 | 1.89k | BYTE tempBuf[64]; |
295 | 1.89k | PCSYMCRYPT_MODULUS_TYPE_SELECTION_ENTRY pEntry; |
296 | | |
297 | 1.89k | UINT32 nBitsizeOfValue = SymCryptIntBitsizeOfValue( piSrc ); |
298 | 1.89k | UINT32 modulusFeatures = 0; |
299 | | |
300 | 1.89k | if( !disableMontgomery && |
301 | 1.89k | ( flags & (SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PARITY_PUBLIC)) != 0 && |
302 | 1.89k | (SymCryptIntGetValueLsbits32( piSrc ) & 1) == 1 && |
303 | 1.89k | averageOperations >= 10 ) |
304 | 946 | { |
305 | 946 | modulusFeatures |= SYMCRYPT_MODULUS_FEATURE_MONTGOMERY; |
306 | | |
307 | | // Specific modulus value detection |
308 | 946 | if( (flags & SYMCRYPT_FLAG_DATA_PUBLIC) != 0 ) |
309 | 946 | { |
310 | | // Detect if modulus value is the P384 field modulus (convert piSrc to big endian and do comparison with known value of P384 modulus) |
311 | 946 | if( nBitsizeOfValue == 384 && |
312 | 946 | SymCryptFdefRawGetValue(SYMCRYPT_FDEF_INT_PUINT32(piSrc), SYMCRYPT_FDEF_DIGITS_FROM_BITS(384), tempBuf, 64, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST) == SYMCRYPT_NO_ERROR ) |
313 | 285 | { |
314 | | // First 16 bytes are guaranteed to be zero because nBitsizeOfValue is 384 |
315 | 285 | if( memcmp(tempBuf+16, ((PBYTE)SymCryptEcurveParamsNistP384) + sizeof(SYMCRYPT_ECURVE_PARAMS), 48) == 0 ) |
316 | 262 | { |
317 | 262 | modulusFeatures |= SYMCRYPT_MODULUS_FEATURE_NISTP384; |
318 | 262 | } |
319 | 285 | } |
320 | | |
321 | | // Detect if modulus value is the P256 field modulus (not currently used) |
322 | | // if( nBitsizeOfValue == 256 && |
323 | | // SymCryptFdefRawGetValue(SYMCRYPT_FDEF_INT_PUINT32(piSrc), SYMCRYPT_FDEF_DIGITS_FROM_BITS(256), tempBuf, 64, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST) == SYMCRYPT_NO_ERROR ) |
324 | | // { |
325 | | // // First 32 bytes are guaranteed to be zero because nBitsizeOfValue is 256 |
326 | | // if( memcmp(tempBuf+32, ((PBYTE)SymCryptEcurveParamsNistP256) + sizeof(SYMCRYPT_ECURVE_PARAMS), 32) == 0 ) |
327 | | // { |
328 | | // modulusFeatures |= SYMCRYPT_MODULUS_FEATURE_NISTP256; |
329 | | // } |
330 | | // } |
331 | 946 | } |
332 | 946 | } |
333 | | |
334 | 1.89k | pEntry = SymCryptModulusTypeSelections; |
335 | | |
336 | 1.89k | for(;;) |
337 | 13.7k | { |
338 | 13.7k | if( SYMCRYPT_CPU_FEATURES_PRESENT( pEntry->cpuFeatures ) && |
339 | 13.7k | (pEntry->maxBits == 0 || (nDigits <= SymCryptDigitsFromBits( pEntry->maxBits ) && nBitsizeOfValue <= pEntry->maxBits )) && |
340 | 13.7k | (pEntry->modulusFeatures & ~modulusFeatures) == 0 |
341 | 13.7k | ) |
342 | 1.89k | { |
343 | 1.89k | res = pEntry->type; |
344 | 1.89k | break; |
345 | 1.89k | } |
346 | 11.8k | pEntry++; |
347 | 11.8k | } |
348 | | |
349 | 1.89k | return res; |
350 | 1.89k | } |
351 | | |
352 | | VOID |
353 | | SYMCRYPT_CALL |
354 | | SymCryptFdefModSetPostGeneric( |
355 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
356 | | _Inout_ PSYMCRYPT_MODELEMENT peObj, |
357 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
358 | | SIZE_T cbScratch ) |
359 | 1.43k | { |
360 | 1.43k | UNREFERENCED_PARAMETER( pmMod ); |
361 | 1.43k | UNREFERENCED_PARAMETER( peObj ); |
362 | 1.43k | UNREFERENCED_PARAMETER( pbScratch ); |
363 | 1.43k | UNREFERENCED_PARAMETER( cbScratch ); |
364 | 1.43k | } |
365 | | |
366 | | PCUINT32 |
367 | | SYMCRYPT_CALL |
368 | | SymCryptFdefModPreGetGeneric( |
369 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
370 | | _In_ PCSYMCRYPT_MODELEMENT peObj, |
371 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
372 | | SIZE_T cbScratch ) |
373 | 650 | { |
374 | 650 | UNREFERENCED_PARAMETER( pmMod ); |
375 | 650 | UNREFERENCED_PARAMETER( pbScratch ); |
376 | 650 | UNREFERENCED_PARAMETER( cbScratch ); |
377 | | |
378 | 650 | return &peObj->d.uint32[0]; |
379 | 650 | } |
380 | | |
381 | | |
382 | | |
383 | | VOID |
384 | | SYMCRYPT_CALL |
385 | | SymCryptFdefIntToModulus( |
386 | | _In_ PCSYMCRYPT_INT piSrc, |
387 | | _Out_ PSYMCRYPT_MODULUS pmDst, |
388 | | UINT32 averageOperations, |
389 | | UINT32 flags, |
390 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
391 | | SIZE_T cbScratch ) |
392 | 1.89k | { |
393 | 1.89k | pmDst->flags = flags; |
394 | 1.89k | SymCryptIntToDivisor( piSrc, &pmDst->Divisor, averageOperations, flags & SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratch ); |
395 | | |
396 | 1.89k | pmDst->type = SymCryptFdefDecideModulusType( piSrc, pmDst->nDigits, averageOperations, flags ); |
397 | | |
398 | | // Set inv64 - note the value is only valid if the modulus is odd, but the computation |
399 | | // is constant time regardless of the parity, so we can safely compute it in all cases |
400 | 1.89k | pmDst->inv64 = 0 - SymCryptInverseMod2e64( SymCryptIntGetValueLsbits64(piSrc) ); |
401 | | |
402 | 1.89k | SYMCRYPT_MOD_CALL( pmDst ) modulusInit( pmDst, pbScratch, cbScratch ); |
403 | 1.89k | } |
404 | | |
405 | | VOID |
406 | | SYMCRYPT_CALL |
407 | | SymCryptFdefIntToModElement( |
408 | | _In_ PCSYMCRYPT_INT piSrc, |
409 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
410 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
411 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
412 | | SIZE_T cbScratch ) |
413 | 1.17k | { |
414 | 1.17k | SymCryptFdefRawDivMod( |
415 | 1.17k | SYMCRYPT_FDEF_INT_PUINT32( piSrc ), |
416 | 1.17k | piSrc->nDigits, |
417 | 1.17k | &pmMod->Divisor, |
418 | 1.17k | NULL, // throw away the quotient |
419 | 1.17k | &peDst->d.uint32[0], |
420 | 1.17k | pbScratch, |
421 | 1.17k | cbScratch ); |
422 | | |
423 | 1.17k | SYMCRYPT_MOD_CALL( pmMod ) modSetPost( pmMod, peDst, pbScratch, cbScratch ); |
424 | 1.17k | } |
425 | | |
426 | | VOID |
427 | | SYMCRYPT_CALL |
428 | | SymCryptFdefModElementToIntGeneric( |
429 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
430 | | _In_reads_bytes_( pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) |
431 | | PCUINT32 pSrc, |
432 | | _Out_ PSYMCRYPT_INT piDst, |
433 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
434 | | SIZE_T cbScratch ) |
435 | 1.61k | { |
436 | 1.61k | memcpy( SYMCRYPT_FDEF_INT_PUINT32( piDst ), pSrc, pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
437 | | |
438 | 1.61k | SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piDst )[pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32], (piDst->nDigits - pmMod->nDigits) * SYMCRYPT_FDEF_DIGIT_SIZE ); |
439 | | |
440 | 1.61k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pmMod->nDigits ) ); |
441 | 1.61k | } |
442 | | |
443 | | SYMCRYPT_ERROR |
444 | | SYMCRYPT_CALL |
445 | | SymCryptFdefModElementSetValueGeneric( |
446 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
447 | | SIZE_T cbSrc, |
448 | | SYMCRYPT_NUMBER_FORMAT format, |
449 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
450 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
451 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
452 | | SIZE_T cbScratch ) |
453 | 4.36k | { |
454 | 4.36k | SYMCRYPT_ERROR scError; |
455 | 4.36k | UINT32 nDigits = pmMod->nDigits; |
456 | | |
457 | 4.36k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
458 | | |
459 | 4.36k | SYMCRYPT_ASSERT( cbSrc <= nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
460 | | |
461 | 4.36k | scError = SymCryptFdefRawSetValue( pbSrc, cbSrc, format, &peDst->d.uint32[0], nDigits ); |
462 | 4.36k | if( scError != SYMCRYPT_NO_ERROR ) |
463 | 0 | { |
464 | 0 | goto cleanup; |
465 | 0 | } |
466 | | |
467 | 4.36k | SymCryptFdefRawDivMod( |
468 | 4.36k | &peDst->d.uint32[0], |
469 | 4.36k | nDigits, |
470 | 4.36k | &pmMod->Divisor, |
471 | 4.36k | NULL, |
472 | 4.36k | &peDst->d.uint32[0], |
473 | 4.36k | pbScratch, |
474 | 4.36k | cbScratch ); |
475 | | |
476 | 4.36k | scError = SYMCRYPT_NO_ERROR; |
477 | | |
478 | 4.36k | cleanup: |
479 | 4.36k | return scError; |
480 | 4.36k | } |
481 | | |
482 | | SYMCRYPT_ERROR |
483 | | SYMCRYPT_CALL |
484 | | SymCryptFdefModElementGetValue( |
485 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
486 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
487 | | _Out_writes_bytes_( cbDst ) PBYTE pbDst, |
488 | | SIZE_T cbDst, |
489 | | SYMCRYPT_NUMBER_FORMAT format, |
490 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
491 | | SIZE_T cbScratch ) |
492 | 1.76k | { |
493 | 1.76k | SYMCRYPT_ERROR scError; |
494 | 1.76k | PCUINT32 pUint32; |
495 | 1.76k | UINT32 nDigits = pmMod->nDigits; |
496 | | |
497 | | |
498 | 1.76k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
499 | | |
500 | 1.76k | SYMCRYPT_ASSERT( cbDst <= nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
501 | | |
502 | 1.76k | pUint32 = SYMCRYPT_MOD_CALL( pmMod ) modPreGet( pmMod, peSrc, pbScratch, cbScratch ); |
503 | | |
504 | 1.76k | scError = SymCryptFdefRawGetValue( pUint32, nDigits, pbDst, cbDst, format ); |
505 | | |
506 | 1.76k | return scError; |
507 | 1.76k | } |
508 | | |
509 | | UINT32 |
510 | | SYMCRYPT_CALL |
511 | | SymCryptFdefModElementIsEqual( |
512 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
513 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
514 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2 ) |
515 | 4.34k | { |
516 | 4.34k | UINT32 d; |
517 | 4.34k | UINT32 i; |
518 | | |
519 | 4.34k | d = 0; |
520 | 91.9k | for( i=0; i < pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ; i++ ) |
521 | 87.5k | { |
522 | 87.5k | d |= peSrc1->d.uint32[i] ^ peSrc2->d.uint32[i]; |
523 | 87.5k | } |
524 | | |
525 | 4.34k | return SYMCRYPT_MASK32_ZERO( d ); |
526 | 4.34k | } |
527 | | |
528 | | UINT32 |
529 | | SYMCRYPT_CALL |
530 | | SymCryptFdefModElementIsZero( |
531 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
532 | | _In_ PCSYMCRYPT_MODELEMENT peSrc ) |
533 | 77.3k | { |
534 | 77.3k | UINT32 d; |
535 | 77.3k | UINT32 i; |
536 | | |
537 | 77.3k | d = 0; |
538 | 1.94M | for( i=0; i < pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ; i++ ) |
539 | 1.86M | { |
540 | 1.86M | d |= peSrc->d.uint32[i]; // Check that all bits are zero |
541 | 1.86M | } |
542 | | |
543 | 77.3k | return SYMCRYPT_MASK32_ZERO( d ); |
544 | 77.3k | } |
545 | | |
546 | | VOID |
547 | | SYMCRYPT_CALL |
548 | | SymCryptFdefModAddGeneric( |
549 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
550 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
551 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
552 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
553 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
554 | | SIZE_T cbScratch ) |
555 | 145k | { |
556 | 145k | UINT32 c; |
557 | 145k | UINT32 d; |
558 | 145k | UINT32 nDigits = pmMod->nDigits; |
559 | | |
560 | 145k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
561 | 145k | SYMCRYPT_ASSERT( cbScratch >= nDigits*SYMCRYPT_FDEF_DIGIT_SIZE ); |
562 | | |
563 | | // |
564 | | // Doing add/cmp/sub might be faster or not. |
565 | | // Masked add is hard because the mask operations destroy the carry flag. |
566 | | // |
567 | | |
568 | | // dcl - cleanup? |
569 | | |
570 | | // c = SymCryptFdefRawAdd( &pSrc1->uint32[0], &pSrc2->uint32[0], &pDst->uint32[0], nDigits); |
571 | | // d = SymCryptFdefRawSub( &pDst->uint32[0], &pMod->Divisor.Int.uint32[0], &pDst->uint32[0], nDigits ); |
572 | | // e = SymCryptFdefRawMaskedAdd( &pDst->uint32[0], &pMod->Divisor.Int.uint32[0], 0 - (c^d), nDigits ); |
573 | | |
574 | 145k | c = SymCryptFdefRawAdd( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], &peDst->d.uint32[0], nDigits ); |
575 | 145k | d = SymCryptFdefRawSub( &peDst->d.uint32[0], SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), (PUINT32) pbScratch, nDigits ); |
576 | 145k | SymCryptFdefMaskedCopy( pbScratch, (PBYTE) &peDst->d.uint32[0], nDigits, (c^d) - 1 ); |
577 | | |
578 | | // We can't have a carry in the first addition, and no carry in the subtraction. |
579 | 145k | SYMCRYPT_ASSERT( !( c == 1 && d == 0 ) ); |
580 | 145k | } |
581 | | |
582 | | VOID |
583 | | SYMCRYPT_CALL |
584 | | SymCryptFdefModSubGeneric( |
585 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
586 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
587 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
588 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
589 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
590 | | SIZE_T cbScratch ) |
591 | 303k | { |
592 | 303k | UINT32 c; |
593 | 303k | UINT32 d; |
594 | 303k | UINT32 nDigits = pmMod->nDigits; |
595 | | |
596 | 303k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
597 | 303k | SYMCRYPT_ASSERT( cbScratch >= nDigits*SYMCRYPT_FDEF_DIGIT_SIZE ); |
598 | | |
599 | 303k | c = SymCryptFdefRawSub( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], &peDst->d.uint32[0], nDigits ); |
600 | 303k | d = SymCryptFdefRawAdd( &peDst->d.uint32[0], SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), (PUINT32) pbScratch, nDigits ); |
601 | 303k | SymCryptFdefMaskedCopy( pbScratch, (PBYTE) &peDst->d.uint32[0], nDigits, 0 - c ); |
602 | | |
603 | 303k | SYMCRYPT_ASSERT( !(c == 1 && d == 0) ); |
604 | 303k | } |
605 | | |
606 | | |
607 | | VOID |
608 | | SYMCRYPT_CALL |
609 | | SymCryptFdefModNegGeneric( |
610 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
611 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
612 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
613 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
614 | | SIZE_T cbScratch ) |
615 | 83.3k | { |
616 | 83.3k | UINT32 nDigits = pmMod->nDigits; |
617 | 83.3k | UINT32 isZero; |
618 | 83.3k | UINT32 i; |
619 | | |
620 | 83.3k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
621 | | |
622 | | // |
623 | | // We have to be careful to handle the value 0 properly as it does NOT map to Modulus - Value. |
624 | | // |
625 | 83.3k | isZero = SymCryptFdefRawIsEqualUint32( &peSrc->d.uint32[0], nDigits , 0 ); |
626 | 83.3k | SymCryptFdefRawSub( SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), &peSrc->d.uint32[0], &peDst->d.uint32[0], nDigits ); |
627 | | |
628 | | // Now we set the result to zero if the input was zero |
629 | 1.83M | for( i=0; i< nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ ) |
630 | 1.75M | { |
631 | 1.75M | peDst->d.uint32[i] &= ~isZero; |
632 | 1.75M | } |
633 | 83.3k | } |
634 | | |
635 | | VOID |
636 | | SYMCRYPT_CALL |
637 | | SymCryptFdefModElementSetValueUint32Generic( |
638 | | UINT32 value, |
639 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
640 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
641 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
642 | | SIZE_T cbScratch ) |
643 | 6.75k | { |
644 | 6.75k | UINT32 nDigits = pmMod->nDigits; |
645 | | |
646 | 6.75k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
647 | | |
648 | 6.75k | if( pmMod->Divisor.nBits <= 32 && value >= SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int )[0] ) |
649 | 0 | { |
650 | | // The value is >= the modulus; this is not supported |
651 | | |
652 | | // For now do a possibly non-sidechannel safe, but mathematically correct modulo operation |
653 | 0 | value %= SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int )[0]; |
654 | 0 | } |
655 | | |
656 | 6.75k | peDst->d.uint32[0] = value; |
657 | | |
658 | 6.75k | SymCryptWipe( &peDst->d.uint32[1], nDigits * SYMCRYPT_FDEF_DIGIT_SIZE - sizeof( UINT32 ) ); |
659 | 6.75k | } |
660 | | |
661 | | VOID |
662 | | SYMCRYPT_CALL |
663 | | SymCryptFdefModElementSetValueNegUint32( |
664 | | UINT32 value, |
665 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
666 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
667 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
668 | | SIZE_T cbScratch ) |
669 | 852 | { |
670 | 852 | UINT32 nDigits = pmMod->nDigits; |
671 | | |
672 | 852 | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
673 | | |
674 | 852 | if( pmMod->Divisor.nBits <= 32 && value >= SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int )[0] ) |
675 | 0 | { |
676 | | // The value is >= the modulus; this is not supported. |
677 | | |
678 | | // For now do a possibly non-sidechannel safe, but mathematically correct modulo operation |
679 | 0 | value %= SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int )[0]; |
680 | 0 | } |
681 | | |
682 | 852 | if( value == 0 ) |
683 | 0 | { |
684 | 0 | SymCryptWipe( &peDst->d.uint32[0], nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
685 | 852 | } else { |
686 | 852 | SymCryptFdefRawSubUint32( SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), value, &peDst->d.uint32[0], nDigits ); |
687 | 852 | } |
688 | | |
689 | | // |
690 | | // Possible future optimization: we can optimize the value==0 and value==1 cases on a per-type basis |
691 | | // |
692 | 852 | SYMCRYPT_MOD_CALL( pmMod ) modSetPost( pmMod, peDst, pbScratch, cbScratch ); |
693 | 852 | } |
694 | | |
695 | | // In the worst case there is a 1 in 8 chance of successfully generating a value |
696 | | // This is when the modulus is 4 (nBits of modulus is 3), and 0, 1, and -1 are disallowed. |
697 | | // In this case, having 1000 retries, there is a ~ 2^-193 chance of failure unless SymCryptCallbackRandom |
698 | | // is completely broken. This passes the bar of being reasonable to Fatal. |
699 | 536 | #define FDEF_MOD_SET_RANDOM_GENERIC_LIMIT (1000) |
700 | | |
701 | | VOID |
702 | | SYMCRYPT_CALL |
703 | | SymCryptFdefModSetRandomGeneric( |
704 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
705 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
706 | | UINT32 flags, |
707 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
708 | | SIZE_T cbScratch ) |
709 | 268 | { |
710 | 268 | UINT32 offset; |
711 | 268 | UINT32 ulimit; |
712 | 268 | UINT32 nDigits = pmMod->nDigits; |
713 | 268 | PUINT32 pTmp = (PUINT32) pbScratch; |
714 | 268 | UINT32 nUsedBytes; |
715 | 268 | UINT32 mask; |
716 | 268 | UINT32 c; |
717 | 268 | UINT32 cntr; |
718 | 268 | PUINT32 pDst = &peDst->d.uint32[0]; |
719 | 268 | PCUINT32 pMod = SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ); |
720 | | |
721 | 268 | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
722 | | |
723 | 268 | if( (flags & SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO) != 0 ) |
724 | 0 | { |
725 | | // SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO => SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE |
726 | 0 | offset = 0; |
727 | 268 | } else if( (flags & SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE) != 0 ) |
728 | 268 | { |
729 | 268 | offset = 1; |
730 | 268 | } else |
731 | 0 | { |
732 | 0 | offset = 2; |
733 | 0 | } |
734 | | |
735 | 268 | if( (flags & SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE ) ) |
736 | 268 | { |
737 | 268 | ulimit = 0; |
738 | 268 | } else { |
739 | 0 | ulimit = 1; |
740 | 0 | } |
741 | | |
742 | | // |
743 | | // Special case for small divisors: |
744 | | // When the divisor is 1, 2, or 3 we always allow returning -1 |
745 | | // We may also allow returning 1 or 0 depending on the flags specified |
746 | 268 | if ( pmMod->Divisor.nBits < 3 ) |
747 | 0 | { |
748 | | // At a minimum, allow -1 |
749 | 0 | offset = SYMCRYPT_MIN(offset, pMod[0] - 1); |
750 | 0 | ulimit = 0; |
751 | 0 | } |
752 | | |
753 | | // Set pTmp to pMod-(offset+ulimit) |
754 | 268 | SYMCRYPT_ASSERT( nDigits * SYMCRYPT_FDEF_DIGIT_SIZE <= cbScratch ); |
755 | 268 | c = SymCryptFdefRawSubUint32( pMod, offset + ulimit, pTmp, nDigits ); |
756 | 268 | SYMCRYPT_ASSERT( c == 0 ); |
757 | | |
758 | 268 | nUsedBytes = (pmMod->Divisor.nBits + 7)/8; |
759 | 268 | mask = 0x100 >> ( (8-pmMod->Divisor.nBits) & 7); |
760 | 268 | mask -= 1; |
761 | | |
762 | | // Wipe any bytes we won't fill with random |
763 | 268 | SymCryptWipe( (PBYTE)pDst + nUsedBytes, (nDigits * SYMCRYPT_FDEF_DIGIT_SIZE) - nUsedBytes ); |
764 | | |
765 | 268 | for(cntr=0; cntr<FDEF_MOD_SET_RANDOM_GENERIC_LIMIT; cntr++) |
766 | 268 | { |
767 | | // Try random values until we get one we like |
768 | 268 | SymCryptCallbackRandom( (PBYTE)pDst, nUsedBytes ); |
769 | 268 | ((PBYTE)pDst)[nUsedBytes-1] &= (BYTE) mask; |
770 | | |
771 | | // Compare value to pMod-(offset+ulimit) |
772 | 268 | if( SymCryptFdefRawIsLessThan( pDst, pTmp, nDigits ) ) |
773 | 268 | { |
774 | | // The value is within required range [0, Divisor-offset-ulimit) |
775 | 268 | break; |
776 | 268 | } |
777 | 268 | } |
778 | | |
779 | | // Wipe all the digits in pTmp |
780 | 268 | SymCryptWipe( pTmp, nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
781 | | |
782 | 268 | if (cntr >= FDEF_MOD_SET_RANDOM_GENERIC_LIMIT) |
783 | 0 | { |
784 | 0 | SymCryptFatal( 'rndc'); |
785 | 0 | } |
786 | | |
787 | | // Add the offset which allows us to avoid 0 and/or 1 if required. |
788 | | // Now result is in range [offset, Divisor-ulimit) |
789 | 268 | c = SymCryptFdefRawAddUint32( pDst, offset, pDst, nDigits ); |
790 | 268 | SYMCRYPT_ASSERT( c == 0 ); |
791 | 268 | } |
792 | | |
793 | | VOID |
794 | | SYMCRYPT_CALL |
795 | | SymCryptFdefModDivSmallPow2Generic( |
796 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
797 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
798 | | _In_range_(1, NATIVE_BITS) UINT32 exp, |
799 | | _Out_ PSYMCRYPT_MODELEMENT peDst) |
800 | 337k | { |
801 | 337k | UINT32 nDigits = pmMod->nDigits; |
802 | 337k | UINT32 mask; |
803 | 337k | UINT64 t; |
804 | 337k | UINT64 u; |
805 | 337k | UINT32 i; |
806 | 337k | PCUINT32 pMod = SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ); |
807 | | |
808 | | // mod must be odd |
809 | 337k | SYMCRYPT_ASSERT( (pMod[0] & 1) != 0 ); |
810 | 337k | SYMCRYPT_ASSERT( (exp >= 1) && (exp <= NATIVE_BITS) ); |
811 | | |
812 | 337k | do |
813 | 675k | { |
814 | 675k | mask = (UINT32)0 - (peSrc->d.uint32[0] & 1); |
815 | | |
816 | 675k | t = (UINT64) peSrc->d.uint32[0] + (pMod[0] & mask); |
817 | 675k | u = (UINT32) t; |
818 | 675k | t >>= 32; |
819 | | |
820 | 15.7M | for( i = 1; i < nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ ) |
821 | 15.0M | { |
822 | 15.0M | t += pMod[i] & mask; |
823 | 15.0M | t += peSrc->d.uint32[i]; |
824 | | |
825 | 15.0M | u |= t << 32; |
826 | | |
827 | 15.0M | peDst->d.uint32[i-1] = (UINT32)(u >> 1); |
828 | 15.0M | t >>= 32; |
829 | 15.0M | u >>= 32; |
830 | 15.0M | } |
831 | 675k | u |= t << 32; |
832 | 675k | peDst->d.uint32[i-1] = (UINT32)( u >> 1 ); |
833 | | |
834 | 675k | exp -= 1; |
835 | | |
836 | | // First iteration reads from peSrc and writes to peDst |
837 | | // subsequent iterations must read from and write to peDst |
838 | 675k | peSrc = peDst; |
839 | 675k | } while (exp > 0); |
840 | 337k | } |
841 | | |
842 | | VOID |
843 | | SYMCRYPT_CALL |
844 | | SymCryptFdefModDivSmallPow2( |
845 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
846 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
847 | | _In_range_(1, NATIVE_BITS) UINT32 exp, |
848 | | _Out_ PSYMCRYPT_MODELEMENT peDst ) |
849 | 337k | { |
850 | | |
851 | 337k | #if SYMCRYPT_CPU_AMD64 |
852 | 337k | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_MULX ) ) |
853 | 0 | { |
854 | 0 | SymCryptFdefModDivSmallPow2Mulx( pmMod, peSrc, exp, peDst ); |
855 | 0 | } |
856 | 337k | else |
857 | 337k | { |
858 | | // Currently SymCryptAsm does not support AMD64 functions with shl/shr/shrd |
859 | | // by a variable count, as this needs special handling of the rcx (cl) register |
860 | | // For now we just fallback to the generic implementation on machines without MULX |
861 | 337k | SymCryptFdefModDivSmallPow2Generic( pmMod, peSrc, exp, peDst ); |
862 | 337k | } |
863 | | #elif SYMCRYPT_CPU_ARM64 |
864 | | SymCryptFdefModDivSmallPow2Asm( pmMod, peSrc, exp, peDst ); |
865 | | #else |
866 | | SymCryptFdefModDivSmallPow2Generic( pmMod, peSrc, exp, peDst ); |
867 | | #endif |
868 | 337k | } |
869 | | |
870 | | VOID |
871 | | SYMCRYPT_CALL |
872 | | SymCryptFdefModDivPow2( |
873 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
874 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
875 | | UINT32 exp, |
876 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
877 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
878 | | SIZE_T cbScratch ) |
879 | 0 | { |
880 | 0 | UINT32 shiftAmount; |
881 | |
|
882 | 0 | UNREFERENCED_PARAMETER(pbScratch); |
883 | 0 | UNREFERENCED_PARAMETER(cbScratch); |
884 | | |
885 | | // mod must be odd |
886 | 0 | SYMCRYPT_ASSERT( (SYMCRYPT_FDEF_INT_PUINT32(&pmMod->Divisor.Int)[0] & 1) != 0 ); |
887 | |
|
888 | 0 | if( exp == 0 ) |
889 | 0 | { |
890 | | // If exp is 0 we just need to copy peSrc to peDst |
891 | 0 | SymCryptFdefModElementCopy( pmMod, peSrc, peDst ); |
892 | 0 | return; |
893 | 0 | } |
894 | | |
895 | 0 | do |
896 | 0 | { |
897 | 0 | shiftAmount = SYMCRYPT_MIN(NATIVE_BITS, exp); |
898 | 0 | SymCryptFdefModDivSmallPow2( pmMod, peSrc, shiftAmount, peDst ); |
899 | 0 | exp -= shiftAmount; |
900 | | |
901 | | // First iteration reads from peSrc and writes to peDst |
902 | | // subsequent iterations must read from and write to peDst |
903 | 0 | peSrc = peDst; |
904 | 0 | } while( exp > 0 ); |
905 | 0 | } |
906 | | |
907 | | VOID |
908 | | SYMCRYPT_CALL |
909 | | SymCryptFdefModMulGeneric( |
910 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
911 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
912 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
913 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
914 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
915 | | SIZE_T cbScratch ) |
916 | 1.24k | { |
917 | 1.24k | UINT32 nDigits = pmMod->nDigits; |
918 | 1.24k | PUINT32 pTmp = (PUINT32) pbScratch; |
919 | 1.24k | UINT32 scratchOffset = 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE; |
920 | | |
921 | 1.24k | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
922 | 1.24k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
923 | 1.24k | SYMCRYPT_ASSERT( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) >= scratchOffset + SYMCRYPT_FDEF_SCRATCH_BYTES_FOR_INT_DIVMOD( 2 * nDigits, nDigits ) ); |
924 | 1.24k | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbScratch ); |
925 | | |
926 | | // Tmp space is enough for the product plus the DivMod scratch |
927 | | |
928 | 1.24k | SymCryptFdefRawMul( &peSrc1->d.uint32[0], nDigits, &peSrc2->d.uint32[0], nDigits, pTmp ); |
929 | | |
930 | 1.24k | SymCryptFdefRawDivMod( pTmp, 2*nDigits, &pmMod->Divisor, NULL, &peDst->d.uint32[0], pbScratch + scratchOffset, cbScratch - scratchOffset ); |
931 | 1.24k | } |
932 | | |
933 | | VOID |
934 | | SYMCRYPT_CALL |
935 | | SymCryptFdefModSquareGeneric( |
936 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
937 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
938 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
939 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
940 | | SIZE_T cbScratch ) |
941 | 0 | { |
942 | 0 | UINT32 nDigits = pmMod->nDigits; |
943 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
944 | 0 | UINT32 scratchOffset = 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE; |
945 | |
|
946 | 0 | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
947 | 0 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
948 | 0 | SYMCRYPT_ASSERT( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) >= scratchOffset + SYMCRYPT_FDEF_SCRATCH_BYTES_FOR_INT_DIVMOD( 2 * nDigits, nDigits ) ); |
949 | 0 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbScratch ); |
950 | | |
951 | | // Tmp space is enough for the product plus the DivMod scratch |
952 | |
|
953 | 0 | SymCryptFdefRawSquare( &peSrc->d.uint32[0], nDigits, pTmp ); |
954 | |
|
955 | 0 | SymCryptFdefRawDivMod( pTmp, 2*nDigits, &pmMod->Divisor, NULL, &peDst->d.uint32[0], pbScratch + scratchOffset, cbScratch - scratchOffset ); |
956 | 0 | } |
957 | | |
958 | | SYMCRYPT_ERROR |
959 | | SYMCRYPT_CALL |
960 | | SymCryptFdefModInvGeneric( |
961 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
962 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
963 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
964 | | UINT32 flags, |
965 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
966 | | SIZE_T cbScratch ) |
967 | 1.23k | { |
968 | 1.23k | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
969 | 1.23k | UINT32 nDigits = pmMod->nDigits; |
970 | 1.23k | UINT32 nBytes; |
971 | 1.23k | UINT32 c; |
972 | 1.23k | UINT32 leastSignificantUint32; |
973 | 1.23k | UINT32 trailingZeros; |
974 | | |
975 | | // |
976 | | // This function is called on Montgomery moduli so we can't directly call specifically optimized modular operations from here. |
977 | | // |
978 | | // For now we use dispatch functions with pmMod to perform potentially optimized modular operations. |
979 | | // This approach makes sense when on average the cost of dispatch is less than the benefit using an optimized operation. |
980 | | // The alternative is to make specialized ModInv routines for different types of moduli, but we do not yet do this to |
981 | | // reduce code duplication / code size. |
982 | | // |
983 | | |
984 | 1.23k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( nDigits ) ); |
985 | | |
986 | 1.23k | if( (pmMod->flags & (SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME )) != (SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME ) ) |
987 | 0 | { |
988 | | // Inversion over non-public or non-prime moduli currently not supported. |
989 | | // Our blinding below only works for prime moduli. |
990 | | // As the modulus cannot be blinded, it requires a fully side-channel safe algorithm which is much more complicated and |
991 | | // slower. |
992 | | // When this is necessary, we will add a second ModInv implementation for those cases. |
993 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
994 | 0 | goto cleanup; |
995 | 0 | } |
996 | | |
997 | | // |
998 | | // Algorithm: |
999 | | // R = random nonzero value mod Mod |
1000 | | // X := Src * R (mod Mod) |
1001 | | // A = X |
1002 | | // B = Mod |
1003 | | // Va = 1 |
1004 | | // Vb = 0 |
1005 | | // invariant: A = Va*X (mod Mod), B = Vb*X (mod Mod), |
1006 | | // |
1007 | | // if( A == 0 ): error |
1008 | | // |
1009 | | // verify (A | B) is odd |
1010 | | // if B even: swap (A,B), swap( Va, Vb) |
1011 | | // |
1012 | | // repeat: |
1013 | | // while( A even ): |
1014 | | // A /= 2; Va /= 2 (mod Mod) |
1015 | | // if( A == 1 ): break1 |
1016 | | // (A, Va, B, Vb) = (B-A, Vb - Va, A, Va) |
1017 | | // if( A == 0 ): error (not co-prime) |
1018 | | |
1019 | 1.23k | nBytes = SymCryptSizeofModElementFromModulus( pmMod ); |
1020 | | |
1021 | 1.23k | SYMCRYPT_ASSERT( cbScratch >= 4*nBytes ); |
1022 | 1.23k | PSYMCRYPT_MODELEMENT peR = SymCryptModElementCreate( pbScratch, nBytes, pmMod ); |
1023 | 1.23k | pbScratch += nBytes; |
1024 | 1.23k | PSYMCRYPT_MODELEMENT peX = SymCryptModElementCreate( pbScratch, nBytes, pmMod ); |
1025 | 1.23k | pbScratch += nBytes; |
1026 | 1.23k | PSYMCRYPT_MODELEMENT peVa = SymCryptModElementCreate( pbScratch, nBytes, pmMod ); |
1027 | 1.23k | pbScratch += nBytes; |
1028 | 1.23k | PSYMCRYPT_MODELEMENT peVb = SymCryptModElementCreate( pbScratch, nBytes, pmMod ); |
1029 | 1.23k | pbScratch += nBytes; |
1030 | 1.23k | cbScratch -= 4*nBytes; |
1031 | | |
1032 | 1.23k | PSYMCRYPT_MODELEMENT peVtmpPtr; |
1033 | | |
1034 | 1.23k | nBytes = SymCryptSizeofIntFromDigits( nDigits ); |
1035 | 1.23k | SYMCRYPT_ASSERT( cbScratch >= 3 * nBytes ); |
1036 | 1.23k | PSYMCRYPT_INT piA = SymCryptIntCreate( pbScratch, nBytes, nDigits ); |
1037 | 1.23k | pbScratch += nBytes; |
1038 | 1.23k | PSYMCRYPT_INT piB = SymCryptIntCreate( pbScratch, nBytes, nDigits ); |
1039 | 1.23k | pbScratch += nBytes; |
1040 | 1.23k | PSYMCRYPT_INT piT = SymCryptIntCreate( pbScratch, nBytes, nDigits ); |
1041 | 1.23k | pbScratch += nBytes; |
1042 | 1.23k | cbScratch -= 3*nBytes; |
1043 | | |
1044 | 1.23k | PSYMCRYPT_INT piTmpPtr; |
1045 | | |
1046 | 1.23k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
1047 | | |
1048 | | // If the data is not public, multiply by a random blinding factor; otherwise copy the value |
1049 | 1.23k | if( (flags & SYMCRYPT_FLAG_DATA_PUBLIC) == 0 ) |
1050 | 268 | { |
1051 | 268 | SymCryptModSetRandom( pmMod, peR, SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE | SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE, pbScratch, cbScratch ); //R = random |
1052 | 268 | SymCryptModMul( pmMod, peR, peSrc, peX, pbScratch, cbScratch ); // X = R * Src |
1053 | 268 | } else |
1054 | 969 | { |
1055 | 969 | SymCryptModElementCopy( pmMod, peSrc, peX ); |
1056 | 969 | } |
1057 | | |
1058 | | // Set up piA and piB |
1059 | 1.23k | SymCryptFdefModElementToIntGeneric( pmMod, &peX->d.uint32[0], piA, pbScratch, cbScratch ); // A = X |
1060 | 1.23k | SymCryptIntCopy( SymCryptIntFromModulus( (PSYMCRYPT_MODULUS) pmMod ), piB ); // B = Mod |
1061 | | |
1062 | | // Reject if A = 0, B = 0, or A and B both even |
1063 | 1.23k | if( SymCryptIntIsEqualUint32( piA, 0 ) | |
1064 | 1.23k | SymCryptIntIsEqualUint32( piB, 0 ) | |
1065 | 1.23k | (((SymCryptIntGetValueLsbits32( piA ) | SymCryptIntGetValueLsbits32( piB )) & 1) ^ 1) ) |
1066 | 0 | { |
1067 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1068 | 0 | goto cleanup; |
1069 | 0 | } |
1070 | | |
1071 | 1.23k | if( SymCryptIntIsEqualUint32( piB, 2 ) ) |
1072 | 0 | { |
1073 | | // Mod = 2 is a valid input. Luckilly, modular inversion is easy. |
1074 | | // The rest of the code assumes that Mod is odd. Other even values are not prime. |
1075 | 0 | SymCryptModElementCopy( pmMod, peSrc, peDst); |
1076 | 0 | goto cleanup; |
1077 | 0 | } |
1078 | | |
1079 | 1.23k | SymCryptFdefModElementSetValueUint32Generic( 1, pmMod, peVa, pbScratch, cbScratch ); // Va = 1 |
1080 | 1.23k | SymCryptFdefModElementSetValueUint32Generic( 0, pmMod, peVb, pbScratch, cbScratch ); // Vb = 0 |
1081 | | |
1082 | 1.23k | for(;;) |
1083 | 337k | { |
1084 | | // invariant: A = Va*X (mod Mod), B = Vb*X (mod Mod), A != 0, B > 1. |
1085 | | // Remove factors of 2 from A. This loop terminates because A != 0 |
1086 | 337k | leastSignificantUint32 = SymCryptIntGetValueLsbits32(piA); |
1087 | 674k | while( (leastSignificantUint32 & 1) == 0 ) |
1088 | 337k | { |
1089 | 337k | trailingZeros = SymCryptCountTrailingZeros32( leastSignificantUint32 ); |
1090 | 337k | SymCryptIntDivPow2( piA, trailingZeros, piA ); |
1091 | 337k | SymCryptFdefModDivSmallPow2( pmMod, peVa, trailingZeros, peVa ); |
1092 | 337k | leastSignificantUint32 = SymCryptIntGetValueLsbits32(piA); |
1093 | 337k | } |
1094 | | |
1095 | 337k | if( SymCryptIntIsEqualUint32( piA, 1 ) ) |
1096 | 1.23k | { |
1097 | | // A = 1 = Va * X (mod Mod), so Va is the inverse of X |
1098 | 1.23k | break; |
1099 | 1.23k | } |
1100 | | |
1101 | 336k | c = SymCryptIntSubSameSize( piB, piA, piT ); |
1102 | | |
1103 | | // If A != 1 and A=B, then A is the GCD of the original inputs, and there is no inverse |
1104 | 336k | if( SymCryptIntIsEqualUint32( piT, 0 ) ) |
1105 | 0 | { |
1106 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1107 | 0 | goto cleanup; |
1108 | 0 | } |
1109 | | |
1110 | 336k | if( c == 0 ) |
1111 | 182k | { |
1112 | | // B > A, we set B to B-A and swap (B,A) |
1113 | | // that way we continue our halving on B-A |
1114 | | |
1115 | 182k | SymCryptIntCopy( piT, piB ); |
1116 | 182k | SymCryptModSub( pmMod, peVb, peVa, peVb, pbScratch, cbScratch ); |
1117 | | |
1118 | 182k | piTmpPtr = piB; piB = piA; piA = piTmpPtr; |
1119 | 182k | peVtmpPtr = peVb; peVb = peVa; peVa = peVtmpPtr; |
1120 | 182k | } else { |
1121 | | // B < A, Set A to A-B and continue halving A |
1122 | 153k | SymCryptIntNeg( piT, piA ); |
1123 | 153k | SymCryptModSub( pmMod, peVa, peVb, peVa, pbScratch, cbScratch ); |
1124 | 153k | } |
1125 | 336k | } |
1126 | | |
1127 | | // 1 = A = Va * X (mod Mod), so Va is the inverse of X |
1128 | | // Check computation that we can test in the debugger |
1129 | 1.23k | SymCryptModMul( pmMod, peVa, peX, peVb, pbScratch, cbScratch ); |
1130 | | |
1131 | | // Actual answer |
1132 | | |
1133 | | // If the data is not public, multiply by the random blinding factor; otherwise copy the value |
1134 | 1.23k | if( (flags & SYMCRYPT_FLAG_DATA_PUBLIC) == 0 ) |
1135 | 268 | { |
1136 | 268 | SymCryptModMul( pmMod, peVa, peR, peDst, pbScratch, cbScratch ); |
1137 | 268 | } else |
1138 | 969 | { |
1139 | 969 | SymCryptModElementCopy( pmMod, peVa, peDst ); |
1140 | 969 | } |
1141 | | |
1142 | 1.23k | cleanup: |
1143 | 1.23k | return scError; |
1144 | 1.23k | } |
1145 | | |
1146 | | |
1147 | | //============================= |
1148 | | // Montgomery representation |
1149 | | |
1150 | | VOID |
1151 | | SYMCRYPT_CALL |
1152 | | SymCryptFdefModulusInitMontgomeryInternal( |
1153 | | _Inout_ PSYMCRYPT_MODULUS pmMod, |
1154 | | UINT32 nUint32Used, // R = 2^{32 * this parameter} |
1155 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1156 | | SIZE_T cbScratch ) |
1157 | 946 | { |
1158 | | // Scratch space is big enough for an nDigit+1 byte value + sufficient divmod scratch |
1159 | 946 | PUINT32 pR2; |
1160 | 946 | UINT32 cbR2; |
1161 | 946 | UINT32 nDigits; |
1162 | | |
1163 | 946 | PUINT32 modR2; |
1164 | 946 | PUINT32 negDivisor; |
1165 | | |
1166 | 946 | nDigits = pmMod->nDigits; |
1167 | 946 | modR2 = (PUINT32)((PBYTE)&pmMod->Divisor + SymCryptFdefSizeofDivisorFromDigits( nDigits )); |
1168 | | |
1169 | 946 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbScratch ); |
1170 | | |
1171 | 946 | pmMod->tm.montgomery.Rsqr = modR2; |
1172 | 946 | negDivisor = (PUINT32)((PBYTE)modR2 + (nDigits * SYMCRYPT_FDEF_DIGIT_SIZE)); |
1173 | | |
1174 | | // We pre-compute R^2 mod M |
1175 | | |
1176 | 946 | pR2 = (PUINT32) pbScratch; |
1177 | 946 | cbR2 = (2*nDigits + 1) * SYMCRYPT_FDEF_DIGIT_SIZE; |
1178 | 946 | SYMCRYPT_ASSERT( cbScratch >= cbR2 ); |
1179 | 946 | SYMCRYPT_ASSERT( cbScratch >= 2 * nUint32Used * sizeof(UINT32) ); |
1180 | | |
1181 | | // Set it to R^2 |
1182 | 946 | SymCryptWipe( pR2, cbR2 ); |
1183 | 946 | pR2[ 2 * nUint32Used ] = 1; |
1184 | 946 | SymCryptFdefRawDivMod( pR2, 2*nDigits + 1, &pmMod->Divisor, NULL, modR2, pbScratch + cbR2, cbScratch - cbR2 ); |
1185 | | |
1186 | 946 | SymCryptFdefRawNeg( SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), 0, negDivisor, nDigits ); |
1187 | 946 | } |
1188 | | |
1189 | | VOID |
1190 | | SYMCRYPT_CALL |
1191 | | SymCryptFdefModulusInitMontgomery( |
1192 | | _Inout_ PSYMCRYPT_MODULUS pmMod, |
1193 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1194 | | SIZE_T cbScratch ) |
1195 | 43 | { |
1196 | 43 | SymCryptFdefModulusInitMontgomeryInternal( pmMod, pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32, pbScratch, cbScratch ); |
1197 | 43 | } |
1198 | | |
1199 | | VOID |
1200 | | SymCryptFdefMontgomeryReduceC( |
1201 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1202 | | _Inout_updates_( 2 * pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pSrc, |
1203 | | _Out_writes_( pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pDst ) |
1204 | 0 | { |
1205 | 0 | UINT32 nDigits = pmMod->nDigits; |
1206 | 0 | UINT32 nWords = nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; |
1207 | 0 | PCUINT32 pMod = SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ); |
1208 | |
|
1209 | 0 | UINT32 hc = 0; |
1210 | 0 | for( UINT32 i=0; i<nWords; i++ ) |
1211 | 0 | { |
1212 | 0 | UINT32 m = (UINT32)pmMod->inv64 * pSrc[0]; |
1213 | 0 | UINT64 c = 0; |
1214 | 0 | for( UINT32 j = 0; j < nWords; j++ ) |
1215 | 0 | { |
1216 | | // Invariant: c < 2^32 |
1217 | 0 | c += SYMCRYPT_MUL32x32TO64( pMod[j], m ); |
1218 | 0 | c += pSrc[j]; |
1219 | | // There is no overflow on C because the max value is |
1220 | | // (2^32 - 1) * (2^32 - 1) + 2^32 - 1 + 2^32 - 1 = 2^64 - 1. |
1221 | 0 | pSrc[j] = (UINT32) c; |
1222 | 0 | c >>= 32; |
1223 | 0 | } |
1224 | 0 | c = c + pSrc[nWords] + hc; |
1225 | 0 | pSrc[nWords] = (UINT32) c; |
1226 | 0 | hc = c >> 32; |
1227 | 0 | pSrc++; |
1228 | 0 | } |
1229 | 0 | SYMCRYPT_ASSERT( hc < 2 ); |
1230 | |
|
1231 | 0 | UINT32 d = SymCryptFdefRawSub( pSrc, pMod, pDst, nDigits ); |
1232 | |
|
1233 | 0 | SYMCRYPT_ASSERT( hc <= d ); // if hc = 1, then d = 1 is mandatory |
1234 | |
|
1235 | 0 | SymCryptFdefMaskedCopy( (PCBYTE) pSrc, (PBYTE) pDst, nDigits, hc - (hc | d) ); // copy only if hc=0, d=1 |
1236 | 0 | } |
1237 | | |
1238 | | VOID |
1239 | | SymCryptFdefMontgomeryReduce( |
1240 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1241 | | _Inout_updates_( 2 * pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pSrc, |
1242 | | _Out_writes_( pmMod->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pDst ) |
1243 | 456k | { |
1244 | 456k | #if SYMCRYPT_CPU_AMD64 |
1245 | 456k | if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_MULX ) ) |
1246 | 0 | { |
1247 | 0 | SymCryptFdefMontgomeryReduceMulx( pmMod, pSrc, pDst ); |
1248 | 456k | } else { |
1249 | 456k | SymCryptFdefMontgomeryReduceAsm( pmMod, pSrc, pDst ); |
1250 | 456k | } |
1251 | | #elif SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_ARM |
1252 | | SymCryptFdefMontgomeryReduceAsm( pmMod, pSrc, pDst ); |
1253 | | #else |
1254 | | SymCryptFdefMontgomeryReduceC( pmMod, pSrc, pDst ); |
1255 | | #endif |
1256 | 456k | } |
1257 | | |
1258 | | |
1259 | | VOID |
1260 | | SYMCRYPT_CALL |
1261 | | SymCryptFdefModSetPostMontgomery( |
1262 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1263 | | _Inout_ PSYMCRYPT_MODELEMENT peObj, |
1264 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1265 | | SIZE_T cbScratch ) |
1266 | 577 | { |
1267 | | // Montgomery representation for X is R*X mod M where R = 2^<nDigits * bits-per-digit> |
1268 | | // Montgomery reduction performs an implicit division by R |
1269 | | // This function converts to the internal representation by multiplying by R^2 mod M and then performing a Montgomery reduction |
1270 | 577 | UINT32 nDigits = pmMod->nDigits; |
1271 | | |
1272 | | // dcl - this should not incur significant cost, consider checking always |
1273 | 577 | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1274 | 577 | UNREFERENCED_PARAMETER( cbScratch ); |
1275 | | |
1276 | 577 | SymCryptFdefRawMul( &peObj->d.uint32[0], nDigits, pmMod->tm.montgomery.Rsqr, nDigits, (PUINT32) pbScratch ); |
1277 | 577 | SymCryptFdefMontgomeryReduce( pmMod, (PUINT32) pbScratch, &peObj->d.uint32[0] ); |
1278 | 577 | } |
1279 | | |
1280 | | PCUINT32 |
1281 | | SYMCRYPT_CALL |
1282 | | SymCryptFdefModPreGetMontgomery( |
1283 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1284 | | _In_ PCSYMCRYPT_MODELEMENT peObj, |
1285 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1286 | | SIZE_T cbScratch ) |
1287 | 64 | { |
1288 | 64 | PUINT32 pTmp = (PUINT32) pbScratch; |
1289 | 64 | UINT32 nDigits = pmMod->nDigits; |
1290 | | |
1291 | | // dcl - this should not incur significant cost, consider checking always |
1292 | 64 | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1293 | 64 | UNREFERENCED_PARAMETER( cbScratch ); |
1294 | | |
1295 | 64 | memcpy( pTmp, &peObj->d.uint32[0], nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1296 | 64 | SymCryptWipe( pTmp + nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32, nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1297 | 64 | SymCryptFdefMontgomeryReduce( pmMod, pTmp, pTmp ); |
1298 | | |
1299 | 64 | return pTmp; |
1300 | 64 | } |
1301 | | |
1302 | | VOID |
1303 | | SYMCRYPT_CALL |
1304 | | SymCryptFdefModulusCopyFixupMontgomery( |
1305 | | _In_ PCSYMCRYPT_MODULUS pmSrc, |
1306 | | _Out_ PSYMCRYPT_MODULUS pmDst ) |
1307 | 0 | { |
1308 | | // We only have to fix up the Montgomery-specific stuff here |
1309 | | // dcl - not sure I understand why you pass pmSrc here |
1310 | 0 | UNREFERENCED_PARAMETER( pmSrc ); |
1311 | 0 | pmDst->tm.montgomery.Rsqr = (PUINT32)((PBYTE)&pmDst->Divisor + SymCryptFdefSizeofDivisorFromDigits( pmDst->nDigits )); |
1312 | 0 | } |
1313 | | |
1314 | | VOID |
1315 | | SYMCRYPT_CALL |
1316 | | SymCryptFdefModMulMontgomery( |
1317 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1318 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
1319 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
1320 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1321 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1322 | | SIZE_T cbScratch ) |
1323 | 300k | { |
1324 | 300k | UINT32 nDigits = pmMod->nDigits; |
1325 | 300k | PUINT32 pTmp = (PUINT32) pbScratch; |
1326 | | |
1327 | | // dcl - missing assert? |
1328 | 300k | UNREFERENCED_PARAMETER( cbScratch ); |
1329 | 300k | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1330 | | |
1331 | 300k | SymCryptFdefRawMul( &peSrc1->d.uint32[0], nDigits, &peSrc2->d.uint32[0], nDigits, pTmp ); |
1332 | 300k | SymCryptFdefMontgomeryReduce( pmMod, pTmp, &peDst->d.uint32[0] ); |
1333 | 300k | } |
1334 | | |
1335 | | #if SYMCRYPT_CPU_AMD64 |
1336 | | VOID |
1337 | | SYMCRYPT_CALL |
1338 | | SymCryptFdefModMulMontgomeryMulx( |
1339 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1340 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
1341 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
1342 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1343 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1344 | | SIZE_T cbScratch ) |
1345 | 0 | { |
1346 | 0 | UINT32 nDigits = pmMod->nDigits; |
1347 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1348 | |
|
1349 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1350 | 0 | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1351 | |
|
1352 | 0 | SymCryptFdefRawMulMulx( &peSrc1->d.uint32[0], nDigits, &peSrc2->d.uint32[0], nDigits, pTmp ); |
1353 | 0 | SymCryptFdefMontgomeryReduceMulx( pmMod, pTmp, &peDst->d.uint32[0] ); |
1354 | 0 | } |
1355 | | |
1356 | | VOID |
1357 | | SYMCRYPT_CALL |
1358 | | SymCryptFdefModMulMontgomeryMulx1024( |
1359 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1360 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
1361 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
1362 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1363 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1364 | | SIZE_T cbScratch ) |
1365 | 0 | { |
1366 | 0 | UINT32 nDigits = pmMod->nDigits; |
1367 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1368 | |
|
1369 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1370 | 0 | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1371 | |
|
1372 | 0 | SymCryptFdefRawMulMulx1024( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], nDigits, pTmp ); |
1373 | 0 | SymCryptFdefMontgomeryReduceMulx1024( pmMod, pTmp, &peDst->d.uint32[0] ); |
1374 | 0 | } |
1375 | | #endif |
1376 | | |
1377 | | |
1378 | | VOID |
1379 | | SYMCRYPT_CALL |
1380 | | SymCryptFdefModSquareMontgomery( |
1381 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1382 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1383 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1384 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1385 | | SIZE_T cbScratch ) |
1386 | 155k | { |
1387 | 155k | UINT32 nDigits = pmMod->nDigits; |
1388 | 155k | PUINT32 pTmp = (PUINT32) pbScratch; |
1389 | | |
1390 | 155k | UNREFERENCED_PARAMETER( cbScratch ); |
1391 | 155k | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1392 | | |
1393 | 155k | SymCryptFdefRawSquare( &peSrc->d.uint32[0], nDigits, pTmp ); |
1394 | 155k | SymCryptFdefMontgomeryReduce( pmMod, pTmp, &peDst->d.uint32[0] ); |
1395 | 155k | } |
1396 | | |
1397 | | |
1398 | | #if SYMCRYPT_CPU_AMD64 |
1399 | | VOID |
1400 | | SYMCRYPT_CALL |
1401 | | SymCryptFdefModSquareMontgomeryMulx( |
1402 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1403 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1404 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1405 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1406 | | SIZE_T cbScratch ) |
1407 | 0 | { |
1408 | 0 | UINT32 nDigits = pmMod->nDigits; |
1409 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1410 | |
|
1411 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1412 | 0 | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1413 | |
|
1414 | 0 | SymCryptFdefRawSquareMulx( &peSrc->d.uint32[0], nDigits, pTmp ); |
1415 | 0 | SymCryptFdefMontgomeryReduceMulx( pmMod, pTmp, &peDst->d.uint32[0] ); |
1416 | 0 | } |
1417 | | |
1418 | | VOID |
1419 | | SYMCRYPT_CALL |
1420 | | SymCryptFdefModSquareMontgomeryMulx1024( |
1421 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1422 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1423 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1424 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1425 | | SIZE_T cbScratch ) |
1426 | 0 | { |
1427 | 0 | UINT32 nDigits = pmMod->nDigits; |
1428 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1429 | |
|
1430 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1431 | 0 | SYMCRYPT_ASSERT( cbScratch >= 2 * nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1432 | |
|
1433 | 0 | SymCryptFdefRawSquareMulx1024( &peSrc->d.uint32[0], nDigits, pTmp ); |
1434 | 0 | SymCryptFdefMontgomeryReduceMulx1024( pmMod, pTmp, &peDst->d.uint32[0] ); |
1435 | 0 | } |
1436 | | #endif |
1437 | | |
1438 | | SYMCRYPT_ERROR |
1439 | | SYMCRYPT_CALL |
1440 | | SymCryptFdefModInvMontgomery( |
1441 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1442 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1443 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1444 | | UINT32 flags, |
1445 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1446 | | SIZE_T cbScratch ) |
1447 | 43 | { |
1448 | 43 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1449 | 43 | UINT32 nDigits = pmMod->nDigits; |
1450 | 43 | UINT32 nBytes = nDigits * SYMCRYPT_FDEF_DIGIT_SIZE; |
1451 | 43 | PUINT32 pTmp = (PUINT32) pbScratch; |
1452 | | |
1453 | 43 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pTmp ); |
1454 | | |
1455 | | // |
1456 | | // We have R*X; we first apply the montgomery reduction twice to get X/R, and then invert that |
1457 | | // using the generic inversion to get R/X. |
1458 | | // |
1459 | 43 | SYMCRYPT_ASSERT( cbScratch >= 2 * nBytes ); |
1460 | 43 | memcpy( pTmp, &peSrc->d.uint32[0], nBytes ); |
1461 | | |
1462 | 43 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
1463 | 43 | SymCryptFdefMontgomeryReduce( pmMod, pTmp, pTmp ); |
1464 | | |
1465 | 43 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
1466 | 43 | SymCryptFdefMontgomeryReduce( pmMod, pTmp, &peDst->d.uint32[0] ); |
1467 | | |
1468 | 43 | scError = SymCryptFdefModInvGeneric( pmMod, peDst, peDst, flags, pbScratch, cbScratch ); |
1469 | | |
1470 | 43 | return scError; |
1471 | 43 | } |
1472 | | |
1473 | | #if SYMCRYPT_CPU_AMD64 |
1474 | | |
1475 | | //===================================== |
1476 | | // 256-bit Montgomery modulus code |
1477 | | // |
1478 | | |
1479 | | SYMCRYPT_ERROR |
1480 | | SYMCRYPT_CALL |
1481 | | SymCryptFdefModInvMontgomery256( |
1482 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1483 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1484 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1485 | | UINT32 flags, |
1486 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1487 | | SIZE_T cbScratch ) |
1488 | 0 | { |
1489 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1490 | 0 | UINT32 nBytes = 32; |
1491 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1492 | |
|
1493 | 0 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pTmp ); |
1494 | | |
1495 | | // |
1496 | | // We have R*X; we first apply the montgomery reduction twice to get X/R, and then invert that |
1497 | | // using the generic inversion to get R/X. |
1498 | | // |
1499 | 0 | SYMCRYPT_ASSERT( cbScratch >= 2 * nBytes ); |
1500 | 0 | memcpy( pTmp, &peSrc->d.uint32[0], nBytes ); |
1501 | |
|
1502 | 0 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
1503 | 0 | SymCryptFdefMontgomeryReduce256Asm( pmMod, pTmp, pTmp ); |
1504 | |
|
1505 | 0 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
1506 | 0 | SymCryptFdefMontgomeryReduce256Asm( pmMod, pTmp, &peDst->d.uint32[0] ); |
1507 | |
|
1508 | 0 | scError = SymCryptFdefModInvGeneric( pmMod, peDst, peDst, flags, pbScratch, cbScratch ); |
1509 | |
|
1510 | 0 | return scError; |
1511 | 0 | } |
1512 | | |
1513 | | VOID |
1514 | | SYMCRYPT_CALL |
1515 | | SymCryptFdefModSetPostMontgomeryMulx256( |
1516 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1517 | | _Inout_ PSYMCRYPT_MODELEMENT peObj, |
1518 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1519 | | SIZE_T cbScratch ) |
1520 | 0 | { |
1521 | | // Montgomery representation for X is R*X mod M where R = 2^<nDigits * bits-per-digit> |
1522 | | // Montgomery reduction performs an implicit division by R |
1523 | | // This function converts to the internal representation by multiplying by R^2 mod M and then performing a Montgomery reduction |
1524 | 0 | UINT32 nDigits = pmMod->nDigits; |
1525 | |
|
1526 | 0 | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1527 | 0 | UNREFERENCED_PARAMETER( pbScratch ); |
1528 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1529 | 0 | UNREFERENCED_PARAMETER( nDigits ); |
1530 | |
|
1531 | 0 | SymCryptFdefModMulMontgomeryMulx256Asm( pmMod, (PSYMCRYPT_MODELEMENT) pmMod->tm.montgomery.Rsqr, peObj, peObj ); |
1532 | 0 | } |
1533 | | |
1534 | | PCUINT32 |
1535 | | SYMCRYPT_CALL |
1536 | | SymCryptFdefModPreGetMontgomery256( |
1537 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1538 | | _In_ PCSYMCRYPT_MODELEMENT peObj, |
1539 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1540 | | SIZE_T cbScratch ) |
1541 | 0 | { |
1542 | 0 | PUINT32 pTmp = (PUINT32) pbScratch; |
1543 | 0 | UINT32 nDigits = 1; |
1544 | |
|
1545 | 0 | SYMCRYPT_ASSERT( cbScratch >= nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1546 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1547 | |
|
1548 | 0 | memcpy( pTmp, &peObj->d.uint32[0], nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1549 | 0 | SymCryptFdefMontgomeryReduce256Asm( pmMod, pTmp, pTmp ); |
1550 | | |
1551 | | // This gives the right result, but relies on peObj having zeroed upper half |
1552 | | // on AMD64 when digits are 512 bits. This should be true - check in a CHKed build. |
1553 | 0 | for( UINT32 i=8; i<16; ++i ) |
1554 | 0 | { |
1555 | 0 | SYMCRYPT_ASSERT( pTmp[i] == 0 ); |
1556 | 0 | } |
1557 | | |
1558 | | // Wipe the extra bytes |
1559 | | // SymCryptWipeKnownSize( pTmp + (SYMCRYPT_FDEF_DIGIT_NUINT32 / 2), 32 ); |
1560 | |
|
1561 | 0 | return pTmp; |
1562 | 0 | } |
1563 | | |
1564 | | VOID |
1565 | | SYMCRYPT_CALL |
1566 | | SymCryptFdefModulusInitMontgomery256( |
1567 | | _Inout_ PSYMCRYPT_MODULUS pmMod, |
1568 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1569 | | SIZE_T cbScratch ) |
1570 | 0 | { |
1571 | 0 | SymCryptFdefModulusInitMontgomeryInternal( pmMod, 8, pbScratch, cbScratch ); |
1572 | 0 | } |
1573 | | |
1574 | | //===================================== |
1575 | | // 384-bit Montgomery modulus code |
1576 | | // |
1577 | | |
1578 | | VOID |
1579 | | SYMCRYPT_CALL |
1580 | | SymCryptFdefModSetPostMontgomeryMulxP384( |
1581 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1582 | | _Inout_ PSYMCRYPT_MODELEMENT peObj, |
1583 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1584 | | SIZE_T cbScratch ) |
1585 | 0 | { |
1586 | | // Montgomery representation for X is R*X mod M where R = 2^<nDigits * bits-per-digit> |
1587 | | // Montgomery reduction performs an implicit division by R |
1588 | | // This function converts to the internal representation by multiplying by R^2 mod M and then performing a Montgomery reduction |
1589 | 0 | UINT32 nDigits = pmMod->nDigits; |
1590 | |
|
1591 | 0 | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1592 | 0 | UNREFERENCED_PARAMETER( pbScratch ); |
1593 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
1594 | 0 | UNREFERENCED_PARAMETER( nDigits ); |
1595 | |
|
1596 | 0 | SymCryptFdefModMulMontgomeryMulxP384Asm( pmMod, (PSYMCRYPT_MODELEMENT) pmMod->tm.montgomery.Rsqr, peObj, peObj ); |
1597 | 0 | } |
1598 | | |
1599 | | #if 0 |
1600 | | //===================================== |
1601 | | // 512-bit Montgomery modulus code |
1602 | | // |
1603 | | |
1604 | | VOID |
1605 | | SYMCRYPT_CALL |
1606 | | SymCryptFdefModMulMontgomery512( |
1607 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1608 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
1609 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
1610 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1611 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1612 | | SIZE_T cbScratch ) |
1613 | | { |
1614 | | UINT32 nDigits = pmMod->nDigits; |
1615 | | PUINT32 pTmp = (PUINT32) pbScratch; |
1616 | | |
1617 | | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1618 | | UNREFERENCED_PARAMETER( cbScratch ); |
1619 | | |
1620 | | SymCryptFdefRawMul512Asm( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], nDigits, pTmp ); |
1621 | | SymCryptFdefMontgomeryReduce512Asm( pmMod, pTmp, &peDst->d.uint32[0] ); |
1622 | | } |
1623 | | |
1624 | | VOID |
1625 | | SYMCRYPT_CALL |
1626 | | SymCryptFdefModSquareMontgomery512( |
1627 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1628 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1629 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1630 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1631 | | SIZE_T cbScratch ) |
1632 | | { |
1633 | | UINT32 nDigits = pmMod->nDigits; |
1634 | | PUINT32 pTmp = (PUINT32) pbScratch; |
1635 | | |
1636 | | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1637 | | UNREFERENCED_PARAMETER( cbScratch ); |
1638 | | |
1639 | | SymCryptFdefRawSquare512Asm( &peSrc->d.uint32[0], nDigits, pTmp ); |
1640 | | SymCryptFdefMontgomeryReduce512Asm( pmMod, pTmp, &peDst->d.uint32[0] ); |
1641 | | } |
1642 | | |
1643 | | //===================================== |
1644 | | // 1024-bit Montgomery modulus code |
1645 | | // |
1646 | | |
1647 | | VOID |
1648 | | SYMCRYPT_CALL |
1649 | | SymCryptFdefModMulMontgomery1024( |
1650 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1651 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
1652 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
1653 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1654 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1655 | | SIZE_T cbScratch ) |
1656 | | { |
1657 | | UINT32 nDigits = pmMod->nDigits; |
1658 | | PUINT32 pTmp = (PUINT32) pbScratch; |
1659 | | |
1660 | | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1661 | | UNREFERENCED_PARAMETER( cbScratch ); |
1662 | | |
1663 | | SymCryptFdefRawMul1024Asm( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], nDigits, pTmp ); |
1664 | | SymCryptFdefMontgomeryReduce1024Asm( pmMod, pTmp, &peDst->d.uint32[0] ); |
1665 | | } |
1666 | | |
1667 | | VOID |
1668 | | SYMCRYPT_CALL |
1669 | | SymCryptFdefModSquareMontgomery1024( |
1670 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
1671 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
1672 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
1673 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
1674 | | SIZE_T cbScratch ) |
1675 | | { |
1676 | | UINT32 nDigits = pmMod->nDigits; |
1677 | | PUINT32 pTmp = (PUINT32) pbScratch; |
1678 | | |
1679 | | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
1680 | | UNREFERENCED_PARAMETER( cbScratch ); |
1681 | | |
1682 | | SymCryptFdefRawSquare1024Asm( &peSrc->d.uint32[0], nDigits, pTmp ); |
1683 | | SymCryptFdefMontgomeryReduce1024Asm( pmMod, pTmp, &peDst->d.uint32[0] ); |
1684 | | } |
1685 | | #endif |
1686 | | |
1687 | | #endif |