/src/SymCrypt/lib/ec_short_weierstrass.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // ec_short_weierstrass.c ECPOINT functions for short Weierstrass curves. |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | // |
7 | | |
8 | | #include "precomp.h" |
9 | | |
10 | | // |
11 | | // Scratch space requirements for each ECPOINT function. |
12 | | // |
13 | | // A function's requirements in scratch space consist of requirements for its own arithmetic |
14 | | // operations and temporaries ("self" scratch space) and scratch space requirements for other |
15 | | // ECPOINT functions it might call ("callee" scratch space). |
16 | | // |
17 | | // If the outer function does not need the temporaries after calling the inner ECPOINT |
18 | | // function, then the total scratch space can be the maximum of both. Otherwise the scratch |
19 | | // space of the outer function should be the concatenation of the "self" scratch space and |
20 | | // the "callee" scratch space. |
21 | | // |
22 | | // The following table shows the scratch space requirements of each function with appropriate |
23 | | // abbreviations. The calling sequence implies a directed graph that starting from the "leaves" |
24 | | // (functions that do no call others) allows to calculate the total scratch space requirements. |
25 | | // |
26 | | // #N Function Calls Function Self Temporaries Self Scratch |
27 | | // 1 SetZero - 0 COM_MOD(FMod) |
28 | | // 2 SetDistinguishedPoint - 0 0 |
29 | | // 3 IsEqual - 4 ModEl COM_MOD(FMod) |
30 | | // 4 IsZero - 1 ModEl COM_MOD(FMod) |
31 | | // 5 OnCurve - 2 ModEl COM_MOD(FMod) |
32 | | // 6 Double 1,4,9 2 Ecp 0 |
33 | | // 7 Add 1,3,4,8,9 2 Ecp 0 |
34 | | // 8 AddDiffNonZero - 8 ModEl COM_MOD(FMod) |
35 | | // 9 Double - 6 ModEl COM_MOD(FMod) |
36 | | // |
37 | | // 10 SetRandom 11 0 COM_MOD(GOrd) |
38 | | // 11 ScalarMul 4,5,7 1ModEl + (n+2)Ecp + 2Int COM_MOD(GOrd) |
39 | | // |
40 | | // Since only 4 functions call others and to keep things simple, we will have 2 |
41 | | // types of scratch space: "ECURVE_COMMON" and "ECURVE_SCALAR" |
42 | | // |
43 | | // ---- All functions except 10 and 11 will use the "ECURVE_COMMON" scratch space. The size of it |
44 | | // depends only on parameters of the curve. Schematically it will be: |
45 | | // |----------COMMON------------------------------------------------------------------| |
46 | | // |------8 ModEl + 2 Ecpoint----||------COM_MOD(FMod)--------------------------------| |
47 | | // |
48 | | // ---- The SetRandom and ScalarMul have requirements that depend on temporaries for the pre-computation. |
49 | | // Also they depend on the "self" temporaries after calling the inner functions. |
50 | | // Therefore, these will require the "ECURVE_SCALAR" scratch space which |
51 | | // consists of two parts: The self space for the above two functions and the |
52 | | // common scratch space. These parts SHOULD NOT overlap. Schematically: |
53 | | // |
54 | | // |--------------SCALAR---------------------------------------------------| |
55 | | // |----1ModEl + (n+2)Ecp + 2Int--------||---max(COMMON, COM_MOD(GOrd)----| |
56 | | |
57 | | // The scratch space sizes are all calculated by the following function. |
58 | | // *** Notice that almost all the curve parameters (exception is the distinguished point) |
59 | | // must have been initialized before calling this function. |
60 | | VOID |
61 | | SYMCRYPT_CALL |
62 | | SymCryptShortWeierstrassFillScratchSpaces( _In_ PSYMCRYPT_ECURVE pCurve ) |
63 | 852 | { |
64 | 852 | UINT32 nDigits = SymCryptDigitsFromBits( pCurve->FModBitsize ); |
65 | | |
66 | | // |
67 | | // All the scratch space computations are upper bounded by the SizeofXXX bound (2^19) and |
68 | | // the SCRATCH_BYTES_FOR_XXX bound (2^24) (see symcrypt_internal.h). |
69 | | // |
70 | | // One caveat is SymCryptSizeofEcpointFromCurve and SymCryptSizeofEcpointEx which calculate |
71 | | // the size of EcPoint with 4 coordinates (each one a modelement of max size 2^17). Thus upper |
72 | | // bounded by 2^20. |
73 | | // |
74 | | // Another is the precomp points computation where the nPrecompPoints are up to |
75 | | // 2^SYMCRYPT_ECURVE_SW_DEF_WINDOW = 2^6 and the nRecodedDigits are equal to the |
76 | | // GOrd bitsize < 2^20. |
77 | | // |
78 | | // Thus cbScratchScalarMulti is upper bounded by 2^6*2^20 + 2*2^20*2^4 ~ 2^26. |
79 | | // |
80 | | |
81 | | // Common |
82 | 852 | pCurve->cbScratchCommon = |
83 | 852 | 8 * pCurve->cbModElement + |
84 | 852 | 2 * SymCryptSizeofEcpointFromCurve( pCurve ) + |
85 | 852 | SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ); |
86 | | |
87 | | // Scalar (Overhead) |
88 | 852 | pCurve->cbScratchScalar = |
89 | 852 | pCurve->cbModElement + |
90 | 852 | 2 * SymCryptSizeofEcpointFromCurve( pCurve ) + |
91 | 852 | 2 * SymCryptSizeofIntFromDigits( pCurve->GOrdDigits ) + |
92 | 852 | SYMCRYPT_MAX( pCurve->cbScratchCommon, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits )); |
93 | | |
94 | | // Scalar dependent on precomp points (be careful to align the UINT32 arrays properly) |
95 | 852 | pCurve->cbScratchScalarMulti = |
96 | 852 | pCurve->info.sw.nPrecompPoints * SymCryptSizeofEcpointFromCurve( pCurve ) + |
97 | 852 | ((2*pCurve->info.sw.nRecodedDigits * sizeof(UINT32) + SYMCRYPT_ASYM_ALIGN_VALUE - 1 )/SYMCRYPT_ASYM_ALIGN_VALUE) * SYMCRYPT_ASYM_ALIGN_VALUE; |
98 | | |
99 | | // GetSetValue |
100 | 852 | pCurve->cbScratchGetSetValue = |
101 | 852 | SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ) + |
102 | 852 | 2 * pCurve->cbModElement + |
103 | 852 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ), |
104 | 852 | SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->FModDigits ) ); |
105 | | |
106 | 852 | pCurve->cbScratchGetSetValue = SYMCRYPT_MAX( pCurve->cbScratchGetSetValue, SymCryptSizeofIntFromDigits( nDigits ) ); |
107 | | |
108 | | // Eckey |
109 | 852 | pCurve->cbScratchEckey = |
110 | 852 | SYMCRYPT_MAX( pCurve->cbModElement + SymCryptSizeofIntFromDigits(SymCryptEcurveDigitsofScalarMultiplier(pCurve)), |
111 | 852 | SymCryptSizeofEcpointFromCurve( pCurve ) ) + |
112 | 852 | SYMCRYPT_MAX( pCurve->cbScratchScalar + pCurve->cbScratchScalarMulti, pCurve->cbScratchGetSetValue ); |
113 | 852 | } |
114 | | |
115 | | // |
116 | | // The following function sets the point to (1:1:0) in Jacobian coordinates. |
117 | | // |
118 | | VOID |
119 | | SYMCRYPT_CALL |
120 | | SymCryptShortWeierstrassSetZero( |
121 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
122 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
123 | | _Out_writes_bytes_( cbScratch ) |
124 | | PBYTE pbScratch, |
125 | | SIZE_T cbScratch ) |
126 | 829 | { |
127 | 829 | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
128 | 829 | PSYMCRYPT_MODELEMENT peTmp = NULL; |
129 | | |
130 | 829 | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
131 | 829 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
132 | 829 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) ); |
133 | | |
134 | | // Getting handle to X |
135 | 829 | peTmp = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
136 | | |
137 | | // Setting the right value (always 1) |
138 | 829 | SymCryptModElementSetValueUint32( 1, FMod, peTmp, pbScratch, cbScratch ); |
139 | | |
140 | | // Getting handle to Y |
141 | 829 | peTmp = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
142 | | |
143 | | // Setting the right value (always 1) |
144 | 829 | SymCryptModElementSetValueUint32( 1, FMod, peTmp, pbScratch, cbScratch ); |
145 | | |
146 | | // Getting handle to Z |
147 | 829 | peTmp = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ); |
148 | | |
149 | | // Setting the right value (always 0) |
150 | 829 | SymCryptModElementSetValueUint32( 0, pCurve->FMod, peTmp, pbScratch, cbScratch ); |
151 | 829 | } |
152 | | |
153 | | VOID |
154 | | SYMCRYPT_CALL |
155 | | SymCryptShortWeierstrassSetDistinguished( |
156 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
157 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
158 | | _Out_writes_bytes_( cbScratch ) |
159 | | PBYTE pbScratch, |
160 | | SIZE_T cbScratch ) |
161 | 0 | { |
162 | 0 | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
163 | 0 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
164 | |
|
165 | 0 | UNREFERENCED_PARAMETER( pbScratch ); |
166 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
167 | |
|
168 | 0 | SymCryptEcpointCopy( pCurve, pCurve->G, poDst ); |
169 | 0 | } |
170 | | |
171 | | // |
172 | | // The following function checks if |
173 | | // - X1*Z2^2 = X2*Z1^2 and Y1*Z2^3 = Y2*Z1^3 (Equal case) |
174 | | // - X1*Z2^2 = X2*Z1^2 and Y1*Z2^3 = -Y2*Z1^3 (Negative case) |
175 | | // |
176 | | // Remark: The case where Z1 = Z2 = 0 is covered above (the zero point |
177 | | // is equal to its negative). |
178 | | // |
179 | | UINT32 |
180 | | SYMCRYPT_CALL |
181 | | SymCryptShortWeierstrassIsEqual( |
182 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
183 | | _In_ PCSYMCRYPT_ECPOINT poSrc1, |
184 | | _In_ PCSYMCRYPT_ECPOINT poSrc2, |
185 | | UINT32 flags, |
186 | | _Out_writes_bytes_( cbScratch ) |
187 | | PBYTE pbScratch, |
188 | | SIZE_T cbScratch ) |
189 | 660 | { |
190 | 660 | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
191 | | |
192 | 660 | PSYMCRYPT_MODELEMENT peX1 = NULL; // Pointer to X1 |
193 | 660 | PSYMCRYPT_MODELEMENT peY1 = NULL; // Pointer to Y1 |
194 | 660 | PSYMCRYPT_MODELEMENT peZ1 = NULL; // Pointer to Z1 |
195 | 660 | PSYMCRYPT_MODELEMENT peX2 = NULL; // Pointer to X2 |
196 | 660 | PSYMCRYPT_MODELEMENT peY2 = NULL; // Pointer to Y2 |
197 | 660 | PSYMCRYPT_MODELEMENT peZ2 = NULL; // Pointer to Z2 |
198 | | |
199 | 660 | UINT32 dResX = 0; |
200 | 660 | UINT32 dResY = 0; |
201 | 660 | UINT32 dResYN = 0; |
202 | | |
203 | 660 | PSYMCRYPT_MODELEMENT peT[4] = { 0 }; // Temporaries |
204 | | |
205 | 660 | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
206 | 660 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) ); |
207 | 660 | SYMCRYPT_ASSERT( (flags & ~(SYMCRYPT_FLAG_ECPOINT_EQUAL|SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL)) == 0 ); |
208 | 660 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 4 * pCurve->cbModElement ); |
209 | | |
210 | | // Creating temporaries |
211 | 3.30k | for (UINT32 i=0; i<4; i++) |
212 | 2.64k | { |
213 | 2.64k | peT[i] = SymCryptModElementCreate( |
214 | 2.64k | pbScratch, |
215 | 2.64k | pCurve->cbModElement, |
216 | 2.64k | FMod ); |
217 | | |
218 | 2.64k | SYMCRYPT_ASSERT( peT[i] != NULL); |
219 | | |
220 | 2.64k | pbScratch += pCurve->cbModElement; |
221 | 2.64k | } |
222 | | |
223 | | // Fixing remaining scratch space size |
224 | 660 | cbScratch -= 4 * pCurve->cbModElement; |
225 | | |
226 | | // Getting pointers to x and y of the source point |
227 | 660 | peX1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc1 ); |
228 | 660 | peY1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc1 ); |
229 | 660 | peZ1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc1 ); |
230 | 660 | peX2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc2 ); |
231 | 660 | peY2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc2 ); |
232 | 660 | peZ2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc2 ); |
233 | | |
234 | | // Setting the default flag if flags == 0 |
235 | 660 | flags |= ( SYMCRYPT_MASK32_ZERO( flags ) & SYMCRYPT_FLAG_ECPOINT_EQUAL ); |
236 | | |
237 | | // Calculation |
238 | 660 | SymCryptModSquare( FMod, peZ1, peT[0], pbScratch, cbScratch ); // T0 := Z1 * Z1 = Z1^2 |
239 | 660 | SymCryptModSquare( FMod, peZ2, peT[1], pbScratch, cbScratch ); // T1 := Z2 * Z2 = Z2^2 |
240 | 660 | SymCryptModMul( FMod, peX1, peT[1], peT[2], pbScratch, cbScratch ); // T2 := X1 * T1 = X1*Z2^2 |
241 | 660 | SymCryptModMul( FMod, peX2, peT[0], peT[3], pbScratch, cbScratch ); // T3 := X2 * T0 = X2*Z1^2 |
242 | | |
243 | 660 | dResX = SymCryptModElementIsEqual( FMod, peT[2], peT[3] ); |
244 | | |
245 | 660 | SymCryptModMul( FMod, peZ1, peT[0], peT[0], pbScratch, cbScratch ); // T0 := Z1 * T0 = Z1^3 |
246 | 660 | SymCryptModMul( FMod, peZ2, peT[1], peT[1], pbScratch, cbScratch ); // T1 := Z2 * T1 = Z2^3 |
247 | 660 | SymCryptModMul( FMod, peY1, peT[1], peT[2], pbScratch, cbScratch ); // T2 := Y1 * T1 = Y1*Z2^3 |
248 | 660 | SymCryptModMul( FMod, peY2, peT[0], peT[3], pbScratch, cbScratch ); // T3 := Y2 * T0 = Y2*Z1^3 |
249 | | |
250 | 660 | dResY = SymCryptModElementIsEqual( FMod, peT[2], peT[3] ); |
251 | | |
252 | 660 | SymCryptModNeg( FMod, peT[3], peT[3], pbScratch, cbScratch ); // T3 := -T3 = -Y2*Z1^3 |
253 | | |
254 | 660 | dResYN = SymCryptModElementIsEqual( FMod, peT[2], peT[3] ); |
255 | | |
256 | 660 | return (SYMCRYPT_MASK32_NONZERO(flags & SYMCRYPT_FLAG_ECPOINT_EQUAL) & dResX & dResY) | |
257 | 660 | (SYMCRYPT_MASK32_NONZERO(flags & SYMCRYPT_FLAG_ECPOINT_NEG_EQUAL) & dResX & dResYN); |
258 | 660 | } |
259 | | |
260 | | UINT32 |
261 | | SYMCRYPT_CALL |
262 | | SymCryptShortWeierstrassIsZero( |
263 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
264 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
265 | | _Out_writes_bytes_( cbScratch ) |
266 | | PBYTE pbScratch, |
267 | | SIZE_T cbScratch ) |
268 | 4.05k | { |
269 | 4.05k | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
270 | 4.05k | PSYMCRYPT_MODELEMENT peZ = NULL; // Pointer to Z |
271 | | |
272 | 4.05k | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
273 | 4.05k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) ); |
274 | | |
275 | 4.05k | UNREFERENCED_PARAMETER( pbScratch ); |
276 | 4.05k | UNREFERENCED_PARAMETER( cbScratch ); |
277 | | |
278 | | // Getting pointer to Z of the source point |
279 | 4.05k | peZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
280 | | |
281 | | // Setting temporary to 0 |
282 | 4.05k | return SymCryptModElementIsZero( FMod, peZ ); |
283 | 4.05k | } |
284 | | |
285 | | // |
286 | | // The following function verifies if the point (X:Y:Z) in Jacobian |
287 | | // coordinates satisfies the equation Y^2 = X^3 + aXZ^4+bZ^6 . |
288 | | // |
289 | | UINT32 |
290 | | SYMCRYPT_CALL |
291 | | SymCryptShortWeierstrassOnCurve( |
292 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
293 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
294 | | _Out_writes_bytes_( cbScratch ) |
295 | | PBYTE pbScratch, |
296 | | SIZE_T cbScratch ) |
297 | 738 | { |
298 | 738 | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
299 | | |
300 | 738 | PSYMCRYPT_MODELEMENT peX = NULL; // Pointer to X |
301 | 738 | PSYMCRYPT_MODELEMENT peY = NULL; // Pointer to Y |
302 | 738 | PSYMCRYPT_MODELEMENT peZ = NULL; // Pointer to Z |
303 | | |
304 | 738 | PSYMCRYPT_MODELEMENT peT[2] = { 0 }; // Temporaries |
305 | | |
306 | 738 | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
307 | 738 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) ); |
308 | 738 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 2 * pCurve->cbModElement ); |
309 | | |
310 | | // Creating temporaries |
311 | 2.21k | for (UINT32 i=0; i<2; i++) |
312 | 1.47k | { |
313 | 1.47k | peT[i] = SymCryptModElementCreate( |
314 | 1.47k | pbScratch, |
315 | 1.47k | pCurve->cbModElement, |
316 | 1.47k | FMod ); |
317 | | |
318 | 1.47k | SYMCRYPT_ASSERT( peT[i] != NULL); |
319 | | |
320 | 1.47k | pbScratch += pCurve->cbModElement; |
321 | 1.47k | } |
322 | | |
323 | | // Fixing remaining scratch space size |
324 | 738 | cbScratch -= 2*pCurve->cbModElement; |
325 | | |
326 | | // Getting pointers to coordinates of the source point |
327 | 738 | peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
328 | 738 | peY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
329 | 738 | peZ = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
330 | | |
331 | | // Calculation |
332 | 738 | SymCryptModSquare( FMod, peZ, peT[0], pbScratch, cbScratch ); // T1 := Z * Z = Z^2 |
333 | 738 | SymCryptModSquare( FMod, peT[0], peT[1], pbScratch, cbScratch ); // T2 := T1 * T1 = Z^4 |
334 | 738 | SymCryptModMul( FMod, peT[0], peT[1], peT[0], pbScratch, cbScratch ); // T1 := T1 * T2 = Z^6 |
335 | | |
336 | 738 | SymCryptModMul( FMod, peT[0], pCurve->B, peT[0], pbScratch, cbScratch ); // T1 := T1 * b = bZ^6 |
337 | | |
338 | 738 | SymCryptModMul( FMod, peT[1], peX, peT[1], pbScratch, cbScratch ); // T2 := T2 * X = XZ^4 |
339 | 738 | SymCryptModMul( FMod, peT[1], pCurve->A, peT[1], pbScratch, cbScratch ); // T2 := T2 * a = aXZ^4 |
340 | | |
341 | 738 | SymCryptModAdd( FMod, peT[0], peT[1], peT[1], pbScratch, cbScratch ); // T2 := T1 + T2 = aXZ^4 + bZ^6 |
342 | | |
343 | 738 | SymCryptModSquare( FMod, peX, peT[0], pbScratch, cbScratch ); // T1 := X * X = X^2 |
344 | 738 | SymCryptModMul( FMod, peT[0], peX, peT[0], pbScratch, cbScratch ); // T1 := T1 * X = X^3 |
345 | 738 | SymCryptModAdd( FMod, peT[0], peT[1], peT[1], pbScratch, cbScratch ); // T2 := T1 + T2 = X^3 + aXZ^4 + bZ^6 |
346 | | |
347 | 738 | SymCryptModSquare( FMod, peY, peT[0], pbScratch, cbScratch ); // T1 := Y * Y = Y^2 |
348 | | |
349 | 738 | return SymCryptModElementIsEqual( FMod, peT[0], peT[1] ); |
350 | 738 | } |
351 | | |
352 | | // |
353 | | // based on dbl-2007-bl formula |
354 | | // but tweaked by saml to |
355 | | // a) remove overeager conversions from modular multiplication to modular squaring which introduce |
356 | | // more addition/subtraction. With current implementations (based on montgomery reduction), |
357 | | // the cost of [a square and an add/sub] is greater than the cost of [a multiplication] |
358 | | // b) share intermediate results of producing 8YYYY. [add/sub] is ~10% of cost of mul, so reducing |
359 | | // count of these operation has a real impact |
360 | | // |
361 | | // 2Y = 2*Y1 |
362 | | // 2YY = 2Y*Y1 |
363 | | // 4YY = 2*2YY |
364 | | // 8YYYY = 2YY*4YY |
365 | | // S = X1*4YY |
366 | | // XX = X1^2 |
367 | | // ZZ = Z1^2 |
368 | | // ZZZZ = ZZ^2 |
369 | | // M = 3*XX+a*ZZZZ |
370 | | // T = M^2-2*S |
371 | | // X3 = T |
372 | | // Y3 = M*(S-T)-8YYYY |
373 | | // Z3 = Z1*2Y |
374 | | // |
375 | | // Total cost: |
376 | | // 6 Mul (1 by a) |
377 | | // 4 Sqr |
378 | | // 2 Add |
379 | | // 4 Sub |
380 | | // 3 Dbl |
381 | | // |
382 | | // Special Case: |
383 | | // If the source point is equal to the identity |
384 | | // point of the curve (i.e. Z1 = 0 in Jacobian |
385 | | // coordinates) then the resulting point has |
386 | | // Z3 = Z1*2Y1 = 0. Thus, this formula is |
387 | | // complete (it works for all points). |
388 | | // |
389 | | VOID |
390 | | SYMCRYPT_CALL |
391 | | SymCryptShortWeierstrassDouble( |
392 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
393 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
394 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
395 | | UINT32 flags, |
396 | | _Out_writes_bytes_( cbScratch ) |
397 | | PBYTE pbScratch, |
398 | | SIZE_T cbScratch ) |
399 | 0 | { |
400 | 0 | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
401 | 0 | PSYMCRYPT_MODELEMENT peT[3] = { 0 }; // Temporaries |
402 | |
|
403 | 0 | PCSYMCRYPT_MODELEMENT peX1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
404 | 0 | PCSYMCRYPT_MODELEMENT peY1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
405 | 0 | PCSYMCRYPT_MODELEMENT peZ1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
406 | |
|
407 | 0 | PSYMCRYPT_MODELEMENT peX3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
408 | 0 | PSYMCRYPT_MODELEMENT peY3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
409 | 0 | PSYMCRYPT_MODELEMENT peZ3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ); |
410 | |
|
411 | 0 | SYMCRYPT_ASSERT( pCurve->type == SYMCRYPT_INTERNAL_ECURVE_TYPE_SHORT_WEIERSTRASS ); |
412 | 0 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
413 | 0 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 3 * pCurve->cbModElement ); |
414 | |
|
415 | 0 | UNREFERENCED_PARAMETER( flags ); |
416 | | |
417 | | // Creating temporaries |
418 | 0 | for (UINT32 i=0; i<3; i++) |
419 | 0 | { |
420 | 0 | peT[i] = SymCryptModElementCreate( |
421 | 0 | pbScratch, |
422 | 0 | pCurve->cbModElement, |
423 | 0 | FMod ); |
424 | |
|
425 | 0 | SYMCRYPT_ASSERT( peT[i] != NULL); |
426 | |
|
427 | 0 | pbScratch += pCurve->cbModElement; |
428 | 0 | } |
429 | | |
430 | | // Fixing remaining scratch space size |
431 | 0 | cbScratch -= 3*pCurve->cbModElement; |
432 | | |
433 | | // Calculate the points |
434 | 0 | SymCryptModAdd( FMod, peY1, peY1, peT[0], pbScratch, cbScratch ); /* T0 := Y1 + Y1 = 2Y */ |
435 | 0 | SymCryptModSquare( FMod, peZ1, peT[1], pbScratch, cbScratch ); /* T1 := Z1 * Z1 = ZZ */ |
436 | 0 | SymCryptModMul( FMod, peT[0], peZ1, peZ3, pbScratch, cbScratch ); /* Z3 := 2Y * Z1 = 2YZ */ |
437 | |
|
438 | 0 | SymCryptModMul( FMod, peY1, peT[0], peY3, pbScratch, cbScratch ); /* Y3 := 2Y * Y1 = 2YY */ |
439 | 0 | SymCryptModAdd( FMod, peY3, peY3, peT[0], pbScratch, cbScratch ); /* T0 := 2YY + 2YY = 4YY */ |
440 | 0 | SymCryptModMul( FMod, peT[0], peY3, peY3, pbScratch, cbScratch ); /* Y3 := 2YY * 4YY = 8YYYY */ |
441 | |
|
442 | 0 | SymCryptModMul( FMod, peT[0], peX1, peT[0], pbScratch, cbScratch ); /* T0 := X1 * 4YY = 4XYY = S */ |
443 | |
|
444 | 0 | SymCryptModSquare( FMod, peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T1 * T1 = ZZZZ */ |
445 | 0 | SymCryptModSquare( FMod, peX1, peT[2], pbScratch, cbScratch ); /* T2 := X1 * X1 = XX */ |
446 | 0 | SymCryptModMul( FMod, peT[1], pCurve->A, peT[1], pbScratch, cbScratch ); /* T1 := T1 * a = a*ZZZZ */ |
447 | 0 | SymCryptModAdd( FMod, peT[2], peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T2 + T1 = XX + a*ZZZZ */ |
448 | 0 | SymCryptModAdd( FMod, peT[2], peT[2], peT[2], pbScratch, cbScratch ); /* T2 := T2 + T2 = 2*XX */ |
449 | 0 | SymCryptModAdd( FMod, peT[0], peT[0], peX3, pbScratch, cbScratch ); /* X3 := 2*S */ |
450 | 0 | SymCryptModAdd( FMod, peT[2], peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T2 + T1 = 3*XX + a*ZZZZ = M */ |
451 | |
|
452 | 0 | SymCryptModSquare( FMod, peT[1], peT[2], pbScratch, cbScratch ); /* T2 := M^2 */ |
453 | 0 | SymCryptModSub( FMod, peT[2], peX3, peX3, pbScratch, cbScratch ); /* X3 := M^2 - 2*S = T */ |
454 | |
|
455 | 0 | SymCryptModSub( FMod, peT[0], peX3, peT[0], pbScratch, cbScratch ); /* T0 := S - T */ |
456 | 0 | SymCryptModMul( FMod, peT[1], peT[0], peT[0], pbScratch, cbScratch ); /* T0 := M * (S - T) */ |
457 | 0 | SymCryptModSub( FMod, peT[0], peY3, peY3, pbScratch, cbScratch ); /* Y3 := M * (S - T) - 8*YYYY */ |
458 | 0 | } |
459 | | |
460 | | |
461 | | // |
462 | | // based on dbl-2007-bl / dbl-2001-b formulae |
463 | | // but tweaked by saml to |
464 | | // a) remove overeager conversions from modular multiplication to modular squaring which introduce |
465 | | // more addition/subtraction. With current implementations (based on montgomery reduction), |
466 | | // the cost of [a square and an add/sub] is greater than the cost of [a multiplication] |
467 | | // b) share intermediate results of producing 8YYYY. [add/sub] is ~10% of cost of mul, so reducing |
468 | | // count of these operation has a real impact |
469 | | // c) make use of knowledge that curve has a == -3, so M can be calculated more efficiently |
470 | | // |
471 | | // 2Y = 2*Y1 |
472 | | // 2YY = 2Y*Y1 |
473 | | // 4YY = 2*2YY |
474 | | // 8YYYY = 2YY*4YY |
475 | | // ZZ = Z1^2 |
476 | | // S = X1*4YY |
477 | | // M = 3*(X1+ZZ)*(X1-ZZ) = 3*(XX - ZZZZ) |
478 | | // T = M^2-2*S |
479 | | // X3 = T |
480 | | // Y3 = M*(S-T)-8YYYY |
481 | | // Z3 = 2Y*Z1 |
482 | | // |
483 | | // Total cost: |
484 | | // 6 Mul |
485 | | // 2 Sqr |
486 | | // 2 Add |
487 | | // 4 Sub |
488 | | // 4 Dbl |
489 | | // |
490 | | // Special Case: |
491 | | // If the source point is equal to the identity |
492 | | // point of the curve (i.e. Z1 = 0 in Jacobian |
493 | | // coordinates) then the resulting point has |
494 | | // Z3 = Z1*2Y1 = 0. Thus, this formula is |
495 | | // complete (it works for all points). |
496 | | // |
497 | | VOID |
498 | | SYMCRYPT_CALL |
499 | | SymCryptShortWeierstrassDoubleSpecializedAm3( |
500 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
501 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
502 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
503 | | UINT32 flags, |
504 | | _Out_writes_bytes_( cbScratch ) |
505 | | PBYTE pbScratch, |
506 | | SIZE_T cbScratch ) |
507 | 315k | { |
508 | 315k | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
509 | 315k | PSYMCRYPT_MODELEMENT peT[3] = { 0 }; // Temporaries |
510 | | |
511 | 315k | PCSYMCRYPT_MODELEMENT peX1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
512 | 315k | PCSYMCRYPT_MODELEMENT peY1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
513 | 315k | PCSYMCRYPT_MODELEMENT peZ1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
514 | | |
515 | 315k | PSYMCRYPT_MODELEMENT peX3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
516 | 315k | PSYMCRYPT_MODELEMENT peY3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
517 | 315k | PSYMCRYPT_MODELEMENT peZ3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ); |
518 | | |
519 | 315k | SYMCRYPT_ASSERT( pCurve->type == SYMCRYPT_INTERNAL_ECURVE_TYPE_SHORT_WEIERSTRASS_AM3 ); |
520 | 315k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
521 | 315k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 3 * pCurve->cbModElement ); |
522 | | |
523 | 315k | UNREFERENCED_PARAMETER( flags ); |
524 | | |
525 | | // Creating temporaries |
526 | 1.26M | for (UINT32 i=0; i<3; i++) |
527 | 945k | { |
528 | 945k | peT[i] = SymCryptModElementCreate( |
529 | 945k | pbScratch, |
530 | 945k | pCurve->cbModElement, |
531 | 945k | FMod ); |
532 | | |
533 | 945k | SYMCRYPT_ASSERT( peT[i] != NULL); |
534 | | |
535 | 945k | pbScratch += pCurve->cbModElement; |
536 | 945k | } |
537 | | |
538 | | // Fixing remaining scratch space size |
539 | 315k | cbScratch -= 3*pCurve->cbModElement; |
540 | | |
541 | | // Calculate the points |
542 | 315k | SymCryptModAdd( FMod, peY1, peY1, peT[0], pbScratch, cbScratch ); /* T0 := Y1 + Y1 = 2Y */ |
543 | 315k | SymCryptModSquare( FMod, peZ1, peT[1], pbScratch, cbScratch ); /* T1 := Z1 * Z1 = ZZ */ |
544 | 315k | SymCryptModMul( FMod, peY1, peT[0], peY3, pbScratch, cbScratch ); /* Y3 := 2Y * Y1 = 2YY */ |
545 | | |
546 | 315k | SymCryptModMul( FMod, peT[0], peZ1, peZ3, pbScratch, cbScratch ); /* Z3 := 2Y * Z1 = 2YZ */ |
547 | | |
548 | 315k | SymCryptModAdd( FMod, peY3, peY3, peT[0], pbScratch, cbScratch ); /* T0 := 2YY + 2YY = 4YY */ |
549 | 315k | SymCryptModAdd( FMod, peX1, peT[1], peT[2], pbScratch, cbScratch ); /* T2 := X1 + ZZ */ |
550 | 315k | SymCryptModMul( FMod, peT[0], peY3, peY3, pbScratch, cbScratch ); /* Y3 := 2YY * 4YY = 8YYYY */ |
551 | | |
552 | 315k | SymCryptModSub( FMod, peX1, peT[1], peT[1], pbScratch, cbScratch ); /* T1 := X1 - ZZ */ |
553 | 315k | SymCryptModMul( FMod, peT[0], peX1, peT[0], pbScratch, cbScratch ); /* T0 := X1 * 4YY = 4XYY = S */ |
554 | | |
555 | 315k | SymCryptModMul( FMod, peT[2], peT[1], peT[2], pbScratch, cbScratch ); /* T2 := (X1 + ZZ)*(X1 - ZZ) = XX - ZZZZ */ |
556 | 315k | SymCryptModAdd( FMod, peT[2], peT[2], peT[1], pbScratch, cbScratch ); /* T1 := 2*(XX - ZZZZ) */ |
557 | 315k | SymCryptModAdd( FMod, peT[0], peT[0], peX3, pbScratch, cbScratch ); /* X3 := 2*S */ |
558 | 315k | SymCryptModAdd( FMod, peT[1], peT[2], peT[1], pbScratch, cbScratch ); /* T1 := 3*(XX - ZZZZ) = M */ |
559 | | |
560 | 315k | SymCryptModSquare( FMod, peT[1], peT[2], pbScratch, cbScratch ); /* T2 := M^2 */ |
561 | 315k | SymCryptModSub( FMod, peT[2], peX3, peX3, pbScratch, cbScratch ); /* X3 := M^2 - 2*S = T */ |
562 | | |
563 | 315k | SymCryptModSub( FMod, peT[0], peX3, peT[0], pbScratch, cbScratch ); /* T0 := S - T */ |
564 | 315k | SymCryptModMul( FMod, peT[1], peT[0], peT[0], pbScratch, cbScratch ); /* T0 := M * (S - T) */ |
565 | 315k | SymCryptModSub( FMod, peT[0], peY3, peY3, pbScratch, cbScratch ); /* Y3 := M * (S - T) - 8*YYYY */ |
566 | 315k | } |
567 | | |
568 | | // |
569 | | // based on add-2007-bl formula |
570 | | // but tweaked by saml to |
571 | | // remove overeager conversions from modular multiplication to modular squaring which introduce |
572 | | // more addition/subtraction. |
573 | | // |
574 | | // Z1Z1 = Z1^2 |
575 | | // Z2Z2 = Z2^2 |
576 | | // U1 = X1*Z2Z2 |
577 | | // U2 = X2*Z1Z1 |
578 | | // S1 = Y1*Z2*Z2Z2 |
579 | | // S2 = Y2*Z1*Z1Z1 |
580 | | // H = U2-U1 |
581 | | // 2H = 2*H |
582 | | // I = (2H)^2 |
583 | | // J = H*I |
584 | | // r = 2*(S2-S1) |
585 | | // V = U1*I |
586 | | // X3 = r^2-J-2*V |
587 | | // Y3 = r*(V-X3)-2*S1*J |
588 | | // Z3 = (Z1*Z2)*2H |
589 | | // |
590 | | // Total cost: |
591 | | // 12 Mul |
592 | | // 4 Sqr |
593 | | // 0 Add |
594 | | // 7 Sub |
595 | | // 3 Dbl |
596 | | // |
597 | | // Special Case: |
598 | | // If the two source points are opposite (X1 / Z1^2 == X2 / Z2^2), |
599 | | // then H = U2-U1 = 0. Thus Z3 = 0 and the result is correct. |
600 | | // |
601 | | VOID |
602 | | SYMCRYPT_CALL |
603 | | SymCryptShortWeierstrassAddDiffNonZero( |
604 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
605 | | _In_ PCSYMCRYPT_ECPOINT poSrc1, |
606 | | _In_ PCSYMCRYPT_ECPOINT poSrc2, |
607 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
608 | | _Out_writes_bytes_( cbScratch ) |
609 | | PBYTE pbScratch, |
610 | | SIZE_T cbScratch ) |
611 | 64.1k | { |
612 | 64.1k | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
613 | | |
614 | 64.1k | PCSYMCRYPT_MODELEMENT peX1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc1 ); |
615 | 64.1k | PCSYMCRYPT_MODELEMENT peY1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc1 ); |
616 | 64.1k | PCSYMCRYPT_MODELEMENT peZ1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc1 ); |
617 | | |
618 | 64.1k | PCSYMCRYPT_MODELEMENT peX2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc2 ); |
619 | 64.1k | PCSYMCRYPT_MODELEMENT peY2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc2 ); |
620 | 64.1k | PCSYMCRYPT_MODELEMENT peZ2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc2 ); |
621 | | |
622 | 64.1k | PSYMCRYPT_MODELEMENT peX3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
623 | 64.1k | PSYMCRYPT_MODELEMENT peY3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
624 | 64.1k | PSYMCRYPT_MODELEMENT peZ3 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ); |
625 | | |
626 | 64.1k | PSYMCRYPT_MODELEMENT peT[7] = { 0 }; // Temporaries |
627 | | |
628 | 64.1k | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
629 | 64.1k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
630 | 64.1k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 7 * pCurve->cbModElement ); |
631 | | |
632 | | // Creating temporaries |
633 | 512k | for (UINT32 i=0; i<7; i++) |
634 | 448k | { |
635 | 448k | peT[i] = SymCryptModElementCreate( |
636 | 448k | pbScratch, |
637 | 448k | pCurve->cbModElement, |
638 | 448k | FMod ); |
639 | | |
640 | 448k | SYMCRYPT_ASSERT( peT[i] != NULL); |
641 | | |
642 | 448k | pbScratch += pCurve->cbModElement; |
643 | 448k | } |
644 | | |
645 | | // Fixing remaining scratch space size |
646 | 64.1k | cbScratch -= 7*pCurve->cbModElement; |
647 | | |
648 | | // Calculation |
649 | | |
650 | 64.1k | SymCryptModSquare( FMod, peZ1, peT[0], pbScratch, cbScratch ); /* T0 := Z1 * Z1 = Z1Z1 */ |
651 | 64.1k | SymCryptModMul( FMod, peZ1, peT[0], peT[1], pbScratch, cbScratch ); /* T1 := Z1*Z1Z1 */ |
652 | | |
653 | 64.1k | SymCryptModSquare( FMod, peZ2, peT[6], pbScratch, cbScratch ); /* T6 := Z2 * Z2 = Z2Z2 */ |
654 | 64.1k | SymCryptModMul( FMod, peX1, peT[6], peT[2], pbScratch, cbScratch ); /* T2 := X1 * T6 = X1*Z2Z2 = U1 */ |
655 | 64.1k | SymCryptModMul( FMod, peX2, peT[0], peT[3], pbScratch, cbScratch ); /* T3 := X2 * Z1Z1 = U2 */ |
656 | 64.1k | SymCryptModSub( FMod, peT[3], peT[2], peT[5], pbScratch, cbScratch ); /* T5 := T3 - T2 = U2 - U1 = H */ |
657 | 64.1k | SymCryptModAdd( FMod, peT[5], peT[5], peT[3], pbScratch, cbScratch ); /* T3 := T5 + T5 = 2H */ |
658 | | |
659 | 64.1k | SymCryptModMul( FMod, peZ1, peZ2, peT[4], pbScratch, cbScratch ); /* T4 := Z1 * Z2 */ |
660 | | |
661 | 64.1k | SymCryptModMul( FMod, peZ2, peT[6], peT[6], pbScratch, cbScratch ); /* T6 := Z2 * T6 = Z2*Z2Z2 */ |
662 | 64.1k | SymCryptModMul( FMod, peT[4], peT[3], peZ3, pbScratch, cbScratch ); /* Z3 := T4 * T3 = Z1*Z2*2H */ |
663 | | |
664 | 64.1k | SymCryptModMul( FMod, peY1, peT[6], peT[6], pbScratch, cbScratch ); /* T6 := Y1 * T6 = Y1*Z2*Z2Z2 = S1 */ |
665 | 64.1k | SymCryptModMul( FMod, peY2, peT[1], peT[4], pbScratch, cbScratch ); /* T4 := Y2*Z1*Z1Z1 = S2 */ |
666 | 64.1k | SymCryptModSub( FMod, peT[4], peT[6], peT[4], pbScratch, cbScratch ); /* T4 := T4 - T6 = S2-S1 */ |
667 | 64.1k | SymCryptModAdd( FMod, peT[4], peT[4], peT[4], pbScratch, cbScratch ); /* T4 := T4 + T4 = 2*(S2-S1) = r */ |
668 | | |
669 | 64.1k | SymCryptModSquare( FMod, peT[3], peT[3], pbScratch, cbScratch ); /* T3 := T3 * T3 = (2*H)^2 = I */ |
670 | 64.1k | SymCryptModMul( FMod, peT[3], peT[5], peT[5], pbScratch, cbScratch ); /* T5 := T3 * T5 = H*I = J */ |
671 | 64.1k | SymCryptModMul( FMod, peT[2], peT[3], peT[3], pbScratch, cbScratch ); /* T3 := T2 * T3 = U1*I = V */ |
672 | | |
673 | 64.1k | SymCryptModSquare( FMod, peT[4], peT[2], pbScratch, cbScratch ); /* T2 := T4 * T4 = r^2 */ |
674 | 64.1k | SymCryptModSub( FMod, peT[2], peT[5], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T5 = r^2 - J */ |
675 | 64.1k | SymCryptModSub( FMod, peT[2], peT[3], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T3 = r^2 - J - V */ |
676 | 64.1k | SymCryptModSub( FMod, peT[2], peT[3], peX3, pbScratch, cbScratch ); /* T2 := T2 - T3 = r^2 - J - 2*V = X3 */ |
677 | | |
678 | 64.1k | SymCryptModSub( FMod, peT[3], peX3, peT[3], pbScratch, cbScratch ); /* T3 := T3 - T2 = V - X3 */ |
679 | 64.1k | SymCryptModMul( FMod, peT[3], peT[4], peT[3], pbScratch, cbScratch ); /* T3 := T3 * T4 = r*(V-X3) */ |
680 | 64.1k | SymCryptModMul( FMod, peT[6], peT[5], peT[6], pbScratch, cbScratch ); /* T6 := T6 * T5 = S1*J */ |
681 | 64.1k | SymCryptModAdd( FMod, peT[6], peT[6], peT[6], pbScratch, cbScratch ); /* T6 := T6 + T6 = 2*S1*J */ |
682 | 64.1k | SymCryptModSub( FMod, peT[3], peT[6], peY3, pbScratch, cbScratch ); /* Y3 := T6 - T3 = r*(V-X3) - 2*S1*J */ |
683 | 64.1k | } |
684 | | |
685 | | // |
686 | | // The following function is a complete **SIDE-CHANNEL-UNSAFE** |
687 | | // addition of points that detects as fast as possible the special cases |
688 | | // and merges the two previous calls. |
689 | | // |
690 | | VOID |
691 | | SYMCRYPT_CALL |
692 | | SymCryptShortWeierstrassAddSideChannelUnsafe( |
693 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
694 | | _In_ PCSYMCRYPT_ECPOINT poSrc1, |
695 | | _In_ PCSYMCRYPT_ECPOINT poSrc2, |
696 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
697 | | _Out_writes_bytes_( cbScratch ) |
698 | | PBYTE pbScratch, |
699 | | SIZE_T cbScratch ) |
700 | 18.0k | { |
701 | 18.0k | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
702 | | |
703 | 18.0k | PCSYMCRYPT_MODELEMENT peX1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc1 ); |
704 | 18.0k | PCSYMCRYPT_MODELEMENT peY1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc1 ); |
705 | 18.0k | PCSYMCRYPT_MODELEMENT peZ1 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc1 ); |
706 | | |
707 | 18.0k | PCSYMCRYPT_MODELEMENT peX2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc2 ); |
708 | 18.0k | PCSYMCRYPT_MODELEMENT peY2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc2 ); |
709 | 18.0k | PCSYMCRYPT_MODELEMENT peZ2 = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc2 ); |
710 | | |
711 | 18.0k | PSYMCRYPT_MODELEMENT peT[8] = { 0 }; // Temporaries |
712 | | |
713 | 18.0k | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
714 | 18.0k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
715 | 18.0k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + 8 * pCurve->cbModElement ); |
716 | | |
717 | | // Check if one of the points is zero |
718 | 18.0k | if (SymCryptModElementIsZero( FMod, peZ1 )) |
719 | 263 | { |
720 | 263 | SymCryptEcpointCopy( pCurve, poSrc2, poDst); |
721 | 263 | return; |
722 | 263 | } |
723 | | |
724 | 17.7k | if (SymCryptModElementIsZero( FMod, peZ2 )) |
725 | 0 | { |
726 | 0 | SymCryptEcpointCopy( pCurve, poSrc1, poDst); |
727 | 0 | return; |
728 | 0 | } |
729 | | |
730 | | // Creating temporaries |
731 | 159k | for (UINT32 i=0; i<8; i++) |
732 | 141k | { |
733 | 141k | peT[i] = SymCryptModElementCreate( |
734 | 141k | pbScratch, |
735 | 141k | pCurve->cbModElement, |
736 | 141k | FMod ); |
737 | | |
738 | 141k | SYMCRYPT_ASSERT( peT[i] != NULL); |
739 | | |
740 | 141k | pbScratch += pCurve->cbModElement; |
741 | 141k | } |
742 | | |
743 | | // Fixing remaining scratch space size |
744 | 17.7k | cbScratch -= 8*pCurve->cbModElement; |
745 | | |
746 | | // Calculation |
747 | | |
748 | 17.7k | SymCryptModSquare( FMod, peZ1, peT[0], pbScratch, cbScratch ); /* T0 := Z1 * Z1 = Z1Z1 */ |
749 | 17.7k | SymCryptModMul( FMod, peZ1, peT[0], peT[1], pbScratch, cbScratch ); /* T1 := Z1*Z1Z1 */ |
750 | | |
751 | 17.7k | SymCryptModSquare( FMod, peZ2, peT[6], pbScratch, cbScratch ); /* T6 := Z2 * Z2 = Z2Z2 */ |
752 | 17.7k | SymCryptModMul( FMod, peX1, peT[6], peT[2], pbScratch, cbScratch ); /* T2 := X1 * T6 = X1*Z2Z2 = U1 */ |
753 | 17.7k | SymCryptModMul( FMod, peX2, peT[0], peT[3], pbScratch, cbScratch ); /* T3 := X2 * Z1Z1 = U2 */ |
754 | 17.7k | SymCryptModSub( FMod, peT[3], peT[2], peT[5], pbScratch, cbScratch ); /* T5 := T3 - T2 = U2 - U1 = H */ |
755 | | |
756 | 17.7k | SymCryptModMul( FMod, peY2, peT[1], peT[7], pbScratch, cbScratch ); /* T7 := Y2 * T1 = Y2*Z1*Z1Z1 = S2 */ |
757 | 17.7k | SymCryptModMul( FMod, peZ2, peT[6], peT[1], pbScratch, cbScratch ); /* T1 := Z2 * T6 = Z2*Z2Z2 */ |
758 | 17.7k | SymCryptModMul( FMod, peY1, peT[1], peT[1], pbScratch, cbScratch ); /* T1 := Y1 * T1 = Y1*Z2*Z2Z2 = S1 */ |
759 | 17.7k | SymCryptModSub( FMod, peT[7], peT[1], peT[7], pbScratch, cbScratch ); /* T7 := T7 - T1 = S2-S1 */ |
760 | | |
761 | 17.7k | if (SymCryptModElementIsZero( FMod, peT[5] ) & SymCryptModElementIsZero( FMod, peT[7] )) |
762 | 0 | { |
763 | | // Points are equal - run double on poSrc1 |
764 | |
|
765 | 0 | SymCryptModElementCopy( FMod, peT[0], peT[4] ); /* Move Z1Z1 for later */ |
766 | |
|
767 | 0 | SymCryptModSquare( FMod, peX1, peT[0], pbScratch, cbScratch ); /* T0 := X1 * X1 = XX */ |
768 | 0 | SymCryptModSquare( FMod, peY1, peT[3], pbScratch, cbScratch ); /* T3 := Y1 * Y1 = YY */ |
769 | 0 | SymCryptModSquare( FMod, peT[3], peT[5], pbScratch, cbScratch ); /* T5 := T3 * T3 = YYYY */ |
770 | |
|
771 | 0 | SymCryptModAdd( FMod, peX1, peT[3], peT[1], pbScratch, cbScratch ); /* T1 := X1 + T3 = X + YY */ |
772 | 0 | SymCryptModSquare( FMod, peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T1 * T1 = (X + YY)^2 */ |
773 | 0 | SymCryptModSub( FMod, peT[1], peT[0], peT[1], pbScratch, cbScratch ); /* T1 := T1 - T0 = (X + YY)^2 - XX */ |
774 | 0 | SymCryptModSub( FMod, peT[1], peT[5], peT[1], pbScratch, cbScratch ); /* T1 := T1 - T5 = (X + YY)^2 - XX - YYYY */ |
775 | 0 | SymCryptModAdd( FMod, peT[1], peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T1 + T1 = 2*((X + YY)^2 - XX - YYYY) = S */ |
776 | | |
777 | | //SymCryptModSquare( FMod, peZ1, peT[4], pbScratch, cbScratch ); /* T4 := Z1 * Z1 = ZZ */ |
778 | |
|
779 | 0 | SymCryptModSquare( FMod, peT[4], peT[2], pbScratch, cbScratch ); /* T2 := T4 * T4 = ZZ^2 */ |
780 | 0 | SymCryptModMul( FMod, peT[2], pCurve->A, peT[2], pbScratch, cbScratch ); /* T2 := T2 * a = a*ZZ^2 */ |
781 | 0 | SymCryptModAdd( FMod, peT[2], peT[0], peT[2], pbScratch, cbScratch ); /* T2 := T2 + T0 = XX + a*ZZ^2 */ |
782 | 0 | SymCryptModAdd( FMod, peT[0], peT[0], peT[0], pbScratch, cbScratch ); /* T0 := T0 + T0 = 2*XX */ |
783 | 0 | SymCryptModAdd( FMod, peT[2], peT[0], peT[2], pbScratch, cbScratch ); /* T2 := T2 + T0 = 3*XX + a*ZZ^2 = M */ |
784 | |
|
785 | 0 | SymCryptModSquare( FMod, peT[2], peT[0], pbScratch, cbScratch ); /* T0 := T2 * T2 = M^2 */ |
786 | 0 | SymCryptModSub( FMod, peT[0], peT[1], peT[0], pbScratch, cbScratch ); /* T0 := T0 - T1 = M^2 - S */ |
787 | 0 | SymCryptModSub( FMod, peT[0], peT[1], peT[0], pbScratch, cbScratch ); /* T0 := T0 - T1 = M^2 - 2*S = T = X3 */ |
788 | |
|
789 | 0 | SymCryptModSub( FMod, peT[1], peT[0], peT[1], pbScratch, cbScratch ); /* T1 := T1 - T0 = S - T */ |
790 | 0 | SymCryptModMul( FMod, peT[2], peT[1], peT[1], pbScratch, cbScratch ); /* T1 := T2 * T1 = M * (S - T) */ |
791 | 0 | SymCryptModAdd( FMod, peT[5], peT[5], peT[5], pbScratch, cbScratch ); /* T5 := T5 + T5 = 2*YYYY */ |
792 | 0 | SymCryptModAdd( FMod, peT[5], peT[5], peT[5], pbScratch, cbScratch ); /* T5 := T5 + T5 = 4*YYYY */ |
793 | 0 | SymCryptModAdd( FMod, peT[5], peT[5], peT[5], pbScratch, cbScratch ); /* T5 := T5 + T5 = 8*YYYY */ |
794 | 0 | SymCryptModSub( FMod, peT[1], peT[5], peT[1], pbScratch, cbScratch ); /* T1 := T1 - T5 = M * (S - T) - 8*YYYY = Y3 */ |
795 | |
|
796 | 0 | SymCryptModAdd( FMod, peY1, peZ1, peT[2], pbScratch, cbScratch ); /* T2 := Y1 + Z1 */ |
797 | 0 | SymCryptModSquare( FMod, peT[2], peT[2], pbScratch, cbScratch ); /* T2 := T2 * T2 = (Y + Z )^2 */ |
798 | 0 | SymCryptModSub( FMod, peT[2], peT[3], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T3 = (Y + Z )^2 - YY */ |
799 | 0 | SymCryptModSub( FMod, peT[2], peT[4], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T4 = (Y + Z )^2 - YY - ZZ = Z3 */ |
800 | | |
801 | | // Setting the result |
802 | 0 | SymCryptModElementCopy( FMod, peT[0], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ) ); |
803 | 0 | SymCryptModElementCopy( FMod, peT[1], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ) ); |
804 | 0 | SymCryptModElementCopy( FMod, peT[2], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ) ); |
805 | 0 | } |
806 | 17.7k | else |
807 | 17.7k | { |
808 | | // Continue the addition |
809 | | |
810 | 17.7k | SymCryptModAdd( FMod, peZ1, peZ2, peT[4], pbScratch, cbScratch ); /* T4 := Z1 + Z2 */ |
811 | 17.7k | SymCryptModSquare( FMod, peT[4], peT[4], pbScratch, cbScratch ); /* T4 := T4 * T4 = (Z1 + Z2)^2 */ |
812 | 17.7k | SymCryptModSub( FMod, peT[4], peT[0], peT[4], pbScratch, cbScratch ); /* T4 := T4 - Z1Z1 = (Z1 + Z2)^2 - Z1Z1 */ |
813 | 17.7k | SymCryptModSub( FMod, peT[4], peT[6], peT[4], pbScratch, cbScratch ); /* T4 := T4 - T6 = (Z1 + Z2)^2 - Z1Z1 - Z2Z2 */ |
814 | 17.7k | SymCryptModMul( FMod, peT[4], peT[5], peT[4], pbScratch, cbScratch ); /* T4 := T4 * T5 = ((Z1 + Z2)^2 - Z1Z1 - Z2Z2)*H = Z3 */ |
815 | | |
816 | 17.7k | SymCryptModAdd( FMod, peT[7], peT[7], peT[7], pbScratch, cbScratch ); /* T7 := T7 + T7 = 2*(S2-S1) = r */ |
817 | | |
818 | 17.7k | SymCryptModAdd( FMod, peT[5], peT[5], peT[3], pbScratch, cbScratch ); /* T3 := T5 + T5 = 2*H */ |
819 | 17.7k | SymCryptModSquare( FMod, peT[3], peT[3], pbScratch, cbScratch ); /* T3 := T3 * T3 = (2*H)^2 = I */ |
820 | 17.7k | SymCryptModMul( FMod, peT[3], peT[5], peT[5], pbScratch, cbScratch ); /* T5 := T3 * T5 = H*I = J */ |
821 | 17.7k | SymCryptModMul( FMod, peT[2], peT[3], peT[3], pbScratch, cbScratch ); /* T3 := T2 * T3 = U1*I = V */ |
822 | | |
823 | 17.7k | SymCryptModSquare( FMod, peT[7], peT[2], pbScratch, cbScratch ); /* T2 := T7 * T7 = r^2 */ |
824 | 17.7k | SymCryptModSub( FMod, peT[2], peT[5], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T5 = r^2 - J */ |
825 | 17.7k | SymCryptModSub( FMod, peT[2], peT[3], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T3 = r^2 - J - V */ |
826 | 17.7k | SymCryptModSub( FMod, peT[2], peT[3], peT[2], pbScratch, cbScratch ); /* T2 := T2 - T3 = r^2 - J - 2*V = X3 */ |
827 | | |
828 | 17.7k | SymCryptModSub( FMod, peT[3], peT[2], peT[3], pbScratch, cbScratch ); /* T3 := T3 - T2 = V - X3 */ |
829 | 17.7k | SymCryptModMul( FMod, peT[3], peT[7], peT[3], pbScratch, cbScratch ); /* T3 := T3 * T7 = r*(V-X3) */ |
830 | 17.7k | SymCryptModMul( FMod, peT[1], peT[5], peT[6], pbScratch, cbScratch ); /* T6 := T1 * T5 = S1*J */ |
831 | 17.7k | SymCryptModAdd( FMod, peT[6], peT[6], peT[6], pbScratch, cbScratch ); /* T6 := T6 + T6 = 2*S1*J */ |
832 | 17.7k | SymCryptModSub( FMod, peT[3], peT[6], peT[3], pbScratch, cbScratch ); /* T3 := T6 - T3 = r*(V-X3) - 2*S1*J = Y3 */ |
833 | | |
834 | | // Setting the result |
835 | 17.7k | SymCryptModElementCopy( FMod, peT[2], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ) ); |
836 | 17.7k | SymCryptModElementCopy( FMod, peT[3], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ) ); |
837 | 17.7k | SymCryptModElementCopy( FMod, peT[4], SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ) ); |
838 | 17.7k | } |
839 | 17.7k | } |
840 | | |
841 | | VOID |
842 | | SYMCRYPT_CALL |
843 | | SymCryptShortWeierstrassAdd( |
844 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
845 | | _In_ PCSYMCRYPT_ECPOINT poSrc1, |
846 | | _In_ PCSYMCRYPT_ECPOINT poSrc2, |
847 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
848 | | UINT32 flags, |
849 | | _Out_writes_bytes_( cbScratch ) |
850 | | PBYTE pbScratch, |
851 | | SIZE_T cbScratch ) |
852 | 18.6k | { |
853 | 18.6k | UINT32 dSrc1Zero = 0; |
854 | 18.6k | UINT32 dSrc2Zero = 0; |
855 | 18.6k | UINT32 dSrcEqual = 0; |
856 | | |
857 | | // Temporary points |
858 | 18.6k | PSYMCRYPT_ECPOINT poQ0 = NULL; |
859 | 18.6k | PSYMCRYPT_ECPOINT poQ1 = NULL; |
860 | | |
861 | 18.6k | SIZE_T cbEcpoint = SymCryptSizeofEcpointFromCurve( pCurve ); |
862 | | |
863 | 18.6k | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
864 | 18.6k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc1->pCurve) && SymCryptEcurveIsSame(pCurve, poSrc2->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
865 | 18.6k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) ); // We will need the entire scratch space |
866 | | |
867 | 18.6k | SYMCRYPT_ASSERT( cbScratch > 2*cbEcpoint ); |
868 | | |
869 | 18.6k | if ((flags & SYMCRYPT_FLAG_DATA_PUBLIC) != 0) |
870 | 18.0k | { |
871 | 18.0k | SymCryptShortWeierstrassAddSideChannelUnsafe( pCurve, poSrc1, poSrc2, poDst, pbScratch, cbScratch ); |
872 | 18.0k | } |
873 | 660 | else |
874 | 660 | { |
875 | | // Creating temporary points |
876 | 660 | poQ0 = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve ); |
877 | 660 | SYMCRYPT_ASSERT( poQ0 != NULL); |
878 | 660 | pbScratch += cbEcpoint; |
879 | | |
880 | 660 | poQ1 = SymCryptEcpointCreate( pbScratch, cbEcpoint, pCurve ); |
881 | 660 | SYMCRYPT_ASSERT( poQ1 != NULL); |
882 | 660 | pbScratch += cbEcpoint; |
883 | | |
884 | | // Fixing remaining scratch space size |
885 | 660 | cbScratch -= 2*cbEcpoint; |
886 | | |
887 | | // Calculate the masks |
888 | 660 | dSrc1Zero = SymCryptShortWeierstrassIsZero( pCurve, poSrc1, pbScratch, cbScratch ); |
889 | 660 | dSrc2Zero = SymCryptShortWeierstrassIsZero( pCurve, poSrc2, pbScratch, cbScratch ); |
890 | 660 | dSrcEqual = SymCryptShortWeierstrassIsEqual( pCurve, poSrc1, poSrc2, SYMCRYPT_FLAG_ECPOINT_EQUAL, pbScratch, cbScratch ); |
891 | | |
892 | | // Side-channel safe computations |
893 | 660 | SymCryptShortWeierstrassAddDiffNonZero( pCurve, poSrc1, poSrc2, poQ0, pbScratch, cbScratch ); // This covers the cases where Src1 != Src2 or Src1 = -Src2 |
894 | | |
895 | 660 | SymCryptEcpointDouble( pCurve, poSrc1, poQ1, 0, pbScratch, cbScratch ); // Dispatch to Double function; enables type assertion on SymCryptShortWeierstrassDouble to be specific |
896 | 660 | SymCryptEcpointMaskedCopy( pCurve, poQ1, poQ0, dSrcEqual ); // (Masked) copy if the points are equal |
897 | | |
898 | 660 | SymCryptEcpointMaskedCopy( pCurve, poSrc1, poQ0, dSrc2Zero ); // (Masked) copy if Src2 = 0 |
899 | 660 | SymCryptEcpointMaskedCopy( pCurve, poSrc2, poQ0, dSrc1Zero ); // (Masked) copy if Src1 = 0 |
900 | | |
901 | 660 | SymCryptEcpointCopy( pCurve, poQ0, poDst ); // Copy the final result to destination |
902 | 660 | } |
903 | 18.6k | } |
904 | | |
905 | | VOID |
906 | | SYMCRYPT_CALL |
907 | | SymCryptShortWeierstrassNegate( |
908 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
909 | | _Inout_ PSYMCRYPT_ECPOINT poSrc, |
910 | | UINT32 mask, |
911 | | _Out_writes_bytes_( cbScratch ) |
912 | | PBYTE pbScratch, |
913 | | SIZE_T cbScratch ) |
914 | 58.2k | { |
915 | 58.2k | PCSYMCRYPT_MODULUS FMod = pCurve->FMod; |
916 | 58.2k | PSYMCRYPT_MODELEMENT peY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc); |
917 | | |
918 | 58.2k | PSYMCRYPT_MODELEMENT peTmp = NULL; |
919 | | |
920 | 58.2k | SYMCRYPT_ASSERT( SYMCRYPT_CURVE_IS_SHORT_WEIERSTRASS_TYPE(pCurve) ); |
921 | 58.2k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) ); |
922 | 58.2k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) + pCurve->cbModElement); |
923 | | |
924 | 58.2k | peTmp = SymCryptModElementCreate( |
925 | 58.2k | pbScratch, |
926 | 58.2k | pCurve->cbModElement, |
927 | 58.2k | FMod ); |
928 | 58.2k | SYMCRYPT_ASSERT( peTmp != NULL); |
929 | | |
930 | 58.2k | pbScratch += pCurve->cbModElement; |
931 | 58.2k | cbScratch -= pCurve->cbModElement; |
932 | | |
933 | 58.2k | SymCryptModNeg( FMod, peY, peTmp, pbScratch, cbScratch ); |
934 | 58.2k | SymCryptModElementMaskedCopy( FMod, peTmp, peY, mask ); |
935 | 58.2k | } |