Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/ec_twisted_edwards.c
Line
Count
Source (jump to first uncovered line)
1
//
2
// ec_twisted_edwards.c   Twisted Edwards Curve Implementation
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
7
#include "precomp.h"
8
9
VOID
10
SYMCRYPT_CALL
11
SymCryptTwistedEdwardsFillScratchSpaces( _In_ PSYMCRYPT_ECURVE pCurve )
12
94
{
13
94
    UINT32 nDigits = SymCryptDigitsFromBits( pCurve->FModBitsize );
14
94
    UINT32 cbModElement = pCurve->cbModElement;
15
94
    UINT32 nDigitsFieldLength = pCurve->FModDigits;
16
17
    //
18
    // All the scratch space computations are upper bounded by the SizeofXXX bound (2^19) and
19
    // the SCRATCH_BYTES_FOR_XXX bound (2^24) (see symcrypt_internal.h).
20
    //
21
    // One caveat is SymCryptSizeofEcpointFromCurve and SymCryptSizeofEcpointEx which calculate
22
    // the size of EcPoint with 4 coordinates (each one a modelement of max size 2^17). Thus upper
23
    // bounded by 2^20.
24
    //
25
    // Another is the precomp points computation where the nPrecompPoints are up to
26
    // 2^SYMCRYPT_ECURVE_SW_DEF_WINDOW = 2^6 and the nRecodedDigits are equal to the
27
    // GOrd bitsize < 2^20.
28
    //
29
    // Thus cbScratchScalarMulti is upper bounded by 2^6*2^20 + 2*2^20*2^4 ~ 2^26.
30
    //
31
32
94
    pCurve->cbScratchCommon = 8 * cbModElement + SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits );
33
34
94
    pCurve->cbScratchScalar =
35
94
            (pCurve->cbModElement) +
36
94
            2 * SymCryptSizeofEcpointFromCurve( pCurve ) +
37
94
            2 * SymCryptSizeofIntFromDigits( pCurve->GOrdDigits ) +
38
94
            SYMCRYPT_MAX( pCurve->cbScratchCommon, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits ));
39
40
94
    pCurve->cbScratchScalarMulti =
41
94
            pCurve->info.sw.nPrecompPoints * SymCryptSizeofEcpointFromCurve( pCurve ) +
42
94
            ((2*pCurve->info.sw.nRecodedDigits * sizeof(UINT32) + SYMCRYPT_ASYM_ALIGN_VALUE - 1 )/SYMCRYPT_ASYM_ALIGN_VALUE) * SYMCRYPT_ASYM_ALIGN_VALUE;
43
44
94
    pCurve->cbScratchGetSetValue =
45
94
        SymCryptSizeofEcpointEx(cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH) +
46
94
        2 * cbModElement +
47
94
        SYMCRYPT_MAX(SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(nDigitsFieldLength),
48
94
        SYMCRYPT_SCRATCH_BYTES_FOR_MODINV(nDigitsFieldLength));
49
50
94
    pCurve->cbScratchGetSetValue = SYMCRYPT_MAX( pCurve->cbScratchGetSetValue, SymCryptSizeofIntFromDigits( nDigits ) );
51
52
94
    pCurve->cbScratchEckey =
53
94
        SYMCRYPT_MAX( pCurve->cbModElement + SymCryptSizeofIntFromDigits(SymCryptEcurveDigitsofScalarMultiplier(pCurve)),
54
94
                SymCryptSizeofEcpointFromCurve( pCurve ) ) +
55
94
        SYMCRYPT_MAX( pCurve->cbScratchScalar + pCurve->cbScratchScalarMulti, pCurve->cbScratchGetSetValue );
56
94
}
57
58
VOID
59
SYMCRYPT_CALL
60
SymCryptTwistedEdwardsSetDistinguished(
61
    _In_    PCSYMCRYPT_ECURVE   pCurve,
62
    _Out_   PSYMCRYPT_ECPOINT   poDst,
63
    _Out_writes_bytes_( cbScratch )
64
            PBYTE               pbScratch,
65
            SIZE_T              cbScratch )
66
0
{
67
0
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
68
0
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
69
70
0
    UNREFERENCED_PARAMETER( pbScratch );
71
0
    UNREFERENCED_PARAMETER( cbScratch );
72
73
0
    SymCryptEcpointCopy( pCurve, pCurve->G, poDst );
74
0
}
75
76
UINT32
77
SYMCRYPT_CALL
78
SymCryptTwistedEdwardsIsZero(
79
    _In_    PCSYMCRYPT_ECURVE   pCurve,
80
    _In_    PCSYMCRYPT_ECPOINT  poSrc,
81
    _Out_writes_bytes_( cbScratch )
82
            PBYTE               pbScratch,
83
            SIZE_T              cbScratch)
84
505
{
85
505
    PSYMCRYPT_MODULUS     pmMod = pCurve->FMod;
86
505
    UINT32 dResX = 0, dResY = 0;
87
88
505
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
89
505
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) );
90
91
505
    UNREFERENCED_PARAMETER( pbScratch );
92
505
    UNREFERENCED_PARAMETER( cbScratch );
93
94
505
    PSYMCRYPT_MODELEMENT peSrcX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
95
505
    PSYMCRYPT_MODELEMENT peSrcY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
96
505
    PSYMCRYPT_MODELEMENT peSrcZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
97
98
505
    dResX = SymCryptModElementIsZero( pmMod, peSrcX );
99
505
    dResY = SymCryptModElementIsEqual( pmMod, peSrcY, peSrcZ );
100
101
505
    return ( dResX & dResY );
102
505
}
103
104
//
105
// Verify that
106
//   a * x^2 + y^2 = 1 + d * x^2 * y^2
107
//   x = X/Z, y = Y/Z,
108
// To avoid mod inv calculation which is expensive,
109
// we verify Z^2(aX^2 + Y^2) = Z^4 + d * X^2 * Y^2
110
//
111
UINT32
112
SYMCRYPT_CALL
113
SymCryptTwistedEdwardsOnCurve(
114
    _In_    PCSYMCRYPT_ECURVE   pCurve,
115
    _In_    PCSYMCRYPT_ECPOINT  poSrc,
116
    _Out_writes_bytes_( cbScratch )
117
            PBYTE               pbScratch,
118
            SIZE_T              cbScratch)
119
78
{
120
78
    PSYMCRYPT_MODELEMENT  peTemp[4];
121
78
    PSYMCRYPT_MODULUS     pmMod = pCurve->FMod;
122
78
    SIZE_T nBytes;
123
124
78
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
125
78
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) );
126
78
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
127
128
78
    nBytes = SymCryptSizeofModElementFromModulus( pmMod );
129
130
78
    SYMCRYPT_ASSERT( cbScratch >= 4*nBytes );
131
132
390
    for (UINT32 i = 0; i < 4; ++i)
133
312
    {
134
312
       peTemp[i] = SymCryptModElementCreate( pbScratch, nBytes, pmMod );
135
312
       pbScratch += nBytes;
136
312
       cbScratch -= nBytes;
137
312
    }
138
139
78
    PSYMCRYPT_MODELEMENT peSrcX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
140
78
    PSYMCRYPT_MODELEMENT peSrcY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
141
78
    PSYMCRYPT_MODELEMENT peSrcZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
142
143
    // peTemp[0] = X^2
144
78
    SymCryptModSquare( pmMod, peSrcX, peTemp[0], pbScratch, cbScratch);
145
146
    // peTemp[1] = Y^2
147
78
    SymCryptModSquare( pmMod, peSrcY, peTemp[1], pbScratch, cbScratch);
148
149
    // peTemp[2] = Z^2
150
78
    SymCryptModSquare( pmMod, peSrcZ, peTemp[2], pbScratch, cbScratch);
151
152
    // peTemp[3] = a * X^2
153
78
    SymCryptModMul( pmMod, pCurve->A, peTemp[0], peTemp[3], pbScratch, cbScratch );
154
155
    // peTemp[3] = a * X^2 + Y^2
156
78
    SymCryptModAdd( pmMod, peTemp[3], peTemp[1], peTemp[3], pbScratch, cbScratch );
157
158
    // peTemp[3] = Z^2 (a * X^2 + Y^2)
159
78
    SymCryptModMul( pmMod, peTemp[3], peTemp[2], peTemp[3], pbScratch, cbScratch );
160
161
    // peTemp[1] = X^2 * Y^2
162
78
    SymCryptModMul( pmMod, peTemp[0], peTemp[1], peTemp[1], pbScratch, cbScratch );
163
164
    // peTemp[1] = d * X^2 *Y^2
165
78
    SymCryptModMul( pmMod, pCurve->B, peTemp[1], peTemp[1], pbScratch, cbScratch );
166
167
    // peTemp[2] = Z^4
168
78
    SymCryptModMul( pmMod, peTemp[2], peTemp[2], peTemp[2], pbScratch, cbScratch );
169
170
    // peTemp[1] = Z^4 + d * X^2 * Y^2
171
78
    SymCryptModAdd( pmMod, peTemp[2], peTemp[1], peTemp[1], pbScratch, cbScratch );
172
173
78
    return SymCryptModElementIsEqual( pmMod, peTemp[1], peTemp[3] );
174
78
}
175
176
//
177
//  Point doubling: dbl-2008-hwcd, 5Mul + 4Square + 2Add + 5Sub
178
//
179
//  poDst (X, Y, Z, T) = 2 * poSrc(X, Y, Z, T)
180
//  1.  A = X1 ^ 2
181
//  2.  B = Y1 ^ 2
182
//  3.  C = 2 * Z1 ^ 2
183
//  4.  D = a * A
184
//  5.  E = (X1 + Y1) ^ 2 - A - B
185
//  6.  G = D + B
186
//  7.  F = G - C
187
//  8.  H = D - B
188
//  9.  X3 = E * F
189
//  10. Y3 = G * H
190
//  11. T3 = E * H
191
//  12. Z3 = F * G
192
//
193
VOID
194
SYMCRYPT_CALL
195
SymCryptTwistedEdwardsDouble(
196
    _In_    PCSYMCRYPT_ECURVE   pCurve,
197
    _In_    PCSYMCRYPT_ECPOINT  poSrc,
198
    _Out_   PSYMCRYPT_ECPOINT   poDst,
199
            UINT32              flags,
200
    _Out_writes_bytes_( cbScratch )
201
            PBYTE               pbScratch,
202
            SIZE_T              cbScratch)
203
63.8k
{
204
63.8k
    PSYMCRYPT_MODELEMENT  peTemp[8];
205
63.8k
    PSYMCRYPT_MODULUS     pmMod = pCurve->FMod;
206
63.8k
    SIZE_T nBytes;
207
208
63.8k
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
209
63.8k
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
210
63.8k
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
211
212
63.8k
    UNREFERENCED_PARAMETER( flags );
213
214
63.8k
    nBytes = SymCryptSizeofModElementFromModulus( pmMod );
215
216
63.8k
    SYMCRYPT_ASSERT( cbScratch >= 8*nBytes );
217
218
574k
    for (UINT32 i = 0; i < 8; ++i)
219
510k
    {
220
510k
       peTemp[i] = SymCryptModElementCreate( pbScratch, nBytes, pmMod );
221
510k
       pbScratch += nBytes;
222
510k
       cbScratch -= nBytes;
223
510k
    }
224
225
63.8k
    PSYMCRYPT_MODELEMENT peSrcX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
226
63.8k
    PSYMCRYPT_MODELEMENT peSrcY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
227
63.8k
    PSYMCRYPT_MODELEMENT peSrcZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
228
229
63.8k
    PSYMCRYPT_MODELEMENT peDstX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
230
63.8k
    PSYMCRYPT_MODELEMENT peDstY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
231
63.8k
    PSYMCRYPT_MODELEMENT peDstZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst );
232
63.8k
    PSYMCRYPT_MODELEMENT peDstT = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst );
233
234
63.8k
    PSYMCRYPT_MODELEMENT peA = peTemp[0];
235
63.8k
    PSYMCRYPT_MODELEMENT peB = peTemp[1];
236
63.8k
    PSYMCRYPT_MODELEMENT peC = peTemp[2];
237
63.8k
    PSYMCRYPT_MODELEMENT peD = peTemp[3];
238
63.8k
    PSYMCRYPT_MODELEMENT peE = peTemp[4];
239
63.8k
    PSYMCRYPT_MODELEMENT peF = peTemp[5];
240
63.8k
    PSYMCRYPT_MODELEMENT peG = peTemp[6];
241
63.8k
    PSYMCRYPT_MODELEMENT peH = peTemp[7];
242
243
244
    // A = X1^2
245
63.8k
    SymCryptModSquare( pmMod, peSrcX, peA, pbScratch, cbScratch );
246
247
    // B = Y1^2
248
63.8k
    SymCryptModSquare( pmMod, peSrcY, peB, pbScratch, cbScratch );
249
250
    // C1 = Z1^2
251
63.8k
    SymCryptModSquare( pmMod, peSrcZ, peC, pbScratch, cbScratch );
252
253
    // C = C1 + C1 = Z1^2 + Z1^2 = 2 * Z1^2
254
63.8k
    SymCryptModAdd( pmMod, peC, peC, peC, pbScratch, cbScratch );
255
256
    // D = a * A
257
63.8k
    SymCryptModMul( pmMod, pCurve->A, peA, peD, pbScratch, cbScratch );
258
259
    // E1 = X1 + Y1
260
63.8k
    SymCryptModAdd( pmMod, peSrcX, peSrcY, peE, pbScratch, cbScratch );
261
262
    // E2 = E1^2 = (X1 + Y1)^2
263
63.8k
    SymCryptModSquare( pmMod, peE, peE, pbScratch, cbScratch );
264
265
    // E3 = E2 - A = (X1 + Y1)^2 - A
266
63.8k
    SymCryptModSub( pmMod, peE, peA, peE, pbScratch, cbScratch );
267
268
    // E = E3 - B = (X1 + Y1)^2 - A - B
269
63.8k
    SymCryptModSub( pmMod, peE, peB, peE, pbScratch, cbScratch );
270
271
    // G = D + B
272
63.8k
    SymCryptModAdd( pmMod, peD, peB, peG, pbScratch, cbScratch );
273
274
    // F = G - C
275
63.8k
    SymCryptModSub( pmMod, peG, peC, peF, pbScratch, cbScratch );
276
277
    // H = D - B
278
63.8k
    SymCryptModSub( pmMod, peD, peB, peH, pbScratch, cbScratch );
279
280
    // X3 = E * F
281
63.8k
    SymCryptModMul( pmMod, peE, peF, peDstX, pbScratch, cbScratch );
282
283
    // Y3 = G * H
284
63.8k
    SymCryptModMul( pmMod, peG, peH, peDstY, pbScratch, cbScratch );
285
286
    // T3 = E * H
287
63.8k
    SymCryptModMul( pmMod, peE, peH, peDstT, pbScratch, cbScratch );
288
289
    // Z3 = F * G
290
63.8k
    SymCryptModMul( pmMod, peF, peG, peDstZ, pbScratch, cbScratch );
291
63.8k
}
292
293
294
//
295
//  Point addition: add-2008-hwcd  11Mul + 3add + 4sub
296
//
297
//  poDst(X, Y, Z, T) = poSrc(X, Y, Z, T) + poSrc2(X, Y, Z, T)
298
//  1.  A = X1 * X2
299
//  2.  B = Y1 * Y2
300
//  3.  C = d * T1 * T2
301
//  4.  D = Z1 * Z2
302
//  5.  E = (X1 + Y1) * (X2 + Y2) - A - B
303
//  6.  F = D - C
304
//  7.  G = D + C
305
//  8.  H = B - a * A
306
//  9.  X3 = E * F
307
//  10. Y3 = G * H
308
//  11. T3 = E * H
309
//  12. Z3 = F * G
310
//
311
VOID
312
SYMCRYPT_CALL
313
SymCryptTwistedEdwardsAdd(
314
    _In_    PCSYMCRYPT_ECURVE   pCurve,
315
    _In_    PCSYMCRYPT_ECPOINT  poSrc1,
316
    _In_    PCSYMCRYPT_ECPOINT  poSrc2,
317
    _Out_   PSYMCRYPT_ECPOINT   poDst,
318
            UINT32              flags,
319
    _Out_writes_bytes_( cbScratch )
320
            PBYTE               pbScratch,
321
            SIZE_T              cbScratch )
322
16.0k
{
323
16.0k
    PSYMCRYPT_MODELEMENT  peTemp[8];
324
16.0k
    PSYMCRYPT_MODULUS     pmMod = pCurve->FMod;
325
16.0k
    SIZE_T nBytes;
326
327
16.0k
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
328
16.0k
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
329
16.0k
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
330
331
16.0k
    UNREFERENCED_PARAMETER( flags );
332
333
16.0k
    nBytes = SymCryptSizeofModElementFromModulus( pmMod );
334
335
16.0k
    SYMCRYPT_ASSERT( cbScratch >= 8*nBytes );
336
337
144k
    for (UINT32 i = 0; i < 8; ++i)
338
128k
    {
339
128k
       peTemp[i] = SymCryptModElementCreate( pbScratch, nBytes, pmMod );
340
128k
       pbScratch += nBytes;
341
128k
       cbScratch -= nBytes;
342
128k
    }
343
344
16.0k
    PSYMCRYPT_MODELEMENT peSrc1X = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc1 );
345
16.0k
    PSYMCRYPT_MODELEMENT peSrc1Y = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc1 );
346
16.0k
    PSYMCRYPT_MODELEMENT peSrc1Z = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc1 );
347
16.0k
    PSYMCRYPT_MODELEMENT peSrc1T = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poSrc1 );
348
349
16.0k
    PSYMCRYPT_MODELEMENT peSrc2X = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc2 );
350
16.0k
    PSYMCRYPT_MODELEMENT peSrc2Y = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc2 );
351
16.0k
    PSYMCRYPT_MODELEMENT peSrc2Z = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc2 );
352
16.0k
    PSYMCRYPT_MODELEMENT peSrc2T = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poSrc2 );
353
354
16.0k
    PSYMCRYPT_MODELEMENT peDstX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
355
16.0k
    PSYMCRYPT_MODELEMENT peDstY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
356
16.0k
    PSYMCRYPT_MODELEMENT peDstZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst );
357
16.0k
    PSYMCRYPT_MODELEMENT peDstT = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst );
358
359
16.0k
    PSYMCRYPT_MODELEMENT peA = peTemp[0];
360
16.0k
    PSYMCRYPT_MODELEMENT peB = peTemp[1];
361
16.0k
    PSYMCRYPT_MODELEMENT peC = peTemp[2];
362
16.0k
    PSYMCRYPT_MODELEMENT peD = peTemp[3];
363
16.0k
    PSYMCRYPT_MODELEMENT peE = peTemp[4];
364
16.0k
    PSYMCRYPT_MODELEMENT peF = peTemp[5];
365
16.0k
    PSYMCRYPT_MODELEMENT peG = peTemp[6];
366
16.0k
    PSYMCRYPT_MODELEMENT peH = peTemp[7];
367
368
    // A = X1 * X2
369
16.0k
    SymCryptModMul( pmMod, peSrc1X, peSrc2X, peA, pbScratch, cbScratch );
370
371
    // B = Y1 * Y2
372
16.0k
    SymCryptModMul( pmMod, peSrc1Y, peSrc2Y, peB, pbScratch, cbScratch );
373
374
    // C1 = T1 * T2
375
16.0k
    SymCryptModMul( pmMod, peSrc1T, peSrc2T, peC, pbScratch, cbScratch );
376
377
    // C = d * C1 = d * T1 * T2
378
16.0k
    SymCryptModMul( pmMod, pCurve->B, peC, peC, pbScratch, cbScratch );
379
380
    // D = Z1 * Z2
381
16.0k
    SymCryptModMul( pmMod, peSrc1Z, peSrc2Z, peD, pbScratch, cbScratch );
382
383
    // E1 = X1 + Y1
384
16.0k
    SymCryptModAdd( pmMod, peSrc1X, peSrc1Y, peE, pbScratch, cbScratch );
385
386
    // E2 = X2 + Y2
387
16.0k
    SymCryptModAdd( pmMod, peSrc2X, peSrc2Y, peF, pbScratch, cbScratch );
388
389
    // E = E * F
390
16.0k
    SymCryptModMul( pmMod, peE, peF, peE, pbScratch, cbScratch );
391
392
    // E = E - A
393
16.0k
    SymCryptModSub( pmMod, peE, peA, peE, pbScratch, cbScratch );
394
395
    // E = E - B
396
16.0k
    SymCryptModSub( pmMod, peE, peB, peE, pbScratch, cbScratch );
397
398
    // F = D - C
399
16.0k
    SymCryptModSub( pmMod, peD, peC, peF, pbScratch, cbScratch );
400
401
    // G = D + C
402
16.0k
    SymCryptModAdd( pmMod, peD, peC, peG, pbScratch, cbScratch );
403
404
    // H = a * A
405
16.0k
    SymCryptModMul( pmMod, pCurve->A, peA, peH, pbScratch, cbScratch );
406
407
    // H = B - a * A
408
16.0k
    SymCryptModSub( pmMod, peB, peH, peH, pbScratch, cbScratch );
409
410
    // X3 = E * F
411
16.0k
    SymCryptModMul( pmMod, peE, peF, peDstX, pbScratch, cbScratch );
412
413
    // Y3 = G * H
414
16.0k
    SymCryptModMul( pmMod, peG, peH, peDstY, pbScratch, cbScratch );
415
416
    // T3 = E * H
417
16.0k
    SymCryptModMul( pmMod, peE, peH, peDstT, pbScratch, cbScratch );
418
419
    // Y3 = F * G
420
16.0k
    SymCryptModMul( pmMod, peF, peG, peDstZ, pbScratch, cbScratch );
421
16.0k
}
422
423
VOID
424
SYMCRYPT_CALL
425
SymCryptTwistedEdwardsAddDiffNonZero(
426
    _In_    PCSYMCRYPT_ECURVE   pCurve,
427
    _In_    PCSYMCRYPT_ECPOINT  poSrc1,
428
    _In_    PCSYMCRYPT_ECPOINT  poSrc2,
429
    _Out_   PSYMCRYPT_ECPOINT   poDst,
430
    _Out_writes_bytes_(cbScratch)
431
            PBYTE               pbScratch,
432
            SIZE_T              cbScratch )
433
13.5k
{
434
13.5k
    SymCryptTwistedEdwardsAdd( pCurve, poSrc1, poSrc2, poDst, 0, pbScratch, cbScratch );
435
13.5k
}
436
437
//
438
//  Verify poSrc1(X1, Y1, Z1, T1) = poSrc2(X2, Y2, Z2, T2)
439
//  To avoid ModInv for 1/Z, we do
440
//     X1 * Z2 = X2 * Z1, and
441
//     Y1 * Z2 = Y2 * Z1
442
//
443
//  This function also do poSrc1 = -1 * poSrc check as flags indicates
444
//
445
UINT32
446
SYMCRYPT_CALL
447
SymCryptTwistedEdwardsIsEqual(
448
    _In_    PCSYMCRYPT_ECURVE   pCurve,
449
    _In_    PCSYMCRYPT_ECPOINT  poSrc1,
450
    _In_    PCSYMCRYPT_ECPOINT  poSrc2,
451
            UINT32              flags,
452
    _Out_writes_bytes_(cbScratch)
453
            PBYTE               pbScratch,
454
            SIZE_T              cbScratch)
455
0
{
456
0
    PSYMCRYPT_MODELEMENT  peTemp[2];
457
0
    PSYMCRYPT_MODELEMENT  peSrc1X, peSrc1Y, peSrc1Z;
458
0
    PSYMCRYPT_MODELEMENT  peSrc2X, peSrc2Y, peSrc2Z;
459
0
    PSYMCRYPT_MODULUS     pmMod = pCurve->FMod;
460
0
    SIZE_T nBytes;
461
0
    UINT32  dResX = 0;
462
0
    UINT32  dResXN = 0;
463
0
    UINT32  dResY = 0;
464
465
0
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
466
0
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) );
467
0
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
468
469
0
    nBytes = SymCryptSizeofModElementFromModulus( pmMod );
470
471
0
    SYMCRYPT_ASSERT( cbScratch >= 2*nBytes );
472
473
0
    for (UINT32 i = 0; i < 2; ++i)
474
0
    {
475
0
        peTemp[i] = SymCryptModElementCreate( pbScratch, nBytes, pmMod );
476
0
        pbScratch += nBytes;
477
0
        cbScratch -= nBytes;
478
0
    }
479
480
0
    peSrc1X = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc1 );
481
0
    peSrc1Y = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc1 );
482
0
    peSrc1Z = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc1 );
483
484
0
    peSrc2X = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc2 );
485
0
    peSrc2Y = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc2 );
486
0
    peSrc2Z = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc2 );
487
488
    // Setting the default flag if flags == 0
489
0
    flags |= (SYMCRYPT_MASK32_ZERO(flags) & SYMCRYPT_FLAG_ECPOINT_EQUAL);
490
491
    // peTemp[0] = X1 * Z2
492
0
    SymCryptModMul( pmMod, peSrc1X, peSrc2Z, peTemp[0], pbScratch, cbScratch );
493
494
    // peTemp[1] = X2 * Z1
495
0
    SymCryptModMul( pmMod, peSrc2X, peSrc1Z, peTemp[1], pbScratch, cbScratch );
496
497
0
    dResX = SymCryptModElementIsEqual( pmMod, peTemp[0], peTemp[1] );
498
499
    // Neg peTemp[1]
500
0
    SymCryptModNeg(pmMod, peTemp[1], peTemp[1], pbScratch, cbScratch);
501
0
    dResXN = SymCryptModElementIsEqual(pmMod, peTemp[0], peTemp[1]);
502
503
    // peTemp[0] = Y1 * Z2
504
0
    SymCryptModMul( pmMod, peSrc1Y, peSrc2Z, peTemp[0], pbScratch, cbScratch );
505
506
    // peTemp[1] = Y2 * Z1
507
0
    SymCryptModMul( pmMod, peSrc2Y, peSrc1Z, peTemp[1], pbScratch, cbScratch );
508
509
0
    dResY = SymCryptModElementIsEqual( pmMod, peTemp[0], peTemp[1] );
510
511
0
    return (SYMCRYPT_MASK32_NONZERO( flags & SYMCRYPT_FLAG_ECPOINT_EQUAL ) & dResX & dResY ) |
512
0
           (SYMCRYPT_MASK32_NONZERO( flags & SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL ) & dResXN & dResY );
513
0
}
514
515
VOID
516
SYMCRYPT_CALL
517
SymCryptTwistedEdwardsSetZero(
518
    _In_    PCSYMCRYPT_ECURVE   pCurve,
519
    _Out_   PSYMCRYPT_ECPOINT   poDst,
520
    _Out_writes_bytes_(cbScratch)
521
            PBYTE               pbScratch,
522
            SIZE_T              cbScratch)
523
157
{
524
157
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
525
157
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
526
157
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
527
528
157
    PSYMCRYPT_MODULUS  pmMod = pCurve->FMod;
529
530
157
    PSYMCRYPT_MODELEMENT peDstX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
531
157
    PSYMCRYPT_MODELEMENT peDstY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
532
157
    PSYMCRYPT_MODELEMENT peDstZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst );
533
157
    PSYMCRYPT_MODELEMENT peDstT = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst );
534
535
157
    SymCryptModElementSetValueUint32( 0, pmMod, peDstX, pbScratch, cbScratch );
536
157
    SymCryptModElementSetValueUint32( 1, pmMod, peDstY, pbScratch, cbScratch );
537
157
    SymCryptModElementSetValueUint32( 1, pmMod, peDstZ, pbScratch, cbScratch );
538
157
    SymCryptModElementSetValueUint32( 0, pmMod, peDstT, pbScratch, cbScratch );
539
157
}
540
541
VOID
542
SYMCRYPT_CALL
543
SymCryptTwistedEdwardsNegate(
544
    _In_    PCSYMCRYPT_ECURVE   pCurve,
545
    _Inout_ PSYMCRYPT_ECPOINT   poSrc,
546
            UINT32              mask,
547
    _Out_writes_bytes_( cbScratch )
548
            PBYTE               pbScratch,
549
            SIZE_T              cbScratch )
550
12.2k
{
551
12.2k
    PCSYMCRYPT_MODULUS FMod = pCurve->FMod;
552
12.2k
    PSYMCRYPT_MODELEMENT peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0,pCurve, poSrc);
553
12.2k
    PSYMCRYPT_MODELEMENT peT = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3,pCurve, poSrc);
554
555
12.2k
    PSYMCRYPT_MODELEMENT peTmp = NULL;
556
557
12.2k
    SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_TWISTED_EDWARDS_TYPE(pCurve) );
558
12.2k
    SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) );
559
12.2k
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + pCurve->cbModElement );
560
561
12.2k
    peTmp = SymCryptModElementCreate(
562
12.2k
                pbScratch,
563
12.2k
                pCurve->cbModElement,
564
12.2k
                FMod );
565
12.2k
    SYMCRYPT_ASSERT( peTmp != NULL);
566
567
12.2k
    pbScratch += pCurve->cbModElement;
568
12.2k
    cbScratch -= pCurve->cbModElement;
569
570
12.2k
    SymCryptModNeg( FMod, peX, peTmp, pbScratch, cbScratch );
571
12.2k
    SymCryptModElementMaskedCopy( FMod, peTmp, peX, mask );
572
573
12.2k
    SymCryptModNeg( FMod, peT, peTmp, pbScratch, cbScratch );
574
12.2k
    SymCryptModElementMaskedCopy( FMod, peTmp, peT, mask );
575
12.2k
}