Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/fdef_int.c
15010 views
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
//
10
// Default big-number format:
11
// INT objects are stored in two parts:
12
// a SYMCRYPT_FDEF_INT structure
13
// an array of UINT32; the # elements in the array is a multiple of SYMCRYPT_FDEF_DIGIT_SIZE/4.
14
//
15
// The pointer passed points to the start of the UINT32 array, just after the SYMCRYPT_FDEF_INT structure.
16
//
17
// The generic implementation accesses the digits as an array of UINT32, but on 64-bit CPUs
18
// the code can also view it as an array of UINT64.
19
//
20
21
UINT32
22
SYMCRYPT_CALL
23
SymCryptFdefRawAddC(
24
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
25
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
26
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
27
UINT32 nDigits )
28
{
29
UINT32 i;
30
UINT64 t;
31
32
t = 0;
33
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
34
{
35
t = t + pSrc1[i] + pSrc2[i];
36
pDst[i] = (UINT32) t;
37
t >>= 32;
38
}
39
40
return (UINT32) t;
41
}
42
43
UINT32
44
SYMCRYPT_CALL
45
SymCryptFdefRawAdd(
46
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
47
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
48
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
49
UINT32 nDigits )
50
{
51
#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_ARM
52
return SymCryptFdefRawAddAsm( pSrc1, pSrc2, pDst, nDigits );
53
#else
54
return SymCryptFdefRawAddC( pSrc1, pSrc2, pDst, nDigits );
55
#endif
56
}
57
58
59
UINT32
60
SYMCRYPT_CALL
61
SymCryptFdefRawAddUint32(
62
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 Src1,
63
UINT32 Src2,
64
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 Dst,
65
UINT32 nDigits )
66
{
67
UINT32 i;
68
UINT64 t;
69
70
t = Src2;
71
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
72
{
73
t = t + Src1[i];
74
Dst[i] = (UINT32) t;
75
t >>= 32;
76
}
77
78
return (UINT32) t;
79
}
80
81
UINT32
82
SYMCRYPT_CALL
83
SymCryptFdefIntAddUint32(
84
_In_ PCSYMCRYPT_INT piSrc1,
85
UINT32 u32Src2,
86
_Out_ PSYMCRYPT_INT piDst )
87
{
88
SYMCRYPT_CHECK_MAGIC( piSrc1 );
89
SYMCRYPT_CHECK_MAGIC( piDst );
90
91
SYMCRYPT_ASSERT( piSrc1->nDigits == piDst->nDigits );
92
93
return SymCryptFdefRawAddUint32( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), u32Src2, SYMCRYPT_FDEF_INT_PUINT32( piDst ), piDst->nDigits );
94
}
95
96
UINT32
97
SYMCRYPT_CALL
98
SymCryptFdefIntAddSameSize(
99
_In_ PCSYMCRYPT_INT piSrc1,
100
_In_ PCSYMCRYPT_INT piSrc2,
101
_Out_ PSYMCRYPT_INT piDst )
102
{
103
SYMCRYPT_ASSERT( piSrc1->nDigits == piSrc2->nDigits && piSrc2->nDigits == piDst->nDigits );
104
105
return SymCryptFdefRawAdd( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ),
106
SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ),
107
SYMCRYPT_FDEF_INT_PUINT32( piDst ),
108
piDst->nDigits );
109
}
110
111
UINT32
112
SYMCRYPT_CALL
113
SymCryptFdefIntAddMixedSize(
114
_In_ PCSYMCRYPT_INT piSrc1,
115
_In_ PCSYMCRYPT_INT piSrc2,
116
_Out_ PSYMCRYPT_INT piDst )
117
{
118
UINT32 nS1 = piSrc1->nDigits;
119
UINT32 nS2 = piSrc2->nDigits;
120
UINT32 nD = piDst->nDigits;
121
UINT32 c;
122
UINT32 nW;
123
124
SYMCRYPT_ASSERT( nD >= nS1 && nD >= nS2 );
125
126
if( nS1 < nS2 )
127
{
128
c = SymCryptFdefRawAdd( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), SYMCRYPT_FDEF_INT_PUINT32( piDst ), nS1 );
129
c = SymCryptFdefRawAddUint32( &SYMCRYPT_FDEF_INT_PUINT32( piSrc2 )[nS1 * SYMCRYPT_FDEF_DIGIT_NUINT32], c, &SYMCRYPT_FDEF_INT_PUINT32( piDst )[nS1 * SYMCRYPT_FDEF_DIGIT_NUINT32], nS2 - nS1 );
130
nW = nS2;
131
} else {
132
// nS2 < nS1
133
c = SymCryptFdefRawAdd( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), SYMCRYPT_FDEF_INT_PUINT32( piDst ), nS2 );
134
c = SymCryptFdefRawAddUint32( &SYMCRYPT_FDEF_INT_PUINT32( piSrc1 )[nS2 * SYMCRYPT_FDEF_DIGIT_NUINT32], c, &SYMCRYPT_FDEF_INT_PUINT32( piDst )[nS2 * SYMCRYPT_FDEF_DIGIT_NUINT32], nS1 - nS2 );
135
nW = nS1;
136
}
137
138
if( nW < nD )
139
{
140
SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piDst )[nW * SYMCRYPT_FDEF_DIGIT_NUINT32], (nD - nW) * SYMCRYPT_FDEF_DIGIT_SIZE );
141
SYMCRYPT_FDEF_INT_PUINT32( piDst )[nW * SYMCRYPT_FDEF_DIGIT_NUINT32] = c;
142
c = 0;
143
}
144
145
return c;
146
}
147
148
UINT32
149
SYMCRYPT_CALL
150
SymCryptFdefRawSubC(
151
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
152
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
153
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
154
UINT32 nDigits )
155
{
156
UINT32 i;
157
UINT64 t;
158
UINT32 c;
159
160
c = 0;
161
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
162
{
163
// c == 1 for carry, 0 for no carry
164
t = (UINT64) pSrc1[i] - pSrc2[i] - c;
165
pDst[i] = (UINT32) t;
166
c = (UINT32)(t >> 32) & 1;
167
}
168
169
return c;
170
}
171
172
UINT32
173
SYMCRYPT_CALL
174
SymCryptFdefRawSub(
175
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
176
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
177
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
178
UINT32 nDigits )
179
{
180
#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_ARM
181
return SymCryptFdefRawSubAsm( pSrc1, pSrc2, pDst, nDigits );
182
#else
183
return SymCryptFdefRawSubC( pSrc1, pSrc2, pDst, nDigits );
184
#endif
185
}
186
187
188
UINT32
189
SYMCRYPT_CALL
190
SymCryptFdefRawSubUint32(
191
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
192
UINT32 Src2,
193
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
194
UINT32 nDigits )
195
{
196
UINT32 i;
197
UINT64 t;
198
UINT32 c;
199
200
c = Src2;
201
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
202
{
203
t = (UINT64)pSrc1[i] - c;
204
pDst[i] = (UINT32) t;
205
c = (UINT32)(t >> 32) & 1;
206
}
207
208
return c;
209
}
210
211
UINT32
212
SYMCRYPT_CALL
213
SymCryptFdefRawNeg(
214
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
215
UINT32 carryIn,
216
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
217
UINT32 nDigits )
218
{
219
UINT32 i;
220
UINT64 t;
221
UINT32 c;
222
223
c = carryIn;
224
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
225
{
226
t = (UINT64)0 - pSrc1[i] - c;
227
pDst[i] = (UINT32) t;
228
c = (UINT32)(t >> 32) & 1;
229
}
230
231
return c;
232
}
233
234
UINT32
235
SYMCRYPT_CALL
236
SymCryptFdefIntSubUint32(
237
_In_ PCSYMCRYPT_INT piSrc1,
238
UINT32 u32Src2,
239
_Out_ PSYMCRYPT_INT piDst )
240
{
241
SYMCRYPT_ASSERT( piSrc1->nDigits == piDst->nDigits );
242
243
return SymCryptFdefRawSubUint32( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), u32Src2, SYMCRYPT_FDEF_INT_PUINT32( piDst ), piDst->nDigits );
244
}
245
246
UINT32
247
SYMCRYPT_CALL
248
SymCryptFdefIntSubSameSize(
249
_In_ PCSYMCRYPT_INT piSrc1,
250
_In_ PCSYMCRYPT_INT piSrc2,
251
_Out_ PSYMCRYPT_INT piDst )
252
{
253
SYMCRYPT_ASSERT( piSrc1->nDigits == piSrc2->nDigits && piSrc1->nDigits == piDst->nDigits );
254
255
return SymCryptFdefRawSub( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), SYMCRYPT_FDEF_INT_PUINT32( piDst ), piDst->nDigits );
256
}
257
258
UINT32
259
SYMCRYPT_CALL
260
SymCryptFdefIntSubMixedSize(
261
_In_ PCSYMCRYPT_INT piSrc1,
262
_In_ PCSYMCRYPT_INT piSrc2,
263
_Out_ PSYMCRYPT_INT piDst )
264
{
265
UINT32 nS1 = piSrc1->nDigits;
266
UINT32 nS2 = piSrc2->nDigits;
267
UINT32 nD = piDst->nDigits;
268
UINT32 c;
269
UINT32 n;
270
271
SYMCRYPT_ASSERT( nD >= nS1 && nD >= nS2 );
272
273
if( nS1 < nS2 )
274
{
275
c = SymCryptFdefRawSub( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), SYMCRYPT_FDEF_INT_PUINT32( piDst ), nS1 );
276
c = SymCryptFdefRawNeg( &SYMCRYPT_FDEF_INT_PUINT32( piSrc2 )[nS1 * SYMCRYPT_FDEF_DIGIT_NUINT32], c, &SYMCRYPT_FDEF_INT_PUINT32( piDst )[nS1 * SYMCRYPT_FDEF_DIGIT_NUINT32], nS2 - nS1 );
277
n = nS2 * SYMCRYPT_FDEF_DIGIT_NUINT32;
278
} else {
279
// nS2 < nS1
280
c = SymCryptFdefRawSub( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), SYMCRYPT_FDEF_INT_PUINT32( piDst ), nS2 );
281
c = SymCryptFdefRawSubUint32( &SYMCRYPT_FDEF_INT_PUINT32( piSrc1 )[nS2 * SYMCRYPT_FDEF_DIGIT_NUINT32], c, &SYMCRYPT_FDEF_INT_PUINT32( piDst )[nS2 * SYMCRYPT_FDEF_DIGIT_NUINT32], nS1 - nS2 );
282
n = nS1 * SYMCRYPT_FDEF_DIGIT_NUINT32;
283
}
284
285
//
286
// Set the rest of the result to 0s or 1s
287
//
288
while( n < nD * SYMCRYPT_FDEF_DIGIT_NUINT32 )
289
{
290
SYMCRYPT_FDEF_INT_PUINT32( piDst )[n++] = 0 - c;
291
}
292
293
return c;
294
}
295
296
UINT32
297
SYMCRYPT_CALL
298
SymCryptFdefRawIsLessThanC(
299
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
300
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
301
UINT32 nDigits )
302
{
303
UINT32 i;
304
UINT64 t;
305
UINT32 c;
306
307
// We just do a subtraction without writing and return the carry
308
c = 0;
309
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
310
{
311
// c == 1 for carry, 0 for no carry
312
t = (UINT64) pSrc1[i] - pSrc2[i] - c;
313
c = (UINT32)(t >> 32) & 1;
314
}
315
316
// All booleans are returned as masks
317
return 0 - c;
318
}
319
320
UINT32
321
SYMCRYPT_CALL
322
SymCryptFdefRawIsLessThan(
323
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
324
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
325
UINT32 nDigits )
326
{
327
#if 0 & SYMCRYPT_CPU_AMD64
328
// return SymCryptFdefRawIsLessThanAsm( pSrc1, pSrc2, nDigits );
329
#else
330
return SymCryptFdefRawIsLessThanC( pSrc1, pSrc2, nDigits );
331
#endif
332
}
333
334
UINT32
335
SYMCRYPT_CALL
336
SymCryptFdefRawIsZeroC(
337
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
338
UINT32 nDigits )
339
{
340
UINT32 i;
341
UINT32 c;
342
343
c = 0;
344
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
345
{
346
c |= pSrc1[i];
347
}
348
349
// All booleans are returned as masks
350
return SYMCRYPT_MASK32_ZERO( c );
351
}
352
353
UINT32
354
SYMCRYPT_CALL
355
SymCryptFdefRawIsZero(
356
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
357
UINT32 nDigits )
358
{
359
#if 0 & SYMCRYPT_CPU_AMD64
360
// return SymCryptFdefRawIsZeroAsm( pSrc1, nDigits );
361
#else
362
return SymCryptFdefRawIsZeroC( pSrc1, nDigits );
363
#endif
364
}
365
366
UINT32
367
SYMCRYPT_CALL
368
SymCryptFdefIntIsLessThan(
369
_In_ PCSYMCRYPT_INT piSrc1,
370
_In_ PCSYMCRYPT_INT piSrc2 )
371
{
372
UINT32 nD1 = piSrc1->nDigits;
373
UINT32 nD2 = piSrc2->nDigits;
374
375
UINT32 res;
376
377
if( nD1 == nD2 )
378
{
379
res = SymCryptFdefRawIsLessThan( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), nD1 );
380
} else if( nD1 < nD2 ) {
381
res = SymCryptFdefRawIsLessThan( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), nD1 );
382
res |= ~SymCryptFdefRawIsZero( &SYMCRYPT_FDEF_INT_PUINT32( piSrc2 )[ nD1 * SYMCRYPT_FDEF_DIGIT_NUINT32 ], nD2 - nD1 );
383
} else {
384
res = SymCryptFdefRawIsLessThan( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), nD2 );
385
res &= SymCryptFdefRawIsZero( &SYMCRYPT_FDEF_INT_PUINT32( piSrc1 )[ nD2 * SYMCRYPT_FDEF_DIGIT_NUINT32 ], nD1 - nD2 );
386
}
387
388
return res;
389
}
390
391
392
VOID
393
SYMCRYPT_CALL
394
SymCryptFdefIntNeg(
395
_In_ PCSYMCRYPT_INT piSrc,
396
_Out_ PSYMCRYPT_INT piDst )
397
{
398
UINT32 nDigits = piDst->nDigits;
399
SYMCRYPT_ASSERT( piSrc->nDigits == nDigits );
400
401
SymCryptFdefRawNeg( SYMCRYPT_FDEF_INT_PUINT32( piSrc ), 0, SYMCRYPT_FDEF_INT_PUINT32( piDst ), nDigits );
402
}
403
404
405
VOID
406
SYMCRYPT_CALL
407
SymCryptFdefIntMulPow2(
408
_In_ PCSYMCRYPT_INT piSrc,
409
SIZE_T Exp,
410
_Out_ PSYMCRYPT_INT piDst )
411
{
412
SYMCRYPT_ASSERT( piSrc->nDigits == piDst->nDigits );
413
414
SIZE_T shiftWords = Exp / (8 * sizeof( UINT32 ) );
415
SIZE_T shiftBits = Exp % (8 * sizeof( UINT32 ) );
416
417
UINT32 nWords = piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32;
418
419
if( shiftWords >= nWords )
420
{
421
SymCryptWipe( SYMCRYPT_FDEF_INT_PUINT32( piDst ), nWords * sizeof( UINT32 ) );
422
goto cleanup;
423
}
424
425
SIZE_T i = nWords;
426
while( i > shiftWords )
427
{
428
i--;
429
UINT64 t = (UINT64)SYMCRYPT_FDEF_INT_PUINT32( piSrc )[i - shiftWords] << 32;
430
if( i > shiftWords )
431
{
432
t |= SYMCRYPT_FDEF_INT_PUINT32( piSrc )[i - shiftWords - 1];
433
}
434
SYMCRYPT_FDEF_INT_PUINT32( piDst )[i] = (UINT32)(t >> (32 - shiftBits));
435
}
436
437
while( i > 0 )
438
{
439
i--;
440
SYMCRYPT_FDEF_INT_PUINT32( piDst )[i] = 0;
441
}
442
443
cleanup:
444
;
445
}
446
447
// In shift-based operations which we have no assembly for, and we'd like to use 32-bit words
448
// on 32-bit architectures and 64-bit words on 64-bit architectures. So we use NATIVE_UINT &
449
// friends.
450
451
// Note that accessing the FDEF uint32 array as an array of NATIVE_UINTs relies on
452
// the little-endianness of the target if NATIVE_UINT is larger than 32 bits.
453
// AMD64 is little endian and ARM64 code is always expected to execute in little
454
// endian mode, but this is not true in general for an arbitrary 64 bit platform.
455
//
456
// If we need to support a 64 bit big endian platform, we need to either
457
// restrict its NATIVE_UINT to 32 bits, or introduce load and store macros.
458
#define SYMCRYPT_FDEF_INT_PNATIVE_UINT(p) ((NATIVE_UINT*) SYMCRYPT_FDEF_INT_PUINT32( p ))
459
// Ensure that sizeof(NATIVE_UINT) > 4 only when compiling for known little endian target
460
C_ASSERT( (NATIVE_BYTES <= 4) || SYMCRYPT_CPU_AMD64 || SYMCRYPT_CPU_ARM64 );
461
462
#define SYMCRYPT_FDEF_DIGIT_NNATIVE_UINT ((NATIVE_UINT)(SYMCRYPT_FDEF_DIGIT_SIZE / NATIVE_BYTES))
463
464
// Ensure that digit is divisible by native word size!
465
C_ASSERT(SYMCRYPT_FDEF_DIGIT_NNATIVE_UINT * NATIVE_BYTES == SYMCRYPT_FDEF_DIGIT_SIZE);
466
467
VOID
468
SYMCRYPT_CALL
469
SymCryptFdefIntDivPow2(
470
_In_ PCSYMCRYPT_INT piSrc,
471
SIZE_T exp,
472
_Out_ PSYMCRYPT_INT piDst )
473
{
474
SIZE_T shiftWords = exp / NATIVE_BITS;
475
SIZE_T shiftRightBits = exp % NATIVE_BITS;
476
SIZE_T shiftLeftBits = (NATIVE_BITS-1) - shiftRightBits;
477
NATIVE_UINT lowWord, highWord, highPart;
478
SIZE_T i = 0;
479
480
NATIVE_UINT nWords = piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NNATIVE_UINT;
481
482
SYMCRYPT_ASSERT( piSrc->nDigits == piDst->nDigits );
483
484
shiftWords = SYMCRYPT_MIN(shiftWords, nWords);
485
if( shiftWords < nWords )
486
{
487
lowWord = SYMCRYPT_FDEF_INT_PNATIVE_UINT(piSrc)[shiftWords];
488
while( i+shiftWords+1 < nWords )
489
{
490
highWord = SYMCRYPT_FDEF_INT_PNATIVE_UINT(piSrc)[i+shiftWords+1];
491
492
// We always shift highWord left by 1 to keep variable shiftLeftBits in range [0,NATIVE_BITS-1]
493
highPart = (highWord << shiftLeftBits)<<1;
494
495
SYMCRYPT_FDEF_INT_PNATIVE_UINT(piDst)[i] = (lowWord >> shiftRightBits) | highPart;
496
497
lowWord = highWord;
498
i++;
499
}
500
SYMCRYPT_FDEF_INT_PNATIVE_UINT(piDst)[i] = (lowWord >> shiftRightBits);
501
i++;
502
}
503
504
SYMCRYPT_ASSERT(i + shiftWords == nWords);
505
506
SymCryptWipe( &SYMCRYPT_FDEF_INT_PNATIVE_UINT( piDst )[nWords-shiftWords], shiftWords * NATIVE_BYTES );
507
}
508
509
VOID
510
SYMCRYPT_CALL
511
SymCryptFdefIntShr1(
512
UINT32 highestBit,
513
_In_ PCSYMCRYPT_INT piSrc,
514
_Out_ PSYMCRYPT_INT piDst )
515
{
516
UINT32 nWords = piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NNATIVE_UINT;
517
518
SYMCRYPT_ASSERT( piSrc->nDigits == piDst->nDigits );
519
SYMCRYPT_ASSERT( highestBit < 2 );
520
521
SIZE_T i = 0;
522
NATIVE_UINT lowWord = SYMCRYPT_FDEF_INT_PNATIVE_UINT(piSrc)[0];
523
NATIVE_UINT highWord = 0;
524
while( i+1 < nWords )
525
{
526
highWord = SYMCRYPT_FDEF_INT_PNATIVE_UINT(piSrc)[i+1];
527
528
SYMCRYPT_FDEF_INT_PNATIVE_UINT(piDst)[i] = (lowWord >> 1) | (highWord << (NATIVE_BITS - 1));
529
530
lowWord = highWord;
531
i++;
532
}
533
534
SYMCRYPT_FDEF_INT_PNATIVE_UINT(piDst)[i] = (lowWord >> 1) | ((NATIVE_UINT)highestBit) << (NATIVE_BITS - 1);
535
}
536
537
VOID
538
SYMCRYPT_CALL
539
SymCryptFdefIntModPow2(
540
_In_ PCSYMCRYPT_INT piSrc,
541
SIZE_T exp,
542
_Out_ PSYMCRYPT_INT piDst )
543
{
544
SIZE_T expWords = exp / 32; // index of word with the partial mask
545
SIZE_T expBits = exp % 32; // # bits to leave in that word
546
547
UINT32 nWords = piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32;
548
549
SYMCRYPT_ASSERT( piSrc->nDigits == piDst->nDigits );
550
551
if( piSrc != piDst )
552
{
553
memcpy( SYMCRYPT_FDEF_INT_PUINT32( piDst ), SYMCRYPT_FDEF_INT_PUINT32( piSrc ), nWords * sizeof( UINT32 ) );
554
}
555
556
if( expWords >= nWords )
557
{
558
// exp is so large that Dst = Src is sufficient.
559
goto cleanup;
560
}
561
562
for( SIZE_T i=expWords + 1; i < nWords; i++ )
563
{
564
SYMCRYPT_FDEF_INT_PUINT32( piDst )[i] = 0;
565
}
566
567
if( expBits != 0 )
568
{
569
SYMCRYPT_FDEF_INT_PUINT32( piDst )[expWords] &= ((UINT32) -1) >> (32 - expBits );
570
} else {
571
SYMCRYPT_FDEF_INT_PUINT32( piDst )[expWords] = 0;
572
}
573
574
cleanup:
575
;
576
}
577
578
UINT32
579
SYMCRYPT_CALL
580
SymCryptFdefIntGetBit(
581
_In_ PCSYMCRYPT_INT piSrc,
582
UINT32 iBit )
583
{
584
SYMCRYPT_ASSERT( iBit < piSrc->nDigits * SYMCRYPT_FDEF_DIGIT_BITS );
585
586
return (((SYMCRYPT_FDEF_INT_PUINT32( piSrc)[iBit / 32]) >> (iBit % 32)) & 1);
587
}
588
589
UINT32
590
SYMCRYPT_CALL
591
SymCryptFdefIntGetBits(
592
_In_ PCSYMCRYPT_INT piSrc,
593
UINT32 iBit,
594
UINT32 nBits )
595
{
596
UINT32 mainMask = 0;
597
UINT32 result = 0;
598
599
SYMCRYPT_ASSERT( (nBits > 0) &&
600
(nBits < 33) &&
601
(iBit < piSrc->nDigits * SYMCRYPT_FDEF_DIGIT_BITS) &&
602
(iBit + nBits <= piSrc->nDigits * SYMCRYPT_FDEF_DIGIT_BITS) );
603
604
mainMask = (UINT32)(-1) >> (32-nBits);
605
606
// Get the lower word first (it exists since iBit is smaller than the max bit)
607
result = SYMCRYPT_FDEF_INT_PUINT32(piSrc)[iBit/32];
608
609
// Shift to the right accordingly
610
result >>= (iBit%32);
611
612
// Get the upper word (if we need it)
613
// Note: the iBit and nBits values are public
614
if ((iBit%32!=0) && ( iBit/32 + 1 < piSrc->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ))
615
{
616
result |= ( SYMCRYPT_FDEF_INT_PUINT32(piSrc)[iBit/32+1] << (32 - iBit%32) );
617
}
618
619
// Mask out the top bits
620
result &= mainMask;
621
622
return result;
623
}
624
625
VOID
626
SYMCRYPT_CALL
627
SymCryptFdefIntSetBits(
628
_In_ PSYMCRYPT_INT piDst,
629
UINT32 value,
630
UINT32 iBit,
631
UINT32 nBits )
632
{
633
UINT32 mainMask = 0;
634
635
UINT32 alignedVal = 0;
636
UINT32 alignedMask = 0;
637
638
SYMCRYPT_ASSERT( (nBits > 0) &&
639
(nBits < 33) &&
640
(iBit < piDst->nDigits * SYMCRYPT_FDEF_DIGIT_BITS) &&
641
(iBit + nBits <= piDst->nDigits * SYMCRYPT_FDEF_DIGIT_BITS) );
642
643
// Zero out the not needed bits of the value
644
mainMask = (UINT32)(-1) >> (32-nBits);
645
value &= mainMask;
646
647
//
648
// Lower word
649
//
650
651
// Create the needed mask
652
alignedMask = mainMask << (iBit%32);
653
654
// Align the value
655
alignedVal = value << (iBit%32);
656
657
// Set the lower word first (it exists since iBit is smaller than the max bit)
658
SYMCRYPT_FDEF_INT_PUINT32(piDst)[iBit/32] = (SYMCRYPT_FDEF_INT_PUINT32(piDst)[iBit/32] & ~alignedMask) | alignedVal;
659
660
//
661
// Upper word
662
//
663
664
if ((iBit%32!=0) && ( iBit/32 + 1 < piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 ))
665
{
666
// Create the needed mask
667
alignedMask = mainMask >> (32 - iBit%32);
668
669
// Align the value
670
alignedVal = value >> (32 - iBit%32);
671
672
// Set the upper word
673
SYMCRYPT_FDEF_INT_PUINT32(piDst)[iBit/32 + 1] = (SYMCRYPT_FDEF_INT_PUINT32(piDst)[iBit/32 + 1] & ~alignedMask) | alignedVal;
674
}
675
676
}
677
678
679
UINT32
680
SYMCRYPT_CALL
681
SymCryptFdefIntMulUint32(
682
_In_ PCSYMCRYPT_INT piSrc1,
683
UINT32 Src2,
684
_Out_ PSYMCRYPT_INT piDst )
685
{
686
UINT32 nWords = piDst->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32;
687
688
SYMCRYPT_ASSERT( piSrc1->nDigits == piDst->nDigits );
689
690
UINT64 c = 0;
691
for( UINT32 i=0; i<nWords; i++ )
692
{
693
c += SYMCRYPT_MUL32x32TO64( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 )[i], Src2 );
694
SYMCRYPT_FDEF_INT_PUINT32( piDst )[i] = (UINT32) c;
695
c >>= 32;
696
}
697
698
return (UINT32) c;
699
}
700
701
702
VOID
703
SYMCRYPT_CALL
704
SymCryptFdefIntMulSameSize(
705
_In_ PCSYMCRYPT_INT piSrc1,
706
_In_ PCSYMCRYPT_INT piSrc2,
707
_Out_ PSYMCRYPT_INT piDst,
708
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
709
SIZE_T cbScratch )
710
{
711
SymCryptFdefIntMulMixedSize( piSrc1, piSrc2, piDst, pbScratch, cbScratch );
712
}
713
714
VOID
715
SYMCRYPT_CALL
716
SymCryptFdefIntSquare(
717
_In_ PCSYMCRYPT_INT piSrc,
718
_Out_ PSYMCRYPT_INT piDst,
719
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
720
SIZE_T cbScratch )
721
{
722
UINT32 nS = piSrc->nDigits;
723
UINT32 nD = piDst->nDigits;
724
725
SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_FDEF_SCRATCH_BYTES_FOR_INT_MUL( piDst->nDigits ) );
726
727
SYMCRYPT_ASSERT( 2*nS <= nD );
728
729
SymCryptFdefRawSquare( SYMCRYPT_FDEF_INT_PUINT32( piSrc ), nS, SYMCRYPT_FDEF_INT_PUINT32( piDst ) );
730
731
if( 2*nS < nD )
732
{
733
SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piDst )[2 * nS * SYMCRYPT_FDEF_DIGIT_NUINT32], (nD - 2*nS) * SYMCRYPT_FDEF_DIGIT_SIZE );
734
}
735
}
736
737
738
VOID
739
SYMCRYPT_CALL
740
SymCryptFdefRawMulC(
741
_In_reads_(nDigits1 * SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1,
742
UINT32 nDigits1,
743
_In_reads_(nDigits2 * SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc2,
744
UINT32 nDigits2,
745
_Out_writes_((nDigits1+nDigits2)*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
746
{
747
UINT32 nWords1 = nDigits1 * SYMCRYPT_FDEF_DIGIT_NUINT32;
748
UINT32 nWords2 = nDigits2 * SYMCRYPT_FDEF_DIGIT_NUINT32;
749
750
// Set Dst to zero
751
SymCryptWipe( pDst, (nDigits1+nDigits2) * SYMCRYPT_FDEF_DIGIT_SIZE );
752
753
for( UINT32 i = 0; i < nWords1; i++ )
754
{
755
UINT32 m = pSrc1[i];
756
UINT64 c = 0;
757
for( UINT32 j = 0; j < nWords2; j++ )
758
{
759
// Invariant: c < 2^32
760
c += SYMCRYPT_MUL32x32TO64( pSrc2[j], m );
761
c += pDst[i+j];
762
// There is no overflow on C because the max value is
763
// (2^32 - 1) * (2^32 - 1) + 2^32 - 1 + 2^32 - 1 = 2^64 - 1.
764
pDst[i+j] = (UINT32) c;
765
c >>= 32;
766
}
767
pDst[i + nWords2] = (UINT32) c;
768
}
769
}
770
771
VOID
772
SYMCRYPT_CALL
773
SymCryptFdefRawMul(
774
_In_reads_(nDigits1*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1,
775
UINT32 nDigits1,
776
_In_reads_(nDigits2*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc2,
777
UINT32 nDigits2,
778
_Out_writes_((nDigits1+nDigits2)*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
779
{
780
#if SYMCRYPT_CPU_AMD64
781
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_MULX ) )
782
{
783
SymCryptFdefRawMulMulx( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
784
} else {
785
SymCryptFdefRawMulAsm( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
786
}
787
#elif SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_ARM
788
SymCryptFdefRawMulAsm( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
789
#else
790
SymCryptFdefRawMulC( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
791
#endif
792
}
793
794
VOID
795
SYMCRYPT_CALL
796
SymCryptFdefRawSquareC(
797
_In_reads_(nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc,
798
UINT32 nDigits,
799
_Out_writes_(2*nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
800
{
801
UINT32 nWords = nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32;
802
803
UINT32 m = 0;
804
UINT64 c = 0;
805
806
// Set Dst to zero
807
SymCryptWipe( pDst, (2*nDigits) * SYMCRYPT_FDEF_DIGIT_SIZE );
808
809
// First Pass - Addition of the cross products x_i*x_j with i!=j
810
for( UINT32 i = 0; i < nWords; i++ )
811
{
812
m = pSrc[i];
813
c = 0;
814
for( UINT32 j = i+1; j < nWords; j++ )
815
{
816
// Invariant: c < 2^32
817
c += SYMCRYPT_MUL32x32TO64( pSrc[j], m );
818
c += pDst[i+j];
819
// There is no overflow on C because the max value is
820
// (2^32 - 1) * (2^32 - 1) + 2^32 - 1 + 2^32 - 1 = 2^64 - 1.
821
pDst[i+j] = (UINT32) c;
822
c >>= 32;
823
}
824
pDst[i + nWords] = (UINT32) c;
825
}
826
827
// Second Pass - Shifting all results 1 bit left
828
c = 0;
829
for( UINT32 i = 1; i < 2*nWords; i++ )
830
{
831
c |= (((UINT64)pDst[i])<<1);
832
pDst[i] = (UINT32)c;
833
c >>= 32;
834
}
835
836
// Third Pass - Adding the squares on the even columns and propagating the sum
837
c = 0;
838
for( UINT32 i = 0; i < nWords; i++ )
839
{
840
//
841
// Even column
842
//
843
m = pSrc[i];
844
c += SYMCRYPT_MUL32x32TO64( m, m );
845
c += pDst[2*i];
846
// There is no overflow on C because the max value is
847
// (2^32 - 1) * (2^32 - 1) + 2^32 - 1 + 2^32 - 1 = 2^64 - 1
848
849
pDst[2*i] = (UINT32) c;
850
c >>= 32;
851
852
//
853
// Odd column
854
//
855
c += pDst[2*i+1];
856
// There is no overflow on C because the max value is
857
// 2^32 - 1 + 2^32 - 1 = 2^33 - 2
858
859
pDst[2*i+1] = (UINT32) c;
860
c >>= 32;
861
}
862
}
863
864
VOID
865
SYMCRYPT_CALL
866
SymCryptFdefRawSquare(
867
_In_reads_(nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc,
868
UINT32 nDigits,
869
_Out_writes_(2*nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
870
{
871
#if SYMCRYPT_CPU_AMD64
872
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_MULX ) )
873
{
874
SymCryptFdefRawSquareMulx( pSrc, nDigits, pDst );
875
} else {
876
SymCryptFdefRawSquareAsm( pSrc, nDigits, pDst );
877
}
878
#elif SYMCRYPT_CPU_ARM64 | SYMCRYPT_CPU_ARM
879
SymCryptFdefRawSquareAsm( pSrc, nDigits, pDst );
880
#elif SYMCRYPT_CPU_X86
881
SymCryptFdefRawMulAsm( pSrc, nDigits, pSrc, nDigits, pDst );
882
#else
883
SymCryptFdefRawSquareC( pSrc, nDigits, pDst );
884
#endif
885
}
886
887
VOID
888
SYMCRYPT_CALL
889
SymCryptFdefIntMulMixedSize(
890
_In_ PCSYMCRYPT_INT piSrc1,
891
_In_ PCSYMCRYPT_INT piSrc2,
892
_Out_ PSYMCRYPT_INT piDst,
893
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
894
SIZE_T cbScratch )
895
{
896
UINT32 nS1 = piSrc1->nDigits;
897
UINT32 nS2 = piSrc2->nDigits;
898
UINT32 nD = piDst ->nDigits;
899
900
SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_FDEF_SCRATCH_BYTES_FOR_INT_MUL( piDst->nDigits ) );
901
902
SYMCRYPT_ASSERT( nS1 + nS2 <= nD );
903
904
SymCryptFdefRawMul( SYMCRYPT_FDEF_INT_PUINT32( piSrc1 ), nS1, SYMCRYPT_FDEF_INT_PUINT32( piSrc2 ), nS2, SYMCRYPT_FDEF_INT_PUINT32( piDst ) );
905
906
if( nS1 + nS2 < nD )
907
{
908
SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piDst )[(nS1 + nS2) * SYMCRYPT_FDEF_DIGIT_NUINT32], (nD - (nS1 + nS2)) * SYMCRYPT_FDEF_DIGIT_SIZE );
909
}
910
}
911
912
913
PSYMCRYPT_INT
914
SYMCRYPT_CALL
915
SymCryptFdefIntFromDivisor( _In_ PSYMCRYPT_DIVISOR pdSrc )
916
{
917
return &pdSrc->Int;
918
}
919
920
VOID
921
SYMCRYPT_CALL
922
SymCryptFdefIntToDivisor(
923
_In_ PCSYMCRYPT_INT piSrc,
924
_Out_ PSYMCRYPT_DIVISOR pdDst,
925
UINT32 totalOperations,
926
UINT32 flags,
927
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
928
SIZE_T cbScratch )
929
{
930
UINT32 W;
931
UINT32 nBits;
932
UINT32 nWords;
933
UINT32 bitToTest;
934
UINT64 P;
935
936
UNREFERENCED_PARAMETER( totalOperations );
937
UNREFERENCED_PARAMETER( flags );
938
939
SYMCRYPT_CHECK_MAGIC( piSrc );
940
SYMCRYPT_CHECK_MAGIC( pdDst );
941
942
SYMCRYPT_ASSERT( piSrc->nDigits == pdDst->nDigits );
943
944
SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_FDEF_SCRATCH_BYTES_FOR_INT_TO_DIVISOR( piSrc->nDigits ) );
945
946
//
947
// Copy the Int.
948
//
949
SymCryptFdefIntCopy( piSrc, &pdDst->Int );
950
951
//
952
// For an N-bit divisor M, and D-bit divisor digit size,
953
// the value W is defined as
954
// floor( (2^{N+D} - 1) / M } - 2^D
955
// which is the largest W such that (W * M + 2^D * M )< 2^{N+D}
956
// To compute W we use a binary search.
957
// This can be optimized, but this is the simplest side-channel safe solution.
958
// We can compute the upper bits of W * M + 2^D * M in a simple loop.
959
//
960
// For now we only compute a 32-bit W for a 32-bit digit divisor size.
961
//
962
963
nBits = SymCryptIntBitsizeOfValue( &pdDst->Int );
964
965
SYMCRYPT_ASSERT( nBits != 0 );
966
if( nBits == 0 )
967
{
968
// Can't create a divisor from a Int whose value is 0
969
970
// We really should not have any callers which get here (it is a requirement that Src != 0)
971
// We assert in CHKed builds
972
// In release set the divisor to 1 instead
973
SymCryptIntSetValueUint32( 1, &pdDst->Int );
974
}
975
976
pdDst->nBits = nBits;
977
978
nWords = (nBits + 31)/32;
979
bitToTest = (UINT32)1 << 31;
980
W = 0;
981
while( bitToTest > 0 )
982
{
983
W |= bitToTest;
984
// Do the multiplication
985
P = 0;
986
for( UINT32 i=0; i<nWords; i++ )
987
{
988
// Invariant:
989
// P <= 2^{2D} - 2 which ensures the mul-add doesn't generate an overflow
990
// P = floor( (W + 2^32)*M[0..i-1] / 2^{32*i} )
991
P += SYMCRYPT_MUL32x32TO64( W, SYMCRYPT_FDEF_INT_PUINT32( &pdDst->Int )[i] );
992
P >>= 32;
993
P += SYMCRYPT_FDEF_INT_PUINT32( &pdDst->Int )[i];
994
}
995
// We are interested in bit N+D, and P[0] is bit nWords*D, this shift brings the relevant bit to position 0
996
P >>= ((nBits+31) % 32) + 1;
997
// If the bit is 1, W*M is too large and we reset the corresponding bit in W.
998
W ^= bitToTest & (0 - ((UINT32)P & 1));
999
bitToTest >>= 1;
1000
}
1001
pdDst->td.fdef.W = W;
1002
1003
SYMCRYPT_SET_MAGIC( pdDst );
1004
}
1005
1006
UINT32
1007
SYMCRYPT_CALL
1008
SymCryptFdefRawMultSubUint32(
1009
_Inout_updates_( nUint32 + 1 ) PUINT32 pAcc,
1010
_In_reads_( nUint32 ) PCUINT32 pSrc1,
1011
UINT32 Src2,
1012
UINT32 nUint32 )
1013
{
1014
//
1015
// pAcc -= pSrc1 * Src2
1016
// BEWARE: this is only used by the DivMod routine, and works in Words rather than Digits
1017
// making optimizations hard.
1018
//
1019
1020
UINT32 i;
1021
UINT64 tmul;
1022
UINT64 tsub;
1023
UINT32 c;
1024
1025
tmul = 0;
1026
c = 0;
1027
for( i=0; i<nUint32; i++ )
1028
{
1029
tmul += SYMCRYPT_MUL32x32TO64( pSrc1[i], Src2 );
1030
tsub = (UINT64)pAcc[i] - (UINT32) tmul - c;
1031
pAcc[i] = (UINT32) tsub;
1032
c = (tsub >> 32) & 1;
1033
tmul >>= 32;
1034
}
1035
1036
// Writing the last word is strictly speaking not necessary, but a really good check that things are going right.
1037
// We can remove the write, but still need the computation of c so it gains very little.
1038
1039
tsub = (UINT64) pAcc[i] - (UINT32) tmul - c;
1040
pAcc[i] = (UINT32) tsub;
1041
c = (tsub >> 32) & 1;
1042
1043
return c;
1044
}
1045
1046
UINT32
1047
SYMCRYPT_CALL
1048
SymCryptFdefRawMaskedAddSubdigit(
1049
_Inout_updates_( nUint32 ) PUINT32 pAcc,
1050
_In_reads_( nUint32 ) PCUINT32 pSrc,
1051
UINT32 mask,
1052
UINT32 nUint32 )
1053
{
1054
UINT32 i;
1055
UINT64 t;
1056
1057
t = 0;
1058
for( i=0; i<nUint32; i++ )
1059
{
1060
t = t + pAcc[i] + (mask & pSrc[i]);
1061
pAcc[i] = (UINT32) t;
1062
t >>= 32;
1063
}
1064
1065
return (UINT32) t;
1066
}
1067
1068
UINT32
1069
SYMCRYPT_CALL
1070
SymCryptFdefRawMaskedAdd(
1071
_Inout_updates_( nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pAcc,
1072
_In_reads_( nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32 ) PCUINT32 pSrc,
1073
UINT32 mask,
1074
UINT32 nDigits )
1075
{
1076
return SymCryptFdefRawMaskedAddSubdigit( pAcc, pSrc, mask, nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32 );
1077
}
1078
1079
UINT32
1080
SYMCRYPT_CALL
1081
SymCryptFdefRawMaskedSub(
1082
_Inout_updates_( nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32 ) PUINT32 pAcc,
1083
_In_reads_( nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32 ) PCUINT32 pSrc,
1084
UINT32 mask,
1085
UINT32 nDigits )
1086
{
1087
UINT32 i;
1088
UINT64 t;
1089
UINT32 c;
1090
1091
c = 0;
1092
for( i=0; i<nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32; i++ )
1093
{
1094
t = (UINT64) pAcc[i] - (mask & pSrc[i]) - c;
1095
pAcc[i] = (UINT32) t;
1096
c = (UINT32)(t >>= 32) & 1;
1097
}
1098
1099
return c;
1100
}
1101
1102
1103
1104
VOID
1105
SYMCRYPT_CALL
1106
SymCryptFdefRawDivMod(
1107
_In_reads_(nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pNum,
1108
UINT32 nDigits,
1109
_In_ PCSYMCRYPT_DIVISOR pdDivisor,
1110
_Out_writes_opt_(nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pQuotient,
1111
_Out_writes_opt_(SYMCRYPT_OBJ_NUINT32(pdDivisor)) PUINT32 pRemainder,
1112
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
1113
SIZE_T cbScratch )
1114
{
1115
UINT32 nWords = nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32;
1116
UINT32 activeDivWords = (pdDivisor->nBits + 8 * sizeof(UINT32) - 1) / (8 * sizeof( UINT32 ) );
1117
UINT32 remainderWords = SYMCRYPT_OBJ_NUINT32( pdDivisor );
1118
1119
UINT32 cbScratchNeeded = (nWords+4) * sizeof( UINT32 );
1120
PUINT32 pTmp = (PUINT32) pbScratch;
1121
UINT32 Qest;
1122
UINT32 Q;
1123
UINT32 c;
1124
UINT32 d;
1125
UINT32 shift;
1126
UINT32 X0, X1;
1127
UINT32 W;
1128
UINT64 T;
1129
UINT32 nQ;
1130
1131
SYMCRYPT_ASSERT( cbScratch >= cbScratchNeeded );
1132
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbScratch );
1133
1134
if( nWords < activeDivWords )
1135
{
1136
//
1137
// input is smaller in size than the significant size of the divisor, no division to do.
1138
// Note that both values in the if() statement are public, so this does not create a side channel.
1139
//
1140
1141
// Set quotient to zero, and the remainder to the input value
1142
if( pQuotient != NULL )
1143
{
1144
SymCryptWipe( pQuotient, nDigits * SYMCRYPT_FDEF_DIGIT_SIZE );
1145
}
1146
1147
if( pRemainder != NULL )
1148
{
1149
SYMCRYPT_ASSERT( remainderWords >= nWords );
1150
memcpy( pRemainder, pNum, nWords * sizeof( UINT32 ) );
1151
SymCryptWipe( &pRemainder[nWords], (remainderWords - nWords) * sizeof( UINT32 ) ); // clear the rest of the remainder words
1152
}
1153
1154
SymCryptFdefClaimScratch( pbScratch, cbScratch, cbScratchNeeded );
1155
goto cleanup;
1156
}
1157
1158
//
1159
// We have two zero words in front and two zero words behind the tmp value to allow unrestricted accesses.
1160
// We keep the explicit offset of 2 rather than adjust the pTmp pointer to avoid negative indexes which appear
1161
// to be buffer overflows, and cause trouble with unsigned computations of negative index values that overflow
1162
// to 2^32 - 1 on a 64-bit CPU.
1163
//
1164
pTmp[0] = pTmp[1] = 0;
1165
memcpy( &pTmp[2], pNum, nWords * sizeof( UINT32 ) );
1166
pTmp[nWords + 2] = pTmp[nWords + 3] = 0;
1167
shift = (0 - pdDivisor->nBits) & 31; // # bits we have to shift top words to the left to align with the W value
1168
1169
// We generate the quotient words one at a time, starting at the most significant position
1170
// The top (divWords - 1) words are always zero
1171
1172
if( pQuotient != NULL )
1173
{
1174
SymCryptWipe( &pQuotient[nWords - activeDivWords + 1], (activeDivWords - 1) * sizeof( UINT32 ) );
1175
}
1176
1177
nQ = nWords - activeDivWords + 1;
1178
1179
// There is always at least one word of Q to be computed, so we can use a do-while loop which
1180
// also avoids the UINT32 underflow.
1181
do
1182
{
1183
nQ--;
1184
X0 = ( ((UINT64) pTmp[nQ + activeDivWords + 2] << 32) + pTmp[nQ + activeDivWords + 1] ) >> (32 - shift);
1185
X1 = ( ((UINT64) pTmp[nQ + activeDivWords + 1] << 32) + pTmp[nQ + activeDivWords + 0] ) >> (32 - shift);
1186
1187
W = (UINT32) pdDivisor->td.fdef.W;
1188
T = SYMCRYPT_MUL32x32TO64( W, X0 ) + (((UINT64)X0) << 32) + X1 + ((W>>1) & ((UINT32)0 - (X1 >> 31)));
1189
Qest = (UINT32)(T >> 32);
1190
// At this point the estimator is correct or one too small, add one but don't overflow
1191
Qest += 1;
1192
Qest += SYMCRYPT_MASK32_ZERO( Qest );
1193
1194
c = SymCryptFdefRawMultSubUint32( &pTmp[nQ+2], SYMCRYPT_FDEF_INT_PUINT32( &pdDivisor->Int ), Qest, activeDivWords );
1195
Q = Qest - c;
1196
d = SymCryptFdefRawMaskedAddSubdigit( &pTmp[nQ+2], SYMCRYPT_FDEF_INT_PUINT32( &pdDivisor->Int ), (0-c), activeDivWords );
1197
SYMCRYPT_ASSERT( c == d );
1198
SYMCRYPT_ASSERT( pTmp[nQ + activeDivWords+2] == (0 - c) );
1199
1200
if( pQuotient != NULL )
1201
{
1202
pQuotient[nQ] = Q;
1203
}
1204
} while( nQ > 0 );
1205
1206
if( pRemainder != NULL )
1207
{
1208
memcpy( pRemainder, pTmp+2, activeDivWords * sizeof( UINT32 ) );
1209
SymCryptWipe( &pRemainder[activeDivWords], (remainderWords - activeDivWords) * sizeof( UINT32 ) );
1210
}
1211
1212
cleanup:
1213
return; // label needs a statement to follow it...
1214
}
1215
1216
1217
VOID
1218
SYMCRYPT_CALL
1219
SymCryptFdefIntDivMod(
1220
_In_ PCSYMCRYPT_INT piSrc,
1221
_In_ PCSYMCRYPT_DIVISOR pdDivisor,
1222
_Out_opt_ PSYMCRYPT_INT piQuotient,
1223
_Out_opt_ PSYMCRYPT_INT piRemainder,
1224
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
1225
SIZE_T cbScratch )
1226
{
1227
UINT32 nDigits = SYMCRYPT_OBJ_NDIGITS( piSrc );
1228
1229
SYMCRYPT_ASSERT( piQuotient == NULL || piQuotient->nDigits >= piSrc->nDigits );
1230
SYMCRYPT_ASSERT( piRemainder == NULL || piRemainder->nDigits >= pdDivisor->nDigits );
1231
1232
SymCryptFdefRawDivMod(
1233
SYMCRYPT_FDEF_INT_PUINT32( piSrc ),
1234
nDigits,
1235
pdDivisor,
1236
piQuotient == NULL ? NULL : SYMCRYPT_FDEF_INT_PUINT32( piQuotient ),
1237
piRemainder == NULL ? NULL : SYMCRYPT_FDEF_INT_PUINT32( piRemainder ),
1238
pbScratch,
1239
cbScratch
1240
);
1241
1242
if ((piQuotient != NULL) && (piQuotient->nDigits > piSrc->nDigits))
1243
{
1244
SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piQuotient )[piSrc->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32], (piQuotient->nDigits - piSrc->nDigits) * SYMCRYPT_FDEF_DIGIT_SIZE );
1245
}
1246
1247
if ((piRemainder != NULL) && (piRemainder->nDigits > pdDivisor->nDigits))
1248
{
1249
SymCryptWipe( &SYMCRYPT_FDEF_INT_PUINT32( piRemainder )[pdDivisor->nDigits * SYMCRYPT_FDEF_DIGIT_NUINT32], (piRemainder->nDigits - pdDivisor->nDigits) * SYMCRYPT_FDEF_DIGIT_SIZE );
1250
}
1251
}
1252
1253
/* Wine hack: asm not supported yet */
1254
1255
UINT32
1256
SYMCRYPT_CALL
1257
SymCryptFdefRawAddAsm(
1258
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 Src1,
1259
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 Src2,
1260
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 Dst,
1261
UINT32 nDigits )
1262
{
1263
return SymCryptFdefRawAddC( Src1, Src2, Dst, nDigits );
1264
}
1265
1266
UINT32
1267
SYMCRYPT_CALL
1268
SymCryptFdefRawSubAsm(
1269
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc1,
1270
_In_reads_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PCUINT32 pSrc2,
1271
_Out_writes_bytes_(nDigits * SYMCRYPT_FDEF_DIGIT_SIZE ) PUINT32 pDst,
1272
UINT32 nDigits )
1273
{
1274
return SymCryptFdefRawSubC( pSrc1, pSrc2, pDst, nDigits );
1275
}
1276
1277
VOID
1278
SYMCRYPT_CALL
1279
SymCryptFdefRawMulAsm(
1280
_In_reads_(nDigits1*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1,
1281
UINT32 nDigits1,
1282
_In_reads_(nDigits2*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc2,
1283
UINT32 nDigits2,
1284
_Out_writes_((nDigits1+nDigits2)*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
1285
{
1286
SymCryptFdefRawMulC( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
1287
}
1288
1289
VOID
1290
SYMCRYPT_CALL
1291
SymCryptFdefRawSquareAsm(
1292
_In_reads_(nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc,
1293
UINT32 nDigits,
1294
_Out_writes_(2*nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
1295
{
1296
SymCryptFdefRawSquareC( pSrc, nDigits, pDst );
1297
}
1298
1299
/* Wine hack: asm not supported yet */
1300
1301
VOID
1302
SYMCRYPT_CALL
1303
SymCryptFdefRawSquareMulx(
1304
_In_reads_(nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc,
1305
UINT32 nDigits,
1306
_Out_writes_(2*nDigits*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
1307
{
1308
SymCryptFdefRawSquareC( pSrc, nDigits, pDst );
1309
}
1310
1311
VOID
1312
SYMCRYPT_CALL
1313
SymCryptFdefRawMulMulx(
1314
_In_reads_(nDigits1*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1,
1315
UINT32 nDigits1,
1316
_In_reads_(nDigits2*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc2,
1317
UINT32 nDigits2,
1318
_Out_writes_((nDigits1+nDigits2)*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst )
1319
{
1320
SymCryptFdefRawMulC( pSrc1, nDigits1, pSrc2, nDigits2, pDst );
1321
}
1322
1323