/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 | } |