/src/SymCrypt/lib/ecpoint.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // ecpoint.c Ecpoint functions |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | // |
7 | | |
8 | | #include "precomp.h" |
9 | | |
10 | | // Table with the number of field elements for each point format |
11 | | const UINT32 SymCryptEcpointFormatNumberofElements[] = { |
12 | | 0, |
13 | | 1, // SYMCRYPT_ECPOINT_FORMAT_X |
14 | | 2, // SYMCRYPT_ECPOINT_FORMAT_XY |
15 | | }; |
16 | | |
17 | | UINT32 |
18 | | SYMCRYPT_CALL |
19 | | SymCryptSizeofEcpointEx( |
20 | | UINT32 cbModElement, |
21 | | UINT32 numOfCoordinates ) |
22 | 62.2k | { |
23 | 62.2k | SYMCRYPT_ASSERT(numOfCoordinates > 0); |
24 | 62.2k | SYMCRYPT_ASSERT(numOfCoordinates <= SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH); |
25 | | |
26 | | // Callers should never specify numOfCoordinates equal to 0 or greater than |
27 | | // SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH |
28 | | // Return 0 to indicate failure if a caller does specify invalid numOfCoordinates |
29 | 62.2k | if( (numOfCoordinates == 0) || (numOfCoordinates > SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH) ) |
30 | 0 | { |
31 | 0 | return 0; |
32 | 0 | } |
33 | | |
34 | | // Since the maximum number of coordinates is 4 this result is bounded |
35 | | // by 4*2^17 + overhead ~ 2^20 |
36 | 62.2k | return sizeof(SYMCRYPT_ECPOINT) + numOfCoordinates * cbModElement; |
37 | 62.2k | } |
38 | | |
39 | | UINT32 |
40 | | SYMCRYPT_CALL |
41 | | SymCryptSizeofEcpointFromCurve( PCSYMCRYPT_ECURVE pCurve ) |
42 | 30.1k | { |
43 | | // Same bound as SymCryptSizeofEcpointEx |
44 | 30.1k | return SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) ); |
45 | 30.1k | } |
46 | | |
47 | | PSYMCRYPT_ECPOINT |
48 | | SYMCRYPT_CALL |
49 | | SymCryptEcpointAllocate( _In_ PCSYMCRYPT_ECURVE pCurve ) |
50 | 0 | { |
51 | 0 | PVOID p = NULL; |
52 | 0 | SIZE_T cb; |
53 | 0 | PSYMCRYPT_ECPOINT res = NULL; |
54 | |
|
55 | 0 | cb = SymCryptSizeofEcpointFromCurve( pCurve ); |
56 | |
|
57 | 0 | if ( cb != 0 ) |
58 | 0 | { |
59 | 0 | p = SymCryptCallbackAlloc( cb ); |
60 | 0 | } |
61 | |
|
62 | 0 | if ( p==NULL ) |
63 | 0 | { |
64 | 0 | goto cleanup; |
65 | 0 | } |
66 | | |
67 | 0 | res = SymCryptEcpointCreate( p, cb, pCurve ); |
68 | |
|
69 | 0 | cleanup: |
70 | 0 | return res; |
71 | 0 | } |
72 | | |
73 | | VOID |
74 | | SYMCRYPT_CALL |
75 | | SymCryptEcpointFree( |
76 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
77 | | _Out_ PSYMCRYPT_ECPOINT poDst ) |
78 | 0 | { |
79 | 0 | SYMCRYPT_CHECK_MAGIC( poDst ); |
80 | 0 | SymCryptEcpointWipe( pCurve, poDst ); |
81 | 0 | SymCryptCallbackFree( poDst ); |
82 | 0 | } |
83 | | |
84 | | PSYMCRYPT_ECPOINT |
85 | | SYMCRYPT_CALL |
86 | | SymCryptEcpointCreateEx( |
87 | | _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, |
88 | | SIZE_T cbBuffer, |
89 | | PCSYMCRYPT_ECURVE pCurve, |
90 | | UINT32 numOfCoordinates ) |
91 | 27.1k | { |
92 | 27.1k | PSYMCRYPT_ECPOINT poPoint = NULL; |
93 | | |
94 | 27.1k | PSYMCRYPT_MODELEMENT pmTmp = NULL; |
95 | 27.1k | UINT32 cbModElement = pCurve->cbModElement; |
96 | | |
97 | 27.1k | PBYTE pbBufferEnd = pbBuffer + cbBuffer; |
98 | 27.1k | UNREFERENCED_PARAMETER( pbBufferEnd ); // only referenced in an ASSERT... |
99 | | |
100 | 27.1k | SYMCRYPT_ASSERT( pCurve->FMod != 0 ); |
101 | 27.1k | SYMCRYPT_ASSERT( pCurve->cbModElement != 0 ); |
102 | 27.1k | SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofEcpointEx( pCurve->cbModElement, numOfCoordinates ) ); |
103 | 27.1k | if ( cbBuffer == 0 || numOfCoordinates == 0 ) |
104 | 0 | { |
105 | 0 | goto cleanup; |
106 | 0 | } |
107 | | |
108 | 27.1k | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer ); |
109 | | |
110 | 27.1k | poPoint = (PSYMCRYPT_ECPOINT) pbBuffer; |
111 | | |
112 | 27.1k | pbBuffer += sizeof(SYMCRYPT_ECPOINT); |
113 | | |
114 | | // Setting the point coordinates |
115 | 114k | for (UINT32 i=0; i<numOfCoordinates; i++) |
116 | 87.1k | { |
117 | 87.1k | SYMCRYPT_ASSERT( pbBuffer + cbModElement <= pbBufferEnd ); |
118 | 87.1k | pmTmp = SymCryptModElementCreate( pbBuffer, cbModElement, pCurve->FMod ); |
119 | 87.1k | if ( pmTmp == NULL ) |
120 | 0 | { |
121 | 0 | poPoint = NULL; |
122 | 0 | goto cleanup; |
123 | 0 | } |
124 | 87.1k | pbBuffer += cbModElement; |
125 | 87.1k | } |
126 | | |
127 | | // Setting the normalized flag |
128 | 27.1k | poPoint->normalized = FALSE; |
129 | | |
130 | | // Setting the curve |
131 | 27.1k | poPoint->pCurve = pCurve; |
132 | | |
133 | | // Setting the magic |
134 | 27.1k | SYMCRYPT_SET_MAGIC( poPoint ); |
135 | | |
136 | 27.1k | cleanup: |
137 | 27.1k | return poPoint; |
138 | 27.1k | } |
139 | | |
140 | | PSYMCRYPT_ECPOINT |
141 | | SYMCRYPT_CALL |
142 | | SymCryptEcpointCreate( |
143 | | _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, |
144 | | SIZE_T cbBuffer, |
145 | | _In_ PCSYMCRYPT_ECURVE pCurve ) |
146 | 25.0k | { |
147 | | |
148 | 25.0k | SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 ); |
149 | | |
150 | 25.0k | return SymCryptEcpointCreateEx( pbBuffer, cbBuffer, pCurve, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) ); |
151 | 25.0k | } |
152 | | |
153 | | PSYMCRYPT_ECPOINT |
154 | | SYMCRYPT_CALL |
155 | | SymCryptEcpointRetrieveHandle( _In_ PBYTE pbBuffer ) |
156 | 0 | { |
157 | 0 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer ); |
158 | |
|
159 | 0 | return (PSYMCRYPT_ECPOINT) pbBuffer; |
160 | 0 | } |
161 | | |
162 | | VOID |
163 | | SYMCRYPT_CALL |
164 | | SymCryptEcpointWipe( _In_ PCSYMCRYPT_ECURVE pCurve, _Out_ PSYMCRYPT_ECPOINT poDst ) |
165 | 0 | { |
166 | 0 | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
167 | | |
168 | | // Wipe the whole structure in one go. |
169 | 0 | SymCryptWipe( poDst, SymCryptSizeofEcpointFromCurve( pCurve ) ); |
170 | 0 | } |
171 | | |
172 | | VOID |
173 | | SymCryptEcpointCopy( |
174 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
175 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
176 | | _Out_ PSYMCRYPT_ECPOINT poDst ) |
177 | 22.5k | { |
178 | 22.5k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
179 | | |
180 | 22.5k | if( poSrc != poDst ) |
181 | 22.5k | { |
182 | | // Unconditionally set the normalization state of destination to source |
183 | 22.5k | poDst->normalized = poSrc->normalized; |
184 | | |
185 | 22.5k | memcpy(poDst + 1, poSrc + 1, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits * SYMCRYPT_FDEF_DIGIT_SIZE); |
186 | 22.5k | } |
187 | 22.5k | } |
188 | | |
189 | | VOID |
190 | | SymCryptEcpointMaskedCopy( |
191 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
192 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
193 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
194 | | UINT32 mask ) |
195 | 971k | { |
196 | 971k | SYMCRYPT_ASSERT( (mask == 0) || (mask == 0xffffffff) ); |
197 | 971k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
198 | | |
199 | | // Unconditionally combine the normalization state of source and destination to avoid potential for |
200 | | // leak of mask. Normalized is a non-secret value and is permitted to be leaked by side-channels |
201 | 971k | poDst->normalized &= poSrc->normalized; |
202 | | |
203 | | // dcl - this looks like the equivalent of memcpy |
204 | | // should be proven that arguments cannot be the result of an integer overflow |
205 | 971k | SymCryptFdefMaskedCopy((PCBYTE)poSrc + sizeof(SYMCRYPT_ECPOINT), (PBYTE)poDst + sizeof(SYMCRYPT_ECPOINT), SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits, mask ); |
206 | 971k | } |
207 | | |
208 | | // |
209 | | // SymCryptEcpointTransform: Internal function to transform an ECPOINT |
210 | | // from one coordinate representation to another. One point has the default |
211 | | // format of the curve. The other point has a format large enough for the external |
212 | | // SYMCRYPT_ECPOINT_FORMAT. |
213 | | // |
214 | | // When the boolean setValue is set to TRUE, the source point is the one with |
215 | | // the external format eformat, and the destination point has the default |
216 | | // format of the curve. If setValue = FALSE the roles are reversed. |
217 | | // This function is only called by the Get / Set Value functions. |
218 | | // |
219 | | SYMCRYPT_ERROR |
220 | | SYMCRYPT_CALL |
221 | | SymCryptEcpointTransform( |
222 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
223 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
224 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
225 | | SYMCRYPT_ECPOINT_FORMAT eformat, |
226 | | BOOLEAN setValue, |
227 | | UINT32 flags, |
228 | | _Out_writes_bytes_( cbScratch ) |
229 | | PBYTE pbScratch, |
230 | | SIZE_T cbScratch ) |
231 | 2.08k | { |
232 | 2.08k | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
233 | | |
234 | 2.08k | PSYMCRYPT_MODELEMENT peSrc = NULL; |
235 | 2.08k | PSYMCRYPT_MODELEMENT peDst = NULL; |
236 | 2.08k | PSYMCRYPT_MODELEMENT peX = NULL; |
237 | 2.08k | PSYMCRYPT_MODELEMENT peY = NULL; |
238 | | |
239 | 2.08k | SYMCRYPT_ECPOINT_COORDINATES coFrom = SYMCRYPT_ECPOINT_COORDINATES_INVALID; |
240 | 2.08k | SYMCRYPT_ECPOINT_COORDINATES coTo = SYMCRYPT_ECPOINT_COORDINATES_INVALID; |
241 | | |
242 | 2.08k | PSYMCRYPT_MODELEMENT peT[2] = { 0 }; // Temporaries |
243 | | |
244 | 2.08k | SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 ); |
245 | 2.08k | SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) ); |
246 | 2.08k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ), |
247 | 2.08k | SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->FModDigits )) + |
248 | 2.08k | 2 * pCurve->cbModElement ); |
249 | | |
250 | | // Get the assumed representation from the external format |
251 | 2.08k | switch (eformat) |
252 | 2.08k | { |
253 | 325 | case (SYMCRYPT_ECPOINT_FORMAT_X): |
254 | 325 | coFrom = SYMCRYPT_ECPOINT_COORDINATES_SINGLE; |
255 | 325 | break; |
256 | 1.75k | case (SYMCRYPT_ECPOINT_FORMAT_XY): |
257 | 1.75k | coFrom = SYMCRYPT_ECPOINT_COORDINATES_AFFINE; |
258 | 1.75k | break; |
259 | 0 | default: |
260 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
261 | 0 | goto cleanup; |
262 | 2.08k | } |
263 | | |
264 | | // Find out whether we are setting or getting the value of the ECPOINT |
265 | 2.08k | if (setValue) |
266 | 1.17k | { |
267 | 1.17k | coTo = pCurve->eCoordinates; |
268 | 1.17k | } |
269 | 912 | else |
270 | 912 | { |
271 | 912 | coTo = coFrom; |
272 | 912 | coFrom = pCurve->eCoordinates; |
273 | 912 | } |
274 | | |
275 | | // Take all the possible supported transformations: |
276 | | // - From SYMCRYPT_ECPOINT_COORDINATES_SINGLE to |
277 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE (identity transformation) |
278 | | // * SYMCRYPT_ECPOINT_COORDINATES_AFFINE (** Set all zeros to the Y coordinate **) |
279 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE |
280 | | // - From SYMCRYPT_ECPOINT_COORDINATES_AFFINE to |
281 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE (** Ignore Y coordinate **) |
282 | | // * SYMCRYPT_ECPOINT_COORDINATES_AFFINE (identity transformation) |
283 | | // * SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN |
284 | | // * SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE |
285 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE (** Ignore Y coordinate **) |
286 | | // - From SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN to |
287 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE |
288 | | // * SYMCRYPT_ECPOINT_COORDINATES_AFFINE |
289 | | // * SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN (identity transformation) |
290 | | // - From SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE to |
291 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE |
292 | | // * SYMCRYPT_ECPOINT_COORDINATES_AFFINE |
293 | | // * SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE (identity transformation) |
294 | | // - From SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE |
295 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE |
296 | | // * SYMCRYPT_ECPOINT_COORDINATES_AFFINE (** Set all zeros to the Y coordinate **) |
297 | | // * SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE (identity transformation) |
298 | | |
299 | | // dcl - this appears that it might be a candidate for refactoring. Lots of code that looks |
300 | | // duplicated across sections. Maybe some number of small functions would make it less fragile? |
301 | 2.08k | if ( coFrom == coTo ) |
302 | 0 | { |
303 | 0 | SymCryptEcpointCopy( pCurve, poSrc, poDst ); // All the identity transformations. |
304 | 0 | } |
305 | 2.08k | else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) |
306 | 0 | { |
307 | 0 | if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) |
308 | 0 | { |
309 | | // Copy X |
310 | 0 | peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
311 | 0 | SYMCRYPT_ASSERT( peX != NULL ); |
312 | |
|
313 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
314 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
315 | |
|
316 | 0 | SymCryptModElementCopy( pCurve->FMod, peX, peDst ); |
317 | | |
318 | | // Set Y to 0 |
319 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
320 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
321 | |
|
322 | 0 | SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch ); |
323 | 0 | } |
324 | 0 | else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE) |
325 | 0 | { |
326 | | // Copy X |
327 | 0 | peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
328 | 0 | SYMCRYPT_ASSERT( peX != NULL ); |
329 | |
|
330 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
331 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
332 | |
|
333 | 0 | SymCryptModElementCopy( pCurve->FMod, peX, peDst ); |
334 | | |
335 | | // Set Y to 1 |
336 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
337 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
338 | |
|
339 | 0 | SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch ); |
340 | | |
341 | | // Setting the normalized flag |
342 | 0 | poDst->normalized = TRUE; |
343 | 0 | } |
344 | 0 | else |
345 | 0 | { |
346 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
347 | 0 | goto cleanup; |
348 | 0 | } |
349 | 0 | } |
350 | 2.08k | else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) |
351 | 1.17k | { |
352 | 1.17k | if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) || |
353 | 1.17k | (coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) || |
354 | 1.17k | (coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) || |
355 | 1.17k | (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE) |
356 | 1.17k | ) |
357 | 1.17k | { |
358 | | // Copy X |
359 | 1.17k | peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
360 | 1.17k | SYMCRYPT_ASSERT( peX != NULL ); |
361 | | |
362 | 1.17k | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
363 | 1.17k | SYMCRYPT_ASSERT( peDst != NULL ); |
364 | | |
365 | 1.17k | SymCryptModElementCopy( pCurve->FMod, peX, peDst ); |
366 | | |
367 | 1.17k | if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) || |
368 | 1.17k | (coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) ) |
369 | 1.17k | { |
370 | | // Copy Y |
371 | 1.17k | peY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
372 | 1.17k | SYMCRYPT_ASSERT( peY != NULL ); |
373 | | |
374 | 1.17k | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
375 | 1.17k | SYMCRYPT_ASSERT( peDst != NULL ); |
376 | | |
377 | 1.17k | SymCryptModElementCopy( pCurve->FMod, peY, peDst ); |
378 | | |
379 | | // Set Z to 1 |
380 | 1.17k | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst ); |
381 | 1.17k | SYMCRYPT_ASSERT( peDst != NULL ); |
382 | | |
383 | 1.17k | SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch ); |
384 | | |
385 | 1.17k | if (coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) |
386 | 125 | { |
387 | | // T = x * y * z |
388 | 125 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst ); |
389 | 125 | SYMCRYPT_ASSERT( peDst != NULL ); |
390 | | |
391 | 125 | SymCryptModMul( pCurve->FMod, peX, peY, peDst, pbScratch, cbScratch ); |
392 | 125 | } |
393 | | |
394 | | // Setting the normalized flag |
395 | 1.17k | poDst->normalized = TRUE; |
396 | 1.17k | } |
397 | 0 | else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE) |
398 | 0 | { |
399 | | // Set Y to 1 (Ignore the second coordinate of the source point) |
400 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
401 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
402 | |
|
403 | 0 | SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch ); |
404 | | |
405 | | // Setting the normalized flag |
406 | 0 | poDst->normalized = TRUE; |
407 | 0 | } |
408 | 1.17k | } |
409 | 0 | else |
410 | 0 | { |
411 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
412 | 0 | goto cleanup; |
413 | 0 | } |
414 | 1.17k | } |
415 | 912 | else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) |
416 | 825 | { |
417 | 825 | if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) || |
418 | 825 | (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) ) |
419 | 825 | { |
420 | | // Creating temporaries |
421 | 2.47k | for (UINT32 i=0; i<2; i++) |
422 | 1.65k | { |
423 | 1.65k | peT[i] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod ); |
424 | 1.65k | SYMCRYPT_ASSERT( peT[i] != NULL); |
425 | | |
426 | 1.65k | pbScratch += pCurve->cbModElement; |
427 | 1.65k | } |
428 | | |
429 | 825 | cbScratch -= 2*pCurve->cbModElement; |
430 | | |
431 | | // Get the Z coordinate of the source point |
432 | 825 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
433 | 825 | SYMCRYPT_ASSERT( peSrc != NULL ); |
434 | | |
435 | | // Check if Z is equal to 0 (i.e. the point is the point at infinity) |
436 | 825 | if (SymCryptModElementIsZero(pCurve->FMod, peSrc)) |
437 | 0 | { |
438 | 0 | scError = SYMCRYPT_INCOMPATIBLE_FORMAT; |
439 | 0 | goto cleanup; |
440 | 0 | } |
441 | | |
442 | | // Calculation |
443 | | // T0 := 1 / Z |
444 | 825 | scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch ); |
445 | 825 | if( scError != SYMCRYPT_NO_ERROR ) |
446 | 0 | { |
447 | 0 | goto cleanup; |
448 | 0 | } |
449 | | |
450 | 825 | SymCryptModMul( pCurve->FMod, peT[0], peT[0], peT[1], pbScratch, cbScratch ); // T1 := T0 * T0 = 1/Z^2 |
451 | | |
452 | | // Get the X coordinates |
453 | 825 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
454 | 825 | SYMCRYPT_ASSERT( peSrc != NULL ); |
455 | | |
456 | 825 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
457 | 825 | SYMCRYPT_ASSERT( peDst != NULL ); |
458 | | |
459 | | // Set the new X |
460 | 825 | SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch ); // X2 := X * T1 = X/Z^2 |
461 | | |
462 | 825 | if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) |
463 | 541 | { |
464 | 541 | SymCryptModMul( pCurve->FMod, peT[0], peT[1], peT[1], pbScratch, cbScratch ); // T1 := T0 * T1 = 1/Z^3 |
465 | | |
466 | | // Get the Y coordinates |
467 | 541 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
468 | 541 | SYMCRYPT_ASSERT( peSrc != NULL ); |
469 | | |
470 | 541 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
471 | 541 | SYMCRYPT_ASSERT( peDst != NULL ); |
472 | | |
473 | | // Set the new Y |
474 | 541 | SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch ); // Y2 := Y * T1 = Y/Z^3 |
475 | 541 | } |
476 | 825 | } |
477 | 0 | else |
478 | 0 | { |
479 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
480 | 0 | goto cleanup; |
481 | 0 | } |
482 | 825 | } |
483 | 87 | else if ( coFrom == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE ) |
484 | 87 | { |
485 | | |
486 | 87 | if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) || |
487 | 87 | (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) ) |
488 | 87 | { |
489 | | // Creating temporary |
490 | 87 | peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod ); |
491 | 87 | SYMCRYPT_ASSERT( peT[0] != NULL); |
492 | 87 | pbScratch += pCurve->cbModElement; |
493 | 87 | cbScratch -= 2*pCurve->cbModElement; |
494 | | |
495 | | // Get the Z coordinate of the source point |
496 | 87 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc ); |
497 | 87 | SYMCRYPT_ASSERT( peSrc != NULL ); |
498 | | |
499 | | // Check if Z is equal to 0 (i.e. the point is the point at infinity) |
500 | 87 | if (SymCryptModElementIsZero(pCurve->FMod, peSrc)) |
501 | 0 | { |
502 | 0 | scError = SYMCRYPT_INCOMPATIBLE_FORMAT; |
503 | 0 | goto cleanup; |
504 | 0 | } |
505 | | |
506 | | // peT[0] = 1 / Z |
507 | 87 | scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch ); |
508 | 87 | if( scError != SYMCRYPT_NO_ERROR ) |
509 | 0 | { |
510 | 0 | goto cleanup; |
511 | 0 | } |
512 | | |
513 | | // Get the X coordinates |
514 | 87 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
515 | 87 | SYMCRYPT_ASSERT( peSrc != NULL ); |
516 | | |
517 | 87 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
518 | 87 | SYMCRYPT_ASSERT( peDst != NULL ); |
519 | | |
520 | | // x = X * (1 / Z) |
521 | 87 | SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch ); |
522 | | |
523 | 87 | if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) |
524 | 46 | { |
525 | | // Get the Y coordinates |
526 | 46 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
527 | 46 | SYMCRYPT_ASSERT( peSrc != NULL ); |
528 | | |
529 | 46 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
530 | 46 | SYMCRYPT_ASSERT( peDst != NULL ); |
531 | | |
532 | | // y = Y * (1 / Z) |
533 | 46 | SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch ); |
534 | 46 | } |
535 | 87 | } |
536 | 0 | else |
537 | 0 | { |
538 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
539 | 0 | goto cleanup; |
540 | 0 | } |
541 | 87 | } |
542 | 0 | else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE) |
543 | 0 | { |
544 | 0 | if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) || |
545 | 0 | (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) ) |
546 | 0 | { |
547 | | // Creating temporary |
548 | 0 | peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod ); |
549 | 0 | SYMCRYPT_ASSERT( peT[0] != NULL); |
550 | |
|
551 | 0 | pbScratch += pCurve->cbModElement; |
552 | 0 | cbScratch -= pCurve->cbModElement; |
553 | | |
554 | | // Get the Y coordinate of the source point |
555 | 0 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc ); |
556 | 0 | SYMCRYPT_ASSERT( peSrc != NULL ); |
557 | | |
558 | | // Check if Y is equal to 0 (i.e. the point is the point at infinity) |
559 | 0 | if (SymCryptModElementIsZero(pCurve->FMod, peSrc)) |
560 | 0 | { |
561 | 0 | scError = SYMCRYPT_INCOMPATIBLE_FORMAT; |
562 | 0 | goto cleanup; |
563 | 0 | } |
564 | | |
565 | | // Calculation |
566 | 0 | scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch ); // T0 := 1 / Y |
567 | 0 | if( scError != SYMCRYPT_NO_ERROR ) |
568 | 0 | { |
569 | 0 | goto cleanup; |
570 | 0 | } |
571 | | |
572 | | // Get the X coordinates |
573 | 0 | peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc ); |
574 | 0 | SYMCRYPT_ASSERT( peSrc != NULL ); |
575 | |
|
576 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst ); |
577 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
578 | | |
579 | | // Set the new X |
580 | 0 | SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch ); // X2 := X * T0 = X/Y |
581 | |
|
582 | 0 | if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) |
583 | 0 | { |
584 | | // Set Y to 0 |
585 | 0 | peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst ); |
586 | 0 | SYMCRYPT_ASSERT( peDst != NULL ); |
587 | |
|
588 | 0 | SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch ); |
589 | 0 | } |
590 | 0 | } |
591 | 0 | } |
592 | 0 | else |
593 | 0 | { |
594 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
595 | 0 | goto cleanup; |
596 | 0 | } |
597 | | |
598 | 2.08k | cleanup: |
599 | | |
600 | 2.08k | return scError; |
601 | 2.08k | } |
602 | | |
603 | | SYMCRYPT_ERROR |
604 | | SYMCRYPT_CALL |
605 | | SymCryptEcpointSetValue( |
606 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
607 | | _In_reads_bytes_(cbSrc) PCBYTE pbSrc, |
608 | | SIZE_T cbSrc, |
609 | | SYMCRYPT_NUMBER_FORMAT nformat, |
610 | | SYMCRYPT_ECPOINT_FORMAT eformat, |
611 | | _Out_ PSYMCRYPT_ECPOINT poDst, |
612 | | UINT32 flags, |
613 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
614 | | SIZE_T cbScratch ) |
615 | 1.17k | { |
616 | 1.17k | SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED; |
617 | 1.17k | PSYMCRYPT_MODELEMENT peTmp = NULL; // Temporary MODELEMENT handle |
618 | 1.17k | PSYMCRYPT_ECPOINT poLarge = NULL; // ECPOINT with the largest format available |
619 | 1.17k | UINT32 cbLarge = 0; |
620 | 1.17k | PSYMCRYPT_INT piTemp = NULL; |
621 | 1.17k | UINT32 cbTemp = 0; |
622 | 1.17k | UINT32 publicKeyDigits = SymCryptEcurveDigitsofFieldElement( pCurve ); |
623 | | |
624 | 1.17k | SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 ); |
625 | | |
626 | 1.17k | SYMCRYPT_ASSERT( pCurve->FMod != 0 ); |
627 | 1.17k | SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 ); |
628 | 1.17k | SYMCRYPT_ASSERT( pCurve->cbModElement != 0 ); |
629 | | |
630 | 1.17k | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) ); |
631 | | |
632 | | // Check that the buffer is of correct size |
633 | 1.17k | if ( cbSrc != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) ) |
634 | 0 | { |
635 | 0 | scError = SYMCRYPT_BUFFER_TOO_SMALL; |
636 | 0 | goto cleanup; |
637 | 0 | } |
638 | 1.17k | cbSrc = cbSrc / SymCryptEcpointFormatNumberofElements[ eformat ]; |
639 | | |
640 | 1.17k | cbTemp = SymCryptSizeofIntFromDigits( publicKeyDigits ); |
641 | 1.17k | SYMCRYPT_ASSERT( cbScratch > cbTemp ); |
642 | | |
643 | 1.17k | piTemp = SymCryptIntCreate( pbScratch, cbTemp, publicKeyDigits ); |
644 | | |
645 | | // Validate the coordinate of the input public key is less than the field modulus |
646 | 3.51k | for ( UINT32 i = 0; i < SymCryptEcpointFormatNumberofElements[eformat]; i++ ) |
647 | 2.34k | { |
648 | 2.34k | scError = SymCryptIntSetValue( pbSrc + i * cbSrc, cbSrc, nformat, piTemp ); |
649 | 2.34k | if (scError != SYMCRYPT_NO_ERROR) |
650 | 0 | { |
651 | 0 | goto cleanup; |
652 | 0 | } |
653 | | |
654 | 2.34k | if ( !SymCryptIntIsLessThan( piTemp, SymCryptIntFromModulus( pCurve->FMod ) ) ) |
655 | 0 | { |
656 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
657 | 0 | goto cleanup; |
658 | 0 | } |
659 | 2.34k | } |
660 | | |
661 | | // Create the large point |
662 | 1.17k | cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ); |
663 | 1.17k | SYMCRYPT_ASSERT( cbScratch > cbLarge ); |
664 | 1.17k | poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ); |
665 | 1.17k | if ( poLarge == NULL ) |
666 | 0 | { |
667 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
668 | 0 | goto cleanup; |
669 | 0 | } |
670 | | |
671 | | // Setting the point coordinates into the big point |
672 | 3.51k | for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++) |
673 | 2.34k | { |
674 | 2.34k | peTmp = (PSYMCRYPT_MODELEMENT)((PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i )); |
675 | 2.34k | if ( peTmp == NULL ) |
676 | 0 | { |
677 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
678 | 0 | goto cleanup; |
679 | 0 | } |
680 | | |
681 | 2.34k | scError = SymCryptModElementSetValue( |
682 | 2.34k | pbSrc, |
683 | 2.34k | cbSrc, |
684 | 2.34k | nformat, |
685 | 2.34k | pCurve->FMod, |
686 | 2.34k | peTmp, |
687 | 2.34k | pbScratch + cbLarge, |
688 | 2.34k | cbScratch - cbLarge ); |
689 | 2.34k | if ( scError != SYMCRYPT_NO_ERROR ) |
690 | 0 | { |
691 | 0 | goto cleanup; |
692 | 0 | } |
693 | 2.34k | pbSrc += cbSrc; |
694 | 2.34k | } |
695 | | |
696 | | // Transform the big point into the destination point |
697 | 1.17k | scError = SymCryptEcpointTransform( pCurve, poLarge, poDst, eformat, TRUE, flags, pbScratch + cbLarge, cbScratch - cbLarge); |
698 | | |
699 | 1.17k | cleanup: |
700 | 1.17k | return scError; |
701 | 1.17k | } |
702 | | |
703 | | SYMCRYPT_ERROR |
704 | | SYMCRYPT_CALL |
705 | | SymCryptEcpointGetValue( |
706 | | _In_ PCSYMCRYPT_ECURVE pCurve, |
707 | | _In_ PCSYMCRYPT_ECPOINT poSrc, |
708 | | SYMCRYPT_NUMBER_FORMAT nformat, |
709 | | SYMCRYPT_ECPOINT_FORMAT eformat, |
710 | | _Out_writes_bytes_(cbDst) PBYTE pbDst, |
711 | | SIZE_T cbDst, |
712 | | UINT32 flags, |
713 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
714 | | SIZE_T cbScratch ) |
715 | 912 | { |
716 | 912 | SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED; |
717 | 912 | PSYMCRYPT_MODELEMENT peTmp = NULL; // Temporary MODELEMENT handle |
718 | 912 | PSYMCRYPT_ECPOINT poLarge = NULL; // ECPOINT with the largest format available |
719 | 912 | UINT32 cbLarge = 0; |
720 | 912 | SIZE_T cbDstElem; |
721 | | |
722 | 912 | SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 ); |
723 | 912 | SYMCRYPT_ASSERT( pCurve->FMod != 0 ); |
724 | 912 | SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 ); |
725 | 912 | SYMCRYPT_ASSERT( pCurve->cbModElement != 0 ); |
726 | | |
727 | 912 | SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) ); |
728 | | |
729 | | // Check that the buffer is of correct size |
730 | 912 | if ( cbDst != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) ) |
731 | 0 | { |
732 | 0 | scError = SYMCRYPT_BUFFER_TOO_SMALL; |
733 | 0 | goto cleanup; |
734 | 0 | } |
735 | 912 | SYMCRYPT_ASSERT( SymCryptEcpointFormatNumberofElements[ eformat ] > 0 ); |
736 | 912 | cbDstElem = cbDst / SymCryptEcpointFormatNumberofElements[ eformat ]; |
737 | | |
738 | | // Create the big point |
739 | 912 | cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ); |
740 | 912 | SYMCRYPT_ASSERT( cbScratch > cbLarge ); |
741 | 912 | poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ); |
742 | 912 | if ( poLarge == NULL ) |
743 | 0 | { |
744 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
745 | 0 | goto cleanup; |
746 | 0 | } |
747 | | |
748 | | // Transform the source point into the big point if needed |
749 | 912 | scError = SymCryptEcpointTransform( pCurve, poSrc, poLarge, eformat, FALSE, flags, pbScratch + cbLarge, cbScratch - cbLarge); |
750 | 912 | if (scError != SYMCRYPT_NO_ERROR) |
751 | 0 | { |
752 | 0 | goto cleanup; |
753 | 0 | } |
754 | | |
755 | | // Getting the point coordinates into the destination buffer |
756 | 2.41k | for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++) |
757 | 1.49k | { |
758 | 1.49k | SYMCRYPT_ASSERT( cbDst >= cbDstElem ); |
759 | 1.49k | peTmp = (PSYMCRYPT_MODELEMENT)( (PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i ) ); |
760 | 1.49k | if ( peTmp == NULL ) |
761 | 0 | { |
762 | 0 | scError = SYMCRYPT_INVALID_BLOB; |
763 | 0 | goto cleanup; |
764 | 0 | } |
765 | | |
766 | 1.49k | scError = SymCryptModElementGetValue( |
767 | 1.49k | pCurve->FMod, |
768 | 1.49k | peTmp, |
769 | 1.49k | pbDst, |
770 | 1.49k | cbDstElem, |
771 | 1.49k | nformat, |
772 | 1.49k | pbScratch + cbLarge, |
773 | 1.49k | cbScratch - cbLarge ); |
774 | 1.49k | if ( scError != SYMCRYPT_NO_ERROR ) |
775 | 0 | { |
776 | 0 | goto cleanup; |
777 | 0 | } |
778 | 1.49k | pbDst += cbDstElem; |
779 | 1.49k | cbDst -= cbDstElem; |
780 | 1.49k | } |
781 | | |
782 | 912 | cleanup: |
783 | | |
784 | 912 | return scError; |
785 | 912 | } |