Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/ecpoint.c
15010 views
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
{
23
SYMCRYPT_ASSERT(numOfCoordinates > 0);
24
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
if( (numOfCoordinates == 0) || (numOfCoordinates > SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH) )
30
{
31
return 0;
32
}
33
34
// Since the maximum number of coordinates is 4 this result is bounded
35
// by 4*2^17 + overhead ~ 2^20
36
return sizeof(SYMCRYPT_ECPOINT) + numOfCoordinates * cbModElement;
37
}
38
39
UINT32
40
SYMCRYPT_CALL
41
SymCryptSizeofEcpointFromCurve( PCSYMCRYPT_ECURVE pCurve )
42
{
43
// Same bound as SymCryptSizeofEcpointEx
44
return SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) );
45
}
46
47
PSYMCRYPT_ECPOINT
48
SYMCRYPT_CALL
49
SymCryptEcpointAllocate( _In_ PCSYMCRYPT_ECURVE pCurve )
50
{
51
PVOID p = NULL;
52
SIZE_T cb;
53
PSYMCRYPT_ECPOINT res = NULL;
54
55
cb = SymCryptSizeofEcpointFromCurve( pCurve );
56
57
if ( cb != 0 )
58
{
59
p = SymCryptCallbackAlloc( cb );
60
}
61
62
if ( p==NULL )
63
{
64
goto cleanup;
65
}
66
67
res = SymCryptEcpointCreate( p, cb, pCurve );
68
69
cleanup:
70
return res;
71
}
72
73
VOID
74
SYMCRYPT_CALL
75
SymCryptEcpointFree(
76
_In_ PCSYMCRYPT_ECURVE pCurve,
77
_Out_ PSYMCRYPT_ECPOINT poDst )
78
{
79
SYMCRYPT_CHECK_MAGIC( poDst );
80
SymCryptEcpointWipe( pCurve, poDst );
81
SymCryptCallbackFree( poDst );
82
}
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
{
92
PSYMCRYPT_ECPOINT poPoint = NULL;
93
94
PSYMCRYPT_MODELEMENT pmTmp = NULL;
95
UINT32 cbModElement = pCurve->cbModElement;
96
97
PBYTE pbBufferEnd = pbBuffer + cbBuffer;
98
UNREFERENCED_PARAMETER( pbBufferEnd ); // only referenced in an ASSERT...
99
100
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
101
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
102
SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofEcpointEx( pCurve->cbModElement, numOfCoordinates ) );
103
if ( cbBuffer == 0 || numOfCoordinates == 0 )
104
{
105
goto cleanup;
106
}
107
108
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
109
110
poPoint = (PSYMCRYPT_ECPOINT) pbBuffer;
111
112
pbBuffer += sizeof(SYMCRYPT_ECPOINT);
113
114
// Setting the point coordinates
115
for (UINT32 i=0; i<numOfCoordinates; i++)
116
{
117
SYMCRYPT_ASSERT( pbBuffer + cbModElement <= pbBufferEnd );
118
pmTmp = SymCryptModElementCreate( pbBuffer, cbModElement, pCurve->FMod );
119
if ( pmTmp == NULL )
120
{
121
poPoint = NULL;
122
goto cleanup;
123
}
124
pbBuffer += cbModElement;
125
}
126
127
// Setting the normalized flag
128
poPoint->normalized = FALSE;
129
130
// Setting the curve
131
poPoint->pCurve = pCurve;
132
133
// Setting the magic
134
SYMCRYPT_SET_MAGIC( poPoint );
135
136
cleanup:
137
return poPoint;
138
}
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
{
147
148
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
149
150
return SymCryptEcpointCreateEx( pbBuffer, cbBuffer, pCurve, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) );
151
}
152
153
PSYMCRYPT_ECPOINT
154
SYMCRYPT_CALL
155
SymCryptEcpointRetrieveHandle( _In_ PBYTE pbBuffer )
156
{
157
SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
158
159
return (PSYMCRYPT_ECPOINT) pbBuffer;
160
}
161
162
VOID
163
SYMCRYPT_CALL
164
SymCryptEcpointWipe( _In_ PCSYMCRYPT_ECURVE pCurve, _Out_ PSYMCRYPT_ECPOINT poDst )
165
{
166
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
167
168
// Wipe the whole structure in one go.
169
SymCryptWipe( poDst, SymCryptSizeofEcpointFromCurve( pCurve ) );
170
}
171
172
VOID
173
SymCryptEcpointCopy(
174
_In_ PCSYMCRYPT_ECURVE pCurve,
175
_In_ PCSYMCRYPT_ECPOINT poSrc,
176
_Out_ PSYMCRYPT_ECPOINT poDst )
177
{
178
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
179
180
if( poSrc != poDst )
181
{
182
// Unconditionally set the normalization state of destination to source
183
poDst->normalized = poSrc->normalized;
184
185
memcpy(poDst + 1, poSrc + 1, SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits * SYMCRYPT_FDEF_DIGIT_SIZE);
186
}
187
}
188
189
VOID
190
SymCryptEcpointMaskedCopy(
191
_In_ PCSYMCRYPT_ECURVE pCurve,
192
_In_ PCSYMCRYPT_ECPOINT poSrc,
193
_Out_ PSYMCRYPT_ECPOINT poDst,
194
UINT32 mask )
195
{
196
SYMCRYPT_ASSERT( (mask == 0) || (mask == 0xffffffff) );
197
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
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
SymCryptFdefMaskedCopy((PCBYTE)poSrc + sizeof(SYMCRYPT_ECPOINT), (PBYTE)poDst + sizeof(SYMCRYPT_ECPOINT), SYMCRYPT_INTERNAL_NUMOF_COORDINATES(pCurve->eCoordinates) * pCurve->FModDigits, mask );
206
}
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
{
232
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
233
234
PSYMCRYPT_MODELEMENT peSrc = NULL;
235
PSYMCRYPT_MODELEMENT peDst = NULL;
236
PSYMCRYPT_MODELEMENT peX = NULL;
237
PSYMCRYPT_MODELEMENT peY = NULL;
238
239
SYMCRYPT_ECPOINT_COORDINATES coFrom = SYMCRYPT_ECPOINT_COORDINATES_INVALID;
240
SYMCRYPT_ECPOINT_COORDINATES coTo = SYMCRYPT_ECPOINT_COORDINATES_INVALID;
241
242
PSYMCRYPT_MODELEMENT peT[2] = { 0 }; // Temporaries
243
244
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
245
SYMCRYPT_ASSERT( SymCryptEcurveIsSame(pCurve, poSrc->pCurve) && SymCryptEcurveIsSame(pCurve, poDst->pCurve) );
246
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ),
247
SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->FModDigits )) +
248
2 * pCurve->cbModElement );
249
250
// Get the assumed representation from the external format
251
switch (eformat)
252
{
253
case (SYMCRYPT_ECPOINT_FORMAT_X):
254
coFrom = SYMCRYPT_ECPOINT_COORDINATES_SINGLE;
255
break;
256
case (SYMCRYPT_ECPOINT_FORMAT_XY):
257
coFrom = SYMCRYPT_ECPOINT_COORDINATES_AFFINE;
258
break;
259
default:
260
scError = SYMCRYPT_INVALID_ARGUMENT;
261
goto cleanup;
262
}
263
264
// Find out whether we are setting or getting the value of the ECPOINT
265
if (setValue)
266
{
267
coTo = pCurve->eCoordinates;
268
}
269
else
270
{
271
coTo = coFrom;
272
coFrom = pCurve->eCoordinates;
273
}
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
if ( coFrom == coTo )
302
{
303
SymCryptEcpointCopy( pCurve, poSrc, poDst ); // All the identity transformations.
304
}
305
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE)
306
{
307
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
308
{
309
// Copy X
310
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
311
SYMCRYPT_ASSERT( peX != NULL );
312
313
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
314
SYMCRYPT_ASSERT( peDst != NULL );
315
316
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
317
318
// Set Y to 0
319
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
320
SYMCRYPT_ASSERT( peDst != NULL );
321
322
SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch );
323
}
324
else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
325
{
326
// Copy X
327
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
328
SYMCRYPT_ASSERT( peX != NULL );
329
330
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
331
SYMCRYPT_ASSERT( peDst != NULL );
332
333
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
334
335
// Set Y to 1
336
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
337
SYMCRYPT_ASSERT( peDst != NULL );
338
339
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
340
341
// Setting the normalized flag
342
poDst->normalized = TRUE;
343
}
344
else
345
{
346
scError = SYMCRYPT_NOT_IMPLEMENTED;
347
goto cleanup;
348
}
349
}
350
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
351
{
352
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
353
(coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) ||
354
(coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) ||
355
(coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
356
)
357
{
358
// Copy X
359
peX = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
360
SYMCRYPT_ASSERT( peX != NULL );
361
362
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
363
SYMCRYPT_ASSERT( peDst != NULL );
364
365
SymCryptModElementCopy( pCurve->FMod, peX, peDst );
366
367
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN) ||
368
(coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE) )
369
{
370
// Copy Y
371
peY = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
372
SYMCRYPT_ASSERT( peY != NULL );
373
374
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
375
SYMCRYPT_ASSERT( peDst != NULL );
376
377
SymCryptModElementCopy( pCurve->FMod, peY, peDst );
378
379
// Set Z to 1
380
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poDst );
381
SYMCRYPT_ASSERT( peDst != NULL );
382
383
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
384
385
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE)
386
{
387
// T = x * y * z
388
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 3, pCurve, poDst );
389
SYMCRYPT_ASSERT( peDst != NULL );
390
391
SymCryptModMul( pCurve->FMod, peX, peY, peDst, pbScratch, cbScratch );
392
}
393
394
// Setting the normalized flag
395
poDst->normalized = TRUE;
396
}
397
else if (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
398
{
399
// Set Y to 1 (Ignore the second coordinate of the source point)
400
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
401
SYMCRYPT_ASSERT( peDst != NULL );
402
403
SymCryptModElementSetValueUint32( 1, pCurve->FMod, peDst, pbScratch, cbScratch );
404
405
// Setting the normalized flag
406
poDst->normalized = TRUE;
407
}
408
}
409
else
410
{
411
scError = SYMCRYPT_NOT_IMPLEMENTED;
412
goto cleanup;
413
}
414
}
415
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN)
416
{
417
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
418
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
419
{
420
// Creating temporaries
421
for (UINT32 i=0; i<2; i++)
422
{
423
peT[i] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
424
SYMCRYPT_ASSERT( peT[i] != NULL);
425
426
pbScratch += pCurve->cbModElement;
427
}
428
429
cbScratch -= 2*pCurve->cbModElement;
430
431
// Get the Z coordinate of the source point
432
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
433
SYMCRYPT_ASSERT( peSrc != NULL );
434
435
// Check if Z is equal to 0 (i.e. the point is the point at infinity)
436
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
437
{
438
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
439
goto cleanup;
440
}
441
442
// Calculation
443
// T0 := 1 / Z
444
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch );
445
if( scError != SYMCRYPT_NO_ERROR )
446
{
447
goto cleanup;
448
}
449
450
SymCryptModMul( pCurve->FMod, peT[0], peT[0], peT[1], pbScratch, cbScratch ); // T1 := T0 * T0 = 1/Z^2
451
452
// Get the X coordinates
453
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
454
SYMCRYPT_ASSERT( peSrc != NULL );
455
456
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
457
SYMCRYPT_ASSERT( peDst != NULL );
458
459
// Set the new X
460
SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch ); // X2 := X * T1 = X/Z^2
461
462
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
463
{
464
SymCryptModMul( pCurve->FMod, peT[0], peT[1], peT[1], pbScratch, cbScratch ); // T1 := T0 * T1 = 1/Z^3
465
466
// Get the Y coordinates
467
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
468
SYMCRYPT_ASSERT( peSrc != NULL );
469
470
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
471
SYMCRYPT_ASSERT( peDst != NULL );
472
473
// Set the new Y
474
SymCryptModMul( pCurve->FMod, peSrc, peT[1], peDst, pbScratch, cbScratch ); // Y2 := Y * T1 = Y/Z^3
475
}
476
}
477
else
478
{
479
scError = SYMCRYPT_NOT_IMPLEMENTED;
480
goto cleanup;
481
}
482
}
483
else if ( coFrom == SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE )
484
{
485
486
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
487
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
488
{
489
// Creating temporary
490
peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
491
SYMCRYPT_ASSERT( peT[0] != NULL);
492
pbScratch += pCurve->cbModElement;
493
cbScratch -= 2*pCurve->cbModElement;
494
495
// Get the Z coordinate of the source point
496
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 2, pCurve, poSrc );
497
SYMCRYPT_ASSERT( peSrc != NULL );
498
499
// Check if Z is equal to 0 (i.e. the point is the point at infinity)
500
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
501
{
502
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
503
goto cleanup;
504
}
505
506
// peT[0] = 1 / Z
507
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch );
508
if( scError != SYMCRYPT_NO_ERROR )
509
{
510
goto cleanup;
511
}
512
513
// Get the X coordinates
514
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
515
SYMCRYPT_ASSERT( peSrc != NULL );
516
517
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
518
SYMCRYPT_ASSERT( peDst != NULL );
519
520
// x = X * (1 / Z)
521
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch );
522
523
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
524
{
525
// Get the Y coordinates
526
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
527
SYMCRYPT_ASSERT( peSrc != NULL );
528
529
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
530
SYMCRYPT_ASSERT( peDst != NULL );
531
532
// y = Y * (1 / Z)
533
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch );
534
}
535
}
536
else
537
{
538
scError = SYMCRYPT_NOT_IMPLEMENTED;
539
goto cleanup;
540
}
541
}
542
else if (coFrom == SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE)
543
{
544
if ( (coTo == SYMCRYPT_ECPOINT_COORDINATES_SINGLE) ||
545
(coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE) )
546
{
547
// Creating temporary
548
peT[0] = SymCryptModElementCreate( pbScratch, pCurve->cbModElement, pCurve->FMod );
549
SYMCRYPT_ASSERT( peT[0] != NULL);
550
551
pbScratch += pCurve->cbModElement;
552
cbScratch -= pCurve->cbModElement;
553
554
// Get the Y coordinate of the source point
555
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poSrc );
556
SYMCRYPT_ASSERT( peSrc != NULL );
557
558
// Check if Y is equal to 0 (i.e. the point is the point at infinity)
559
if (SymCryptModElementIsZero(pCurve->FMod, peSrc))
560
{
561
scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
562
goto cleanup;
563
}
564
565
// Calculation
566
scError = SymCryptModInv( pCurve->FMod, peSrc, peT[0], flags, pbScratch, cbScratch ); // T0 := 1 / Y
567
if( scError != SYMCRYPT_NO_ERROR )
568
{
569
goto cleanup;
570
}
571
572
// Get the X coordinates
573
peSrc = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poSrc );
574
SYMCRYPT_ASSERT( peSrc != NULL );
575
576
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 0, pCurve, poDst );
577
SYMCRYPT_ASSERT( peDst != NULL );
578
579
// Set the new X
580
SymCryptModMul( pCurve->FMod, peSrc, peT[0], peDst, pbScratch, cbScratch ); // X2 := X * T0 = X/Y
581
582
if (coTo == SYMCRYPT_ECPOINT_COORDINATES_AFFINE)
583
{
584
// Set Y to 0
585
peDst = SYMCRYPT_INTERNAL_ECPOINT_COORDINATE( 1, pCurve, poDst );
586
SYMCRYPT_ASSERT( peDst != NULL );
587
588
SymCryptModElementSetValueUint32( 0, pCurve->FMod, peDst, pbScratch, cbScratch );
589
}
590
}
591
}
592
else
593
{
594
scError = SYMCRYPT_NOT_IMPLEMENTED;
595
goto cleanup;
596
}
597
598
cleanup:
599
600
return scError;
601
}
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
{
616
SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED;
617
PSYMCRYPT_MODELEMENT peTmp = NULL; // Temporary MODELEMENT handle
618
PSYMCRYPT_ECPOINT poLarge = NULL; // ECPOINT with the largest format available
619
UINT32 cbLarge = 0;
620
PSYMCRYPT_INT piTemp = NULL;
621
UINT32 cbTemp = 0;
622
UINT32 publicKeyDigits = SymCryptEcurveDigitsofFieldElement( pCurve );
623
624
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
625
626
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
627
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
628
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
629
630
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
631
632
// Check that the buffer is of correct size
633
if ( cbSrc != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) )
634
{
635
scError = SYMCRYPT_BUFFER_TOO_SMALL;
636
goto cleanup;
637
}
638
cbSrc = cbSrc / SymCryptEcpointFormatNumberofElements[ eformat ];
639
640
cbTemp = SymCryptSizeofIntFromDigits( publicKeyDigits );
641
SYMCRYPT_ASSERT( cbScratch > cbTemp );
642
643
piTemp = SymCryptIntCreate( pbScratch, cbTemp, publicKeyDigits );
644
645
// Validate the coordinate of the input public key is less than the field modulus
646
for ( UINT32 i = 0; i < SymCryptEcpointFormatNumberofElements[eformat]; i++ )
647
{
648
scError = SymCryptIntSetValue( pbSrc + i * cbSrc, cbSrc, nformat, piTemp );
649
if (scError != SYMCRYPT_NO_ERROR)
650
{
651
goto cleanup;
652
}
653
654
if ( !SymCryptIntIsLessThan( piTemp, SymCryptIntFromModulus( pCurve->FMod ) ) )
655
{
656
scError = SYMCRYPT_INVALID_ARGUMENT;
657
goto cleanup;
658
}
659
}
660
661
// Create the large point
662
cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
663
SYMCRYPT_ASSERT( cbScratch > cbLarge );
664
poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
665
if ( poLarge == NULL )
666
{
667
scError = SYMCRYPT_INVALID_BLOB;
668
goto cleanup;
669
}
670
671
// Setting the point coordinates into the big point
672
for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++)
673
{
674
peTmp = (PSYMCRYPT_MODELEMENT)((PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i ));
675
if ( peTmp == NULL )
676
{
677
scError = SYMCRYPT_INVALID_BLOB;
678
goto cleanup;
679
}
680
681
scError = SymCryptModElementSetValue(
682
pbSrc,
683
cbSrc,
684
nformat,
685
pCurve->FMod,
686
peTmp,
687
pbScratch + cbLarge,
688
cbScratch - cbLarge );
689
if ( scError != SYMCRYPT_NO_ERROR )
690
{
691
goto cleanup;
692
}
693
pbSrc += cbSrc;
694
}
695
696
// Transform the big point into the destination point
697
scError = SymCryptEcpointTransform( pCurve, poLarge, poDst, eformat, TRUE, flags, pbScratch + cbLarge, cbScratch - cbLarge);
698
699
cleanup:
700
return scError;
701
}
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
{
716
SYMCRYPT_ERROR scError = SYMCRYPT_NOT_IMPLEMENTED;
717
PSYMCRYPT_MODELEMENT peTmp = NULL; // Temporary MODELEMENT handle
718
PSYMCRYPT_ECPOINT poLarge = NULL; // ECPOINT with the largest format available
719
UINT32 cbLarge = 0;
720
SIZE_T cbDstElem;
721
722
SYMCRYPT_ASSERT( (flags & ~SYMCRYPT_FLAG_DATA_PUBLIC) == 0 );
723
SYMCRYPT_ASSERT( pCurve->FMod != 0 );
724
SYMCRYPT_ASSERT( pCurve->eCoordinates != 0 );
725
SYMCRYPT_ASSERT( pCurve->cbModElement != 0 );
726
727
SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
728
729
// Check that the buffer is of correct size
730
if ( cbDst != SymCryptEcpointFormatNumberofElements[ eformat ] * SymCryptEcurveSizeofFieldElement( pCurve ) )
731
{
732
scError = SYMCRYPT_BUFFER_TOO_SMALL;
733
goto cleanup;
734
}
735
SYMCRYPT_ASSERT( SymCryptEcpointFormatNumberofElements[ eformat ] > 0 );
736
cbDstElem = cbDst / SymCryptEcpointFormatNumberofElements[ eformat ];
737
738
// Create the big point
739
cbLarge = SymCryptSizeofEcpointEx( pCurve->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
740
SYMCRYPT_ASSERT( cbScratch > cbLarge );
741
poLarge = SymCryptEcpointCreateEx( pbScratch, cbLarge, pCurve, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH );
742
if ( poLarge == NULL )
743
{
744
scError = SYMCRYPT_INVALID_BLOB;
745
goto cleanup;
746
}
747
748
// Transform the source point into the big point if needed
749
scError = SymCryptEcpointTransform( pCurve, poSrc, poLarge, eformat, FALSE, flags, pbScratch + cbLarge, cbScratch - cbLarge);
750
if (scError != SYMCRYPT_NO_ERROR)
751
{
752
goto cleanup;
753
}
754
755
// Getting the point coordinates into the destination buffer
756
for (UINT32 i=0; i<SymCryptEcpointFormatNumberofElements[eformat]; i++)
757
{
758
SYMCRYPT_ASSERT( cbDst >= cbDstElem );
759
peTmp = (PSYMCRYPT_MODELEMENT)( (PBYTE)poLarge + SYMCRYPT_INTERNAL_ECPOINT_COORDINATE_OFFSET( pCurve, i ) );
760
if ( peTmp == NULL )
761
{
762
scError = SYMCRYPT_INVALID_BLOB;
763
goto cleanup;
764
}
765
766
scError = SymCryptModElementGetValue(
767
pCurve->FMod,
768
peTmp,
769
pbDst,
770
cbDstElem,
771
nformat,
772
pbScratch + cbLarge,
773
cbScratch - cbLarge );
774
if ( scError != SYMCRYPT_NO_ERROR )
775
{
776
goto cleanup;
777
}
778
pbDst += cbDstElem;
779
cbDst -= cbDstElem;
780
}
781
782
cleanup:
783
784
return scError;
785
}
786
787