Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/ec_mul.c
15010 views
1
//
2
// ec_mul.c Generic multiplication algorithms for elliptic curves
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
//
11
// Most of the following algorithms were presented in the paper
12
// "Selecting Elliptic Curves for Cryptography: An Efficiency and
13
// Security Analysis" by Bos, Costello, Longa, and Naehrig
14
//
15
16
//
17
// The following is an adaptation of algorithm 4: "Precomputation
18
// scheme for Weierstrass curves"
19
//
20
// Input: Point P and number of precomputed points nPoints (=2^(w-2))
21
//
22
// Output: P[i] = (2*i+1)P for 0<=i<2^(w-2)
23
//
24
// Remarks:
25
// 1. We store each point in an array of 4*2^(w-2) = 2^w modelements where
26
// each point is represented with X,Y,Z Jacobian coordinates and the W=-Y
27
// negated Y coordinate (so that we can get the negative of a point easily)
28
// 2. The source point P is already in the 0'th position of the array.
29
//
30
VOID
31
SYMCRYPT_CALL
32
SymCryptPrecomputation(
33
_In_ PCSYMCRYPT_ECURVE pCurve,
34
UINT32 nPoints,
35
_In_reads_( SYMCRYPT_ECURVE_SW_MAX_NPRECOMP_POINTS )
36
PSYMCRYPT_ECPOINT * poPIs,
37
_Out_ PSYMCRYPT_ECPOINT poQ,
38
_Out_writes_bytes_( cbScratch )
39
PBYTE pbScratch,
40
SIZE_T cbScratch )
41
{
42
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poQ->pCurve) );
43
// Calculation for Q = 2*P
44
SymCryptEcpointDouble( pCurve, poPIs[0], poQ, 0, pbScratch, cbScratch );
45
46
for (UINT32 i=1; i<nPoints; i++)
47
{
48
// Calculation for (2i+1)*P = i*Q + P
49
SymCryptEcpointAddDiffNonZero( pCurve, poQ, poPIs[i-1], poPIs[i], pbScratch, cbScratch );
50
}
51
}
52
53
VOID
54
SYMCRYPT_CALL
55
SymCryptOfflinePrecomputation(
56
_In_ PSYMCRYPT_ECURVE pCurve,
57
_Out_writes_bytes_( cbScratch )
58
PBYTE pbScratch,
59
SIZE_T cbScratch )
60
{
61
PSYMCRYPT_ECPOINT poQ = NULL;
62
63
UINT32 cbEcpoint = SymCryptSizeofEcpointFromCurve( pCurve );
64
65
SYMCRYPT_ASSERT( cbScratch >= cbEcpoint + SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) );
66
67
poQ = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
68
SYMCRYPT_ASSERT( poQ != NULL );
69
pbScratch += cbEcpoint;
70
cbScratch -= cbEcpoint;
71
72
SymCryptPrecomputation(
73
pCurve,
74
pCurve->info.sw.nPrecompPoints,
75
pCurve->info.sw.poPrecompPoints,
76
poQ,
77
pbScratch,
78
cbScratch );
79
}
80
81
// Mask which is 0xffffffff only when _index == _target
82
#define DELTA_MASK( _index, _target) SYMCRYPT_MASK32_ZERO( (_index) ^ (_target) )
83
84
//
85
// The following is an adaptation of algorithm 1: "Variable-base scalar multiplication
86
// using the fixed-window method"
87
//
88
SYMCRYPT_ERROR
89
SYMCRYPT_CALL
90
SymCryptEcpointScalarMulFixedWindow(
91
_In_ PCSYMCRYPT_ECURVE pCurve,
92
_In_ PCSYMCRYPT_INT piScalar,
93
_In_opt_
94
PCSYMCRYPT_ECPOINT poSrc,
95
UINT32 flags,
96
_Out_ PSYMCRYPT_ECPOINT poDst,
97
_Out_writes_bytes_( cbScratch )
98
PBYTE pbScratch,
99
SIZE_T cbScratch )
100
{
101
SYMCRYPT_ERROR scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
102
103
PCSYMCRYPT_MODULUS FMod = pCurve->FMod;
104
105
UINT32 i, j;
106
107
UINT32 w = pCurve->info.sw.window;
108
UINT32 nPrecompPoints = pCurve->info.sw.nPrecompPoints;
109
// dcl - assuming that nRecodedDigits has some reasonably small range - please document
110
// so that we can know usage of this variable will not cause problems
111
// Also, documentation of inputs, notes, etc at the function definition would be quite helpful
112
UINT32 nRecodedDigits = ((pCurve->GOrdBitsize + w - 2) / (w-1)) + 1;
113
114
// Masks
115
UINT32 fZero = 0;
116
UINT32 fEven = 0;
117
UINT32 indexMask = 0;
118
119
BOOLEAN bPrecompOffline = FALSE;
120
121
// ====================================================
122
// Temporaries
123
PSYMCRYPT_MODELEMENT peT = NULL;
124
PSYMCRYPT_ECPOINT poPIs[SYMCRYPT_ECURVE_SW_MAX_NPRECOMP_POINTS] = { 0 };
125
PSYMCRYPT_ECPOINT poQ = NULL;
126
PSYMCRYPT_ECPOINT poTmp = NULL;
127
PSYMCRYPT_INT piRem = NULL;
128
PSYMCRYPT_INT piTmp = NULL;
129
PUINT32 absofKIs = NULL;
130
PUINT32 sigofKIs = NULL;
131
// ===================================================
132
133
PSYMCRYPT_MODELEMENT peQX = NULL;
134
PSYMCRYPT_MODELEMENT peQY = NULL;
135
PSYMCRYPT_MODELEMENT peQZ = NULL;
136
137
SIZE_T cbEcpoint = SymCryptSizeofEcpointFromCurve( pCurve );
138
SIZE_T cbScalar = SymCryptSizeofIntFromDigits( pCurve->GOrdDigits );
139
140
// Make sure we only specify the correct flags
141
if ((flags & ~SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL) != 0)
142
{
143
scError = SYMCRYPT_INVALID_ARGUMENT;
144
goto exit;
145
}
146
147
// Check if poSrc is NULL and if yes set it to G
148
if (poSrc == NULL)
149
{
150
poSrc = pCurve->G;
151
bPrecompOffline = TRUE;
152
}
153
154
SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ||
155
SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
156
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
157
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS(pCurve, 1) );
158
159
SYMCRYPT_ASSERT( cbScratch >=
160
pCurve->cbModElement +
161
(nPrecompPoints+2)*cbEcpoint +
162
2*cbScalar +
163
((2*nRecodedDigits*sizeof(UINT32) + SYMCRYPT_ASYM_ALIGN_VALUE - 1)/SYMCRYPT_ASYM_ALIGN_VALUE )*SYMCRYPT_ASYM_ALIGN_VALUE +
164
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
165
166
// Creating temporary modelement
167
peT = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, FMod );
168
SYMCRYPT_ASSERT( peT != NULL );
169
pbScratch += pCurve->cbModElement;
170
171
// Creating temporary precomputed points (if needed)
172
SYMCRYPT_ASSERT( nPrecompPoints <= SYMCRYPT_ECURVE_SW_MAX_NPRECOMP_POINTS );
173
for (i=0; i<nPrecompPoints; i++)
174
{
175
if (bPrecompOffline)
176
{
177
poPIs[i] = pCurve->info.sw.poPrecompPoints[i];
178
}
179
else
180
{
181
poPIs[i] = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
182
SYMCRYPT_ASSERT( poPIs[i] != NULL );
183
pbScratch += cbEcpoint;
184
}
185
}
186
187
// Creating temporary points
188
poQ = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
189
SYMCRYPT_ASSERT( poQ != NULL );
190
pbScratch += cbEcpoint;
191
192
poTmp = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
193
SYMCRYPT_ASSERT( poTmp != NULL );
194
pbScratch += cbEcpoint;
195
196
// Creating temporary scalar for the remainder
197
piRem = SymCryptIntCreate( pbScratch, cbScalar, pCurve->GOrdDigits );
198
SYMCRYPT_ASSERT( piRem != NULL);
199
pbScratch += cbScalar;
200
201
piTmp = SymCryptIntCreate( pbScratch, cbScalar, pCurve->GOrdDigits );
202
SYMCRYPT_ASSERT( piTmp != NULL);
203
pbScratch += cbScalar;
204
205
// Fixing pointers to recoded digits (be careful that the remaining space is SYMCRYPT_ASYM_ALIGNed)
206
absofKIs = (PUINT32) pbScratch;
207
pbScratch += nRecodedDigits * sizeof(UINT32);
208
sigofKIs = (PUINT32) pbScratch;
209
pbScratch += nRecodedDigits * sizeof(UINT32);
210
pbScratch = (PBYTE) ( ((SIZE_T)pbScratch + SYMCRYPT_ASYM_ALIGN_VALUE - 1) & ~(SYMCRYPT_ASYM_ALIGN_VALUE - 1) );
211
212
// Fixing remaining scratch space size
213
cbScratch -= ( pCurve->cbModElement + (nPrecompPoints+2)*cbEcpoint + 2*cbScalar );
214
cbScratch -= (((2*nRecodedDigits*sizeof(UINT32) + SYMCRYPT_ASYM_ALIGN_VALUE - 1)/SYMCRYPT_ASYM_ALIGN_VALUE )*SYMCRYPT_ASYM_ALIGN_VALUE);
215
216
//
217
// Main algorithm
218
//
219
220
// It is the caller's responsibility to ensure that the provided piScalar <= GOrd, double check this in debug mode
221
SYMCRYPT_ASSERT( !SymCryptIntIsLessThan( SymCryptIntFromModulus( pCurve->GOrd ), piScalar ) );
222
223
// Store k into an int
224
SymCryptIntCopy( piScalar, piRem );
225
226
// Check if k is 0
227
fZero = SymCryptIntIsEqualUint32( piRem, 0 );
228
229
// Or if the src point is zero
230
fZero |= SymCryptEcpointIsZero( pCurve, poSrc, pbScratch, cbScratch );
231
232
// Check if k is even and convert it to r-k if true
233
fEven = SYMCRYPT_MASK32_ZERO(SymCryptIntGetBit( piRem, 0 ));
234
SymCryptIntSubSameSize( SymCryptIntFromModulus(pCurve->GOrd), piRem, piTmp);
235
SymCryptIntMaskedCopy( piTmp, piRem, fEven );
236
237
// Recoding stage
238
SymCryptFixedWindowRecoding( w, piRem, piTmp, absofKIs, sigofKIs, nRecodedDigits );
239
240
// Precomputation stage
241
if (!bPrecompOffline)
242
{
243
// Copy the first point in the start of the poPIs array
244
SymCryptEcpointCopy( pCurve, poSrc, poPIs[0] );
245
246
SymCryptPrecomputation( pCurve, nPrecompPoints, poPIs, poQ, pbScratch, cbScratch );
247
}
248
249
250
// Get the pointers to Q
251
peQX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poQ );
252
peQY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poQ );
253
peQZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poQ );
254
255
// Q = P[ (|k_t|-1)/2 ] in memory access side-channel safe way
256
// That is, we touch all the precomputed points. The access pattern of KIs is fixed.
257
for (j=0; j<nPrecompPoints; j++)
258
{
259
indexMask = DELTA_MASK( j, absofKIs[nRecodedDigits-1] );
260
SymCryptEcpointMaskedCopy( pCurve, poPIs[j], poQ, indexMask);
261
}
262
263
for (i=nRecodedDigits - 2; i>0; i--)
264
{
265
// Q = 2^(w-1) * Q
266
for (j=0; j<w-1; j++)
267
{
268
SymCryptEcpointDouble( pCurve, poQ, poQ, 0, pbScratch, cbScratch );
269
}
270
271
// Copy the required precomputed point into poTmp (touch all points)
272
for (j=0; j<nPrecompPoints; j++)
273
{
274
indexMask = DELTA_MASK( j, absofKIs[i] );
275
SymCryptEcpointMaskedCopy( pCurve, poPIs[j], poTmp, indexMask);
276
}
277
278
// Negate if needed
279
SymCryptEcpointNegate( pCurve, poTmp, sigofKIs[i], pbScratch, cbScratch );
280
281
// Do the addition Q + s_i P[k_i]
282
SymCryptEcpointAddDiffNonZero( pCurve, poQ, poTmp, poQ, pbScratch, cbScratch );
283
}
284
285
// Q = 2^(w-1) * Q
286
for (j=0; j<w-1; j++)
287
{
288
SymCryptEcpointDouble( pCurve, poQ, poQ, 0, pbScratch, cbScratch );
289
}
290
291
// Copy the point s_0 P[k_0] into poTmp
292
for (j=0; j<nPrecompPoints; j++)
293
{
294
indexMask = DELTA_MASK( j, absofKIs[0] );
295
SymCryptEcpointMaskedCopy( pCurve, poPIs[j], poTmp, indexMask);
296
}
297
298
// Negate if needed
299
SymCryptEcpointNegate( pCurve, poTmp, sigofKIs[0], pbScratch, cbScratch );
300
301
// Complete addition routine
302
SymCryptEcpointAdd( pCurve, poQ, poTmp, poQ, 0, pbScratch, cbScratch );
303
304
// If even invert
305
SymCryptEcpointNegate( pCurve, poQ, fEven, pbScratch, cbScratch );
306
307
// Multiply by the cofactor (if needed) by continuing the doubling
308
if ((pCurve->coFactorPower!=0) && ((flags & SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL) != 0))
309
{
310
for (j=0; j<pCurve->coFactorPower; j++)
311
{
312
SymCryptEcpointDouble( pCurve, poQ, poQ, 0, pbScratch, cbScratch );
313
}
314
}
315
316
// If the resultant point is zero, ensure it will be set to the canonical zero point
317
fZero |= SymCryptEcpointIsZero( pCurve, poQ, pbScratch, cbScratch );
318
319
// Set the zero point
320
SymCryptEcpointSetZero( pCurve, poTmp, pbScratch, cbScratch );
321
SymCryptEcpointMaskedCopy( pCurve, poTmp, poQ, fZero );
322
323
// Output the result (normalized flag == FALSE)
324
SymCryptEcpointCopy( pCurve, poQ, poDst );
325
326
scError = SYMCRYPT_NO_ERROR;
327
328
exit:
329
330
return scError;
331
}
332
333
//
334
// The following is an adaptation of algorithm 9: "Double-scalar multiplication using the
335
// width-w NAF with interleaving"
336
//
337
SYMCRYPT_ERROR
338
SYMCRYPT_CALL
339
SymCryptEcpointMultiScalarMulWnafWithInterleaving(
340
_In_ PCSYMCRYPT_ECURVE pCurve,
341
_In_reads_( nPoints ) PCSYMCRYPT_INT * piSrcScalarArray,
342
_In_reads_( nPoints ) PCSYMCRYPT_ECPOINT * poSrcEcpointArray,
343
_In_ UINT32 nPoints,
344
_In_ UINT32 flags,
345
_Out_ PSYMCRYPT_ECPOINT poDst,
346
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
347
SIZE_T cbScratch )
348
{
349
SYMCRYPT_ERROR scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
350
351
UINT32 i, j;
352
353
UINT32 w = pCurve->info.sw.window;
354
UINT32 nPrecompPoints = pCurve->info.sw.nPrecompPoints; // One table for each base
355
UINT32 nRecodedDigits = pCurve->GOrdBitsize + 1; // Notice the difference with the fixed window
356
357
// Masks
358
UINT32 fZero[SYMCRYPT_ECURVE_MULTI_SCALAR_MUL_MAX_NPOINTS] = { 0 };
359
UINT32 fZeroTot = 0xffffffff;
360
361
BOOLEAN bPrecompOffline = FALSE;
362
363
// ====================================================
364
// Temporaries
365
PSYMCRYPT_ECPOINT poPIs[SYMCRYPT_ECURVE_SW_MAX_NPRECOMP_POINTS] = { 0 };
366
PSYMCRYPT_ECPOINT poQ = NULL;
367
PSYMCRYPT_ECPOINT poTmp = NULL;
368
PSYMCRYPT_INT piRem = NULL;
369
PSYMCRYPT_INT piTmp = NULL;
370
371
PUINT32 absofKIs = NULL;
372
PUINT32 sigofKIs = NULL;
373
// ===================================================
374
375
SIZE_T cbEcpoint = SymCryptSizeofEcpointFromCurve( pCurve );
376
SIZE_T cbScalar = SymCryptSizeofIntFromDigits( pCurve->GOrdDigits );
377
378
PBYTE pbScratchEnd = pbScratch + cbScratch;
379
UNREFERENCED_PARAMETER( pbScratchEnd ); // Used in asserts
380
381
// Make sure we only specify the correct flags
382
if ((flags & ~(SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL)) != 0)
383
{
384
scError = SYMCRYPT_INVALID_ARGUMENT;
385
goto exit;
386
}
387
388
// Check the maximum number of points
389
if (nPoints > SYMCRYPT_ECURVE_MULTI_SCALAR_MUL_MAX_NPOINTS)
390
{
391
scError = SYMCRYPT_NOT_IMPLEMENTED;
392
goto exit;
393
}
394
395
// Check if the first point is NULL
396
if (poSrcEcpointArray[0] == NULL)
397
{
398
poSrcEcpointArray[0] = pCurve->G;
399
bPrecompOffline = TRUE;
400
}
401
402
// Make sure that the non side-channel flag is specified
403
if ((flags & SYMCRYPT_FLAG_DATA_PUBLIC) == 0 )
404
{
405
scError = SYMCRYPT_NOT_IMPLEMENTED;
406
goto exit;
407
}
408
409
SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ||
410
SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
411
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
412
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS(pCurve, nPoints) );
413
414
// Creating temporary precomputed points (if needed for the first point)
415
for (i=0; i<nPoints*nPrecompPoints; i++)
416
{
417
if ((i<nPrecompPoints) && bPrecompOffline)
418
{
419
poPIs[i] = pCurve->info.sw.poPrecompPoints[i];
420
}
421
else
422
{
423
SYMCRYPT_ASSERT( pbScratch + cbEcpoint <= pbScratchEnd );
424
poPIs[i] = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
425
SYMCRYPT_ASSERT( poPIs[i] != NULL );
426
pbScratch += cbEcpoint;
427
}
428
}
429
430
SYMCRYPT_ASSERT( pbScratch + 2*cbEcpoint + 2*cbScalar + 2*nPoints*nRecodedDigits*sizeof(UINT32) <= pbScratchEnd );
431
// Creating temporary points
432
poQ = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
433
SYMCRYPT_ASSERT( poQ != NULL );
434
pbScratch += cbEcpoint;
435
436
poTmp = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve );
437
SYMCRYPT_ASSERT( poTmp != NULL );
438
pbScratch += cbEcpoint;
439
440
// Creating temporary scalar for the remainder
441
piRem = SymCryptIntCreate( pbScratch, cbScalar, pCurve->GOrdDigits );
442
SYMCRYPT_ASSERT( piRem != NULL);
443
pbScratch += cbScalar;
444
445
piTmp = SymCryptIntCreate( pbScratch, cbScalar, pCurve->GOrdDigits );
446
SYMCRYPT_ASSERT( piTmp != NULL);
447
pbScratch += cbScalar;
448
449
// Fixing pointers to recoded digits (be careful that the remaining space is SYMCRYPT_ASYM_ALIGNed)
450
absofKIs = (PUINT32) pbScratch;
451
pbScratch += nPoints * nRecodedDigits * sizeof(UINT32);
452
sigofKIs = (PUINT32) pbScratch;
453
pbScratch += nPoints * nRecodedDigits * sizeof(UINT32);
454
pbScratch = (PBYTE) ( ((SIZE_T)pbScratch + SYMCRYPT_ASYM_ALIGN_VALUE - 1) & ~(SYMCRYPT_ASYM_ALIGN_VALUE - 1) );
455
456
// Fixing remaining scratch space size
457
// dcl - my guess is that the values here are small enough that there should not be a problem, but
458
// would be better if that were documented.
459
cbScratch -= ( (nPoints*nPrecompPoints+2)*cbEcpoint + 2*cbScalar );
460
cbScratch -= (((2*nPoints*nRecodedDigits*sizeof(UINT32) + SYMCRYPT_ASYM_ALIGN_VALUE - 1)/SYMCRYPT_ASYM_ALIGN_VALUE )*SYMCRYPT_ASYM_ALIGN_VALUE);
461
462
//
463
// Main algorithm
464
//
465
for (j = 0; j<nPoints; j++)
466
{
467
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrcEcpointArray[j]->pCurve) );
468
469
// Check if k is 0 or if the src point is zero
470
fZero[j] = ( SymCryptIntIsEqualUint32( piSrcScalarArray[j], 0 ) | SymCryptEcpointIsZero( pCurve, poSrcEcpointArray[j], pbScratch, cbScratch ) );
471
fZeroTot &= fZero[j];
472
473
// Skip the recoding stage (and all remaining steps) if this point will give result zero
474
if (!fZero[j])
475
{
476
SymCryptIntCopy( piSrcScalarArray[j], piRem );
477
478
// Recoding stage
479
SymCryptWidthNafRecoding( w, piRem, &absofKIs[j*nRecodedDigits], &sigofKIs[j*nRecodedDigits], nRecodedDigits );
480
481
// Precomputation stage
482
if ((j>0) || !bPrecompOffline)
483
{
484
// Copy the first point in the start of the poPIs array
485
SymCryptEcpointCopy( pCurve, poSrcEcpointArray[j], poPIs[j*nPrecompPoints] );
486
487
SymCryptPrecomputation( pCurve, nPrecompPoints, &poPIs[j*nPrecompPoints], poQ, pbScratch, cbScratch );
488
}
489
}
490
}
491
492
// Set poQ to zero point
493
SymCryptEcpointSetZero( pCurve, poQ, pbScratch, cbScratch );
494
495
if (!fZeroTot)
496
{
497
// Main loop
498
for (INT32 i = nRecodedDigits-1; i>-1; i--)
499
{
500
SymCryptEcpointDouble( pCurve, poQ, poQ, 0, pbScratch, cbScratch );
501
502
for (j = 0; j<nPoints; j++)
503
{
504
if (!fZero[j] && sigofKIs[j*nRecodedDigits + i] != 0)
505
{
506
SymCryptEcpointCopy( pCurve, poPIs[j*nPrecompPoints + absofKIs[j*nRecodedDigits + i]/2], poTmp );
507
508
if (sigofKIs[j*nRecodedDigits + i] == 0xffffffff)
509
{
510
SymCryptEcpointNegate( pCurve, poTmp, 0xffffffff, pbScratch, cbScratch );
511
}
512
513
SymCryptEcpointAdd( pCurve, poQ, poTmp, poQ, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratch );
514
}
515
}
516
}
517
}
518
519
// Multiply by the cofactor (if needed) by continuing the doubling
520
if ((pCurve->coFactorPower!=0) && ((flags & SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL) != 0))
521
{
522
for (j=0; j<pCurve->coFactorPower; j++)
523
{
524
SymCryptEcpointDouble( pCurve, poQ, poQ, 0, pbScratch, cbScratch );
525
}
526
}
527
528
// If the resultant point is zero, ensure it will be set to the canonical zero point
529
if ( SymCryptEcpointIsZero( pCurve, poQ, pbScratch, cbScratch ) )
530
{
531
// Set poQ to zero point
532
SymCryptEcpointSetZero( pCurve, poQ, pbScratch, cbScratch );
533
}
534
535
// Copy the result to the destination (normalized flag == FALSE)
536
SymCryptEcpointCopy( pCurve, poQ, poDst );
537
538
scError = SYMCRYPT_NO_ERROR;
539
540
exit:
541
return scError;
542
}
543
544
VOID
545
SYMCRYPT_CALL
546
SymCryptEcpointGenericSetRandom(
547
_In_ PCSYMCRYPT_ECURVE pCurve,
548
_Out_ PSYMCRYPT_INT piScalar,
549
_Out_ PSYMCRYPT_ECPOINT poDst,
550
_Out_writes_bytes_( cbScratch )
551
PBYTE pbScratch,
552
SIZE_T cbScratch )
553
{
554
PSYMCRYPT_MODELEMENT peScalar = NULL;
555
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
556
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS(pCurve, 1) );
557
SYMCRYPT_ASSERT( cbScratch >= pCurve->cbModElement );
558
559
peScalar = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->GOrd );
560
SYMCRYPT_ASSERT( peScalar != NULL );
561
562
// Setting a random mod element in the [1, SubgroupOrder-1] set
563
SymCryptModSetRandom( pCurve->GOrd, peScalar, (SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE|SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE), pbScratch + pCurve->cbModElement, cbScratch - pCurve->cbModElement );
564
565
// Setting the integer
566
SymCryptModElementToInt( pCurve->GOrd, peScalar, piScalar, pbScratch + pCurve->cbModElement, cbScratch - pCurve->cbModElement );
567
568
// Do the multiplication (pass over the entire scratch space as it is not needed anymore)
569
// !! Explicitly not checking the error return here as the only error is from specifying invalid flags !!
570
SymCryptEcpointScalarMul( pCurve, piScalar, NULL, 0, poDst, pbScratch, cbScratch );
571
}
572
573