Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/ecurve.c
15010 views
1
//
2
// ecurve.c Ecurve functions
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
// Approximate number of consecutive operations with the modulus and the
11
// (sub)group order of the curve. These numbers can trigger special optimizations
12
// on the underlying code, e.g. use of Montgomery multiplication or not.
13
#define SYMCRYPT_INTERNAL_ECURVE_MODULUS_NUMOF_OPERATIONS( _bitsize ) ( 100 * (_bitsize) )
14
#define SYMCRYPT_INTERNAL_ECURVE_GROUP_ORDER_NUMOF_OPERATIONS ( 1 )
15
16
// We limit the max size of the elliptic curve to avoid denial-of-service attacks when
17
// an attacker sends a curve specification.
18
// Elliptic curve operations are O(n^3) in the curve size. Theoretically SymCrypt supports
19
// values up to 2^20 bits at the moment, so that is 2^12 times more than a typical curve size
20
// of 256 bits. Operations are then 2^36 times slower, and a single operation could take months.
21
// Our largest curve is 521 bits, and we won't see curves > 1024 bits for a while yet.
22
#define SYMCRYPT_INTERNAL_MAX_ECURVE_SIZE (1024)
23
24
// Private struct which records the sizes of various different parts of the elliptic curve
25
// structure.
26
typedef struct _SYMCRYPT_ECURVE_SIZES {
27
UINT32 nDigitsFieldLength;
28
UINT32 nDigitsSubgroupOrder;
29
UINT32 nDigitsCoFactor;
30
UINT32 cbAlloc; // Length of the whole curve buffer
31
UINT32 cbModulus;
32
UINT32 cbModElement;
33
UINT32 cbEcpoint;
34
UINT32 cbSubgroupOrder;
35
UINT32 cbCoFactor;
36
UINT32 cbScratch;
37
SYMCRYPT_ECPOINT_COORDINATES eCoordinates;
38
} SYMCRYPT_ECURVE_SIZES, *PSYMCRYPT_ECURVE_SIZES;
39
typedef const SYMCRYPT_ECURVE_SIZES * PCSYMCRYPT_ECURVE_SIZES;
40
41
// Helper function which validates curve parameters and computes various buffer sizes.
42
static
43
BOOLEAN
44
SymCryptEcurveValidateAndComputeSizes(
45
_In_ PCSYMCRYPT_ECURVE_PARAMS pParams,
46
_Out_ PSYMCRYPT_ECURVE_SIZES pSizes )
47
{
48
BOOLEAN fSuccess = FALSE;
49
50
// Check that the parameters are well formatted
51
SYMCRYPT_ASSERT( pParams != NULL );
52
SYMCRYPT_ASSERT( (pParams->version == 1) || (pParams->version == 2) );
53
SYMCRYPT_ASSERT( pParams->cbFieldLength != 0 );
54
SYMCRYPT_ASSERT( pParams->cbSubgroupOrder != 0 );
55
SYMCRYPT_ASSERT( pParams->cbCofactor != 0 );
56
SYMCRYPT_ASSERT( (pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS) ||
57
(pParams->type == SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS) ||
58
(pParams->type == SYMCRYPT_ECURVE_TYPE_MONTGOMERY) );
59
60
// Reject inputs that are wildly big to avoid denial-of-service attacks.
61
if ( pParams->cbFieldLength > SYMCRYPT_INTERNAL_MAX_ECURVE_SIZE/8 ||
62
pParams->cbSubgroupOrder > SYMCRYPT_INTERNAL_MAX_ECURVE_SIZE / 8 + 1 || // subgroup can be > field prime
63
pParams->cbCofactor > 2 || // We support co-factor = 256
64
pParams->cbSeed > 256 )
65
{
66
goto cleanup;
67
}
68
69
// Getting the # of digits of the various parameters
70
pSizes->nDigitsFieldLength = SymCryptDigitsFromBits( pParams->cbFieldLength * 8 );
71
pSizes->nDigitsSubgroupOrder = SymCryptDigitsFromBits( pParams->cbSubgroupOrder * 8 );
72
pSizes->nDigitsCoFactor = SymCryptDigitsFromBits( pParams->cbCofactor * 8 );
73
74
// -----------------------------------------------
75
// Getting the byte sizes of different objects
76
// -----------------------------------------------
77
pSizes->cbModulus = SymCryptSizeofModulusFromDigits( pSizes->nDigitsFieldLength );
78
pSizes->cbSubgroupOrder = SymCryptSizeofModulusFromDigits( pSizes->nDigitsSubgroupOrder );
79
pSizes->cbCoFactor = SymCryptSizeofIntFromDigits( pSizes->nDigitsCoFactor );
80
81
pSizes->cbModElement = SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pParams->cbFieldLength * 8 );
82
83
// EcPoint: The curve is not initialized yet, we call the helper function.
84
// It depends on the default format of each curve type
85
switch (pParams->type)
86
{
87
case (SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS):
88
pSizes->eCoordinates = SYMCRYPT_ECPOINT_COORDINATES_JACOBIAN;
89
break;
90
case (SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS):
91
pSizes->eCoordinates = SYMCRYPT_ECPOINT_COORDINATES_EXTENDED_PROJECTIVE;
92
break;
93
case (SYMCRYPT_ECURVE_TYPE_MONTGOMERY):
94
pSizes->eCoordinates = SYMCRYPT_ECPOINT_COORDINATES_SINGLE_PROJECTIVE;
95
break;
96
default:
97
goto cleanup;
98
}
99
100
pSizes->cbEcpoint = SymCryptSizeofEcpointEx( pSizes->cbModElement, SYMCRYPT_INTERNAL_NUMOF_COORDINATES( pSizes->eCoordinates ) );
101
// -----------------------------------------------
102
103
// Compute memory needed for the curve
104
//
105
// From symcrypt_internal.h we have:
106
// - sizeof results are upper bounded by 2^19
107
// Thus the following calculation does not overflow cbAlloc.
108
//
109
pSizes->cbAlloc = sizeof( SYMCRYPT_ECURVE ) +
110
pSizes->cbModulus +
111
2 * pSizes->cbModElement +
112
pSizes->cbSubgroupOrder +
113
pSizes->cbCoFactor;
114
115
if ( (pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS) ||
116
(pParams->type == SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS) )
117
{
118
// If the curve's type is short Weierstrass allocate space for 2^(w-2) ECPOINTs
119
// at the end of the curve's structure, where w is the width of the window.
120
//
121
// Note: The window width is fixed now. In later versions we can pass it in as a parameter.
122
// SYMCRYPT_ASSERT( (1 << (SYMCRYPT_ECURVE_SW_DEF_WINDOW-2)) <= SYMCRYPT_ECURVE_SW_MAX_NPRECOMP_POINTS );
123
pSizes->cbAlloc += (1 << (SYMCRYPT_ECURVE_SW_DEF_WINDOW-2))*pSizes->cbEcpoint;
124
}
125
else
126
{
127
// Otherwise just allocate space for just the distinguished point
128
pSizes->cbAlloc += pSizes->cbEcpoint;
129
}
130
131
// Compute memory needed for internal scratch space
132
// EcpointSetValue and SymCryptOfflinePrecomputation
133
134
//
135
// From symcrypt_internal.h we have:
136
// - sizeof results are upper bounded by 2^19
137
// - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
138
// - SymCryptSizeofEcpointEx is bounded by 2^20
139
// Thus the following calculation does not overflow cbScratch.
140
//
141
pSizes->cbScratch = SymCryptSizeofEcpointEx( pSizes->cbModElement, SYMCRYPT_ECPOINT_FORMAT_MAX_LENGTH ) +
142
8 * pSizes->cbModElement +
143
SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pSizes->nDigitsFieldLength ),
144
SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pSizes->nDigitsFieldLength ) );
145
// IntToModulus( FMod and GOrd )
146
pSizes->cbScratch = SYMCRYPT_MAX( pSizes->cbScratch,
147
SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS( SYMCRYPT_MAX(pSizes->nDigitsFieldLength, pSizes->nDigitsSubgroupOrder) ) );
148
// ModElementSetValue( FMod )
149
pSizes->cbScratch = SYMCRYPT_MAX( pSizes->cbScratch,
150
SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pSizes->nDigitsFieldLength ) );
151
152
fSuccess = TRUE;
153
154
cleanup:
155
return fSuccess;
156
}
157
158
BOOLEAN
159
SYMCRYPT_CALL
160
SymCryptEcurveBufferSizesFromParams(
161
_In_ PCSYMCRYPT_ECURVE_PARAMS pParams,
162
_Out_ SIZE_T * pcbCurve,
163
_Out_ SIZE_T * pcbScratch )
164
{
165
BOOLEAN fSuccess = FALSE;
166
SYMCRYPT_ECURVE_SIZES sizes;
167
168
if ( !SymCryptEcurveValidateAndComputeSizes( pParams, &sizes ))
169
{
170
goto cleanup;
171
}
172
173
*pcbCurve = sizes.cbAlloc;
174
*pcbScratch = sizes.cbScratch;
175
176
fSuccess = TRUE;
177
178
cleanup:
179
return fSuccess;
180
}
181
182
// Internal function which actually computes and writes curve into the given buffer.
183
//
184
// This is called internally by both SymCryptEcurveCreate() and SymCryptEcurveAllocate().
185
static
186
PSYMCRYPT_ECURVE
187
SymCryptEcurveInitialize(
188
_In_ PCSYMCRYPT_ECURVE_PARAMS pParams,
189
_In_ UINT32 flags,
190
_In_ PCSYMCRYPT_ECURVE_SIZES pSizes,
191
_Out_writes_bytes_( pSizes->cbAlloc ) PBYTE pbCurve,
192
_Out_writes_bytes_( pSizes->cbScratch) PBYTE pbScratch )
193
{
194
BOOLEAN fSuccess = FALSE;
195
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
196
197
PSYMCRYPT_ECURVE pCurve = (PSYMCRYPT_ECURVE)pbCurve;
198
PBYTE pDst = NULL; // Destination pointer
199
PBYTE pSrc = NULL; // Source pointer
200
201
PBYTE pSrcGenerator = NULL; // We have to set the generator point
202
// only after we have fully initialized the curve
203
204
PSYMCRYPT_INT pTempInt = 0;
205
206
PSYMCRYPT_MODELEMENT peTemp = NULL;
207
208
PCSYMCRYPT_ECURVE_PARAMS_V2_EXTENSION pcParamsV2Ext = NULL;
209
210
UNREFERENCED_PARAMETER( flags );
211
212
// -----------------------------------------------
213
// Populating the fields of the curve object
214
// -----------------------------------------------
215
216
// Version of curve structure
217
pCurve->version = SYMCRYPT_INTERNAL_ECURVE_VERSION_LATEST;
218
219
// Type of curve
220
pCurve->type = (int) pParams->type;
221
222
// Curve point format
223
pCurve->eCoordinates = pSizes->eCoordinates;
224
225
// Number of digits of the field modulus
226
pCurve->FModDigits = pSizes->nDigitsFieldLength;
227
228
// Number of digits of the group order
229
pCurve->GOrdDigits = pSizes->nDigitsSubgroupOrder;
230
231
// Byte size of field elements
232
pCurve->FModBytesize = (UINT32)pParams->cbFieldLength;
233
234
// Byte size of group elements
235
SYMCRYPT_ASSERT( pParams->cbSubgroupOrder < UINT32_MAX );
236
pCurve->GOrdBytesize = (UINT32)pParams->cbSubgroupOrder;
237
238
// Byte size of mod elements
239
pCurve->cbModElement = pSizes->cbModElement;
240
241
// Total bytesize of the curve (used to free the curve object)
242
pCurve->cbAlloc = pSizes->cbAlloc;
243
244
// Set destination and source pointers
245
pDst = ((PBYTE) pCurve) + sizeof( SYMCRYPT_ECURVE );
246
pSrc = ((PBYTE) pParams) + sizeof( SYMCRYPT_ECURVE_PARAMS );
247
248
// Field Modulus
249
pCurve->FMod = SymCryptModulusCreate( pDst, pSizes->cbModulus, pSizes->nDigitsFieldLength );
250
if ( pCurve->FMod == NULL )
251
{
252
goto cleanup;
253
}
254
255
pTempInt = SymCryptIntFromModulus( pCurve->FMod );
256
if ( pTempInt == NULL)
257
{
258
goto cleanup;
259
}
260
261
scError = SymCryptIntSetValue( pSrc, pParams->cbFieldLength, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, pTempInt );
262
if ( scError != SYMCRYPT_NO_ERROR )
263
{
264
goto cleanup;
265
}
266
267
// Field Modulus Bitsize
268
pCurve->FModBitsize = SymCryptIntBitsizeOfValue( pTempInt );
269
if (pCurve->FModBitsize < SYMCRYPT_ECURVE_MIN_BITSIZE_FMOD)
270
{
271
scError = SYMCRYPT_WRONG_KEY_SIZE;
272
goto cleanup;
273
}
274
275
if( (SymCryptIntGetValueLsbits32( pTempInt ) & 1) == 0 )
276
{
277
// 'Prime' must be odd to avoid errors in conversion to modulus
278
scError = SYMCRYPT_INVALID_ARGUMENT;
279
goto cleanup;
280
}
281
282
// IntToModulus requirement:
283
// FModBitsize >= SYMCRYPT_ECURVE_MIN_BITSIZE_FMOD --> pTempInt > 0
284
SymCryptIntToModulus(
285
pTempInt,
286
pCurve->FMod,
287
SYMCRYPT_INTERNAL_ECURVE_MODULUS_NUMOF_OPERATIONS( 8 * pParams->cbFieldLength ),
288
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
289
pbScratch,
290
pSizes->cbScratch );
291
292
pDst += pSizes->cbModulus;
293
pSrc += pParams->cbFieldLength;
294
295
// A constant
296
pCurve->A = SymCryptModElementCreate( pDst, pSizes->cbModElement, pCurve->FMod );
297
if ( pCurve->A == NULL )
298
{
299
goto cleanup;
300
}
301
scError = SymCryptModElementSetValue(
302
pSrc,
303
pParams->cbFieldLength,
304
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
305
pCurve->FMod,
306
pCurve->A,
307
pbScratch,
308
pSizes->cbScratch );
309
if ( scError != SYMCRYPT_NO_ERROR )
310
{
311
goto cleanup;
312
}
313
pDst += pSizes->cbModElement;
314
pSrc += pParams->cbFieldLength;
315
316
// B constant
317
pCurve->B = SymCryptModElementCreate( pDst, pSizes->cbModElement, pCurve->FMod );
318
if ( pCurve->B == NULL )
319
{
320
goto cleanup;
321
}
322
323
// Detect Short-Weierstrass curves with A == -3 (NIST prime curves are all of this form)
324
// Use B's ModElement space for check
325
if( pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS )
326
{
327
SymCryptModElementSetValueNegUint32(
328
3,
329
pCurve->FMod,
330
pCurve->B,
331
pbScratch,
332
pSizes->cbScratch );
333
if ( scError != SYMCRYPT_NO_ERROR )
334
{
335
goto cleanup;
336
}
337
if( SymCryptModElementIsEqual( pCurve->FMod, pCurve->A, pCurve->B ) )
338
{
339
pCurve->type = SYMCRYPT_INTERNAL_ECURVE_TYPE_SHORT_WEIERSTRASS_AM3;
340
}
341
}
342
343
// Set B to the correct value
344
scError = SymCryptModElementSetValue(
345
pSrc,
346
pParams->cbFieldLength,
347
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
348
pCurve->FMod,
349
pCurve->B,
350
pbScratch,
351
pSizes->cbScratch );
352
if ( scError != SYMCRYPT_NO_ERROR )
353
{
354
goto cleanup;
355
}
356
pDst += pSizes->cbModElement;
357
pSrc += pParams->cbFieldLength;
358
359
// Skip over the distinguished point until we fix all the parameters and scratch space sizes
360
pSrcGenerator = pSrc;
361
pSrc += pParams->cbFieldLength * 2;
362
363
// Subgroup Order
364
pCurve->GOrd = SymCryptModulusCreate( pDst, pSizes->cbSubgroupOrder, pSizes->nDigitsSubgroupOrder );
365
if ( pCurve->GOrd == NULL )
366
{
367
goto cleanup;
368
}
369
370
pTempInt = SymCryptIntFromModulus( pCurve->GOrd );
371
if ( pTempInt == NULL)
372
{
373
goto cleanup;
374
}
375
376
scError = SymCryptIntSetValue( pSrc, pParams->cbSubgroupOrder, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, pTempInt );
377
if ( scError != SYMCRYPT_NO_ERROR )
378
{
379
goto cleanup;
380
}
381
382
// Subgroup Order Bitsize
383
pCurve->GOrdBitsize = SymCryptIntBitsizeOfValue( pTempInt );
384
if (pCurve->GOrdBitsize < SYMCRYPT_ECURVE_MIN_BITSIZE_GORD)
385
{
386
scError = SYMCRYPT_WRONG_KEY_SIZE;
387
goto cleanup;
388
}
389
390
if( (SymCryptIntGetValueLsbits32( pTempInt ) & 1) == 0 )
391
{
392
// 'Prime' must be odd to avoid errors in conversion to modulus
393
scError = SYMCRYPT_INVALID_ARGUMENT;
394
goto cleanup;
395
}
396
397
// IntToModulus requirement:
398
// GOrdBitsize >= SYMCRYPT_ECURVE_MIN_BITSIZE_GORD --> pTempInt > 0
399
SymCryptIntToModulus(
400
pTempInt,
401
pCurve->GOrd,
402
SYMCRYPT_INTERNAL_ECURVE_GROUP_ORDER_NUMOF_OPERATIONS,
403
SYMCRYPT_FLAG_DATA_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME,
404
pbScratch,
405
pSizes->cbScratch );
406
407
pDst += pSizes->cbSubgroupOrder;
408
pSrc += pParams->cbSubgroupOrder;
409
410
// Cofactor
411
pCurve->H = SymCryptIntCreate( pDst, pSizes->cbCoFactor, pSizes->nDigitsCoFactor );
412
if ( pCurve->H == NULL )
413
{
414
goto cleanup;
415
}
416
scError = SymCryptIntSetValue(
417
pSrc,
418
pParams->cbCofactor,
419
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
420
pCurve->H );
421
if ( scError != SYMCRYPT_NO_ERROR )
422
{
423
goto cleanup;
424
}
425
426
427
// Make sure that the cofactor is not zero or too big
428
pCurve->coFactorPower = SymCryptIntBitsizeOfValue( pCurve->H ) - 1;
429
if (pCurve->coFactorPower == (UINT32)-1 || pCurve->coFactorPower > SYMCRYPT_ECURVE_MAX_COFACTOR_POWER)
430
{
431
goto cleanup;
432
}
433
434
// Validate that the cofactor is a power of two
435
if (!SymCryptIntIsEqualUint32( pCurve->H, 1<<(pCurve->coFactorPower) ))
436
{
437
goto cleanup;
438
}
439
440
pDst += pSizes->cbCoFactor;
441
pSrc += pParams->cbCofactor;
442
443
// Calculate scratch spaces' sizes
444
if (pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS)
445
{
446
pCurve->info.sw.window = SYMCRYPT_ECURVE_SW_DEF_WINDOW;
447
pCurve->info.sw.nPrecompPoints = (1 << (SYMCRYPT_ECURVE_SW_DEF_WINDOW-2));
448
pCurve->info.sw.nRecodedDigits = pCurve->GOrdBitsize + 1; // This is the maximum - used by the wNAF Interleaving method
449
}
450
else if ( pParams->type == SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS )
451
{
452
pCurve->info.sw.window = SYMCRYPT_ECURVE_SW_DEF_WINDOW;
453
pCurve->info.sw.nPrecompPoints = (1 << (SYMCRYPT_ECURVE_SW_DEF_WINDOW-2));
454
pCurve->info.sw.nRecodedDigits = pCurve->GOrdBitsize + 1; // This is the maximum - used by the wNAF Interleaving method
455
}
456
457
SymCryptEcurveFillScratchSpaces(pCurve);
458
459
// Now set the distinguished point
460
pCurve->G = SymCryptEcpointCreate( pDst, pSizes->cbEcpoint, pCurve );
461
if ( pCurve->G == NULL )
462
{
463
goto cleanup;
464
}
465
scError = SymCryptEcpointSetValue(
466
pCurve,
467
pSrcGenerator,
468
pParams->cbFieldLength * 2,
469
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
470
SYMCRYPT_ECPOINT_FORMAT_XY,
471
pCurve->G,
472
SYMCRYPT_FLAG_DATA_PUBLIC,
473
pbScratch,
474
pSizes->cbScratch );
475
if ( scError != SYMCRYPT_NO_ERROR )
476
{
477
goto cleanup;
478
}
479
pDst += pSizes->cbEcpoint;
480
481
// Fill the precomputed table
482
if ( (pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS) ||
483
(pParams->type == SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS) )
484
{
485
// The first point of the table is the generator
486
pCurve->info.sw.poPrecompPoints[0] = pCurve->G;
487
488
for (UINT32 i=1; i<pCurve->info.sw.nPrecompPoints; i++)
489
{
490
pCurve->info.sw.poPrecompPoints[i] = SymCryptEcpointCreate( pDst, pSizes->cbEcpoint, pCurve );
491
if ( pCurve->info.sw.poPrecompPoints[i] == NULL )
492
{
493
goto cleanup;
494
}
495
pDst += pSizes->cbEcpoint;
496
}
497
498
SymCryptOfflinePrecomputation( pCurve, pbScratch, pSizes->cbScratch );
499
}
500
501
// For Montgomery curve, we calculate A = (A + 2) / 4
502
if (pParams->type == SYMCRYPT_ECURVE_TYPE_MONTGOMERY)
503
{
504
peTemp = SymCryptModElementCreate( pbScratch, pSizes->cbModElement, pCurve->FMod );
505
506
// SetValueUint32 requirements:
507
// FMod > 2 since it has more than SYMCRYPT_ECURVE_MIN_BITSIZE_FMOD bits
508
SymCryptModElementSetValueUint32( 2, pCurve->FMod, peTemp, pbScratch + pSizes->cbModElement, pSizes->cbScratch - pSizes->cbModElement );
509
SymCryptModAdd (pCurve->FMod, pCurve->A, peTemp, pCurve->A, pbScratch + pSizes->cbModElement, pSizes->cbScratch - pSizes->cbModElement ); // A = A + 2;
510
SymCryptModDivPow2( pCurve->FMod, pCurve->A, 2, pCurve->A, pbScratch + pSizes->cbModElement, pSizes->cbScratch - pSizes->cbModElement ); // A = (A + 2) / 4
511
}
512
513
// Set the default curve policy for parameters of version 2
514
if (pParams->version == 2)
515
{
516
// Skip over the seed (if any)
517
pSrc += pParams->cbSeed;
518
519
// Copy the extension info (it can be unaligned)
520
pcParamsV2Ext = (PCSYMCRYPT_ECURVE_PARAMS_V2_EXTENSION) pSrc;
521
}
522
else
523
{
524
// Set the defaults for version 1
525
if (pParams->type == SYMCRYPT_ECURVE_TYPE_SHORT_WEIERSTRASS)
526
{
527
pcParamsV2Ext = SymCryptEcurveParamsV2ExtensionShortWeierstrass;
528
}
529
else if ( pParams->type == SYMCRYPT_ECURVE_TYPE_TWISTED_EDWARDS )
530
{
531
pcParamsV2Ext = SymCryptEcurveParamsV2ExtensionTwistedEdwards;
532
}
533
else if ( pParams->type == SYMCRYPT_ECURVE_TYPE_MONTGOMERY )
534
{
535
pcParamsV2Ext = SymCryptEcurveParamsV2ExtensionMontgomery;
536
}
537
}
538
539
pCurve->PrivateKeyDefaultFormat = pcParamsV2Ext->PrivateKeyDefaultFormat;
540
pCurve->HighBitRestrictionNumOfBits = pcParamsV2Ext->HighBitRestrictionNumOfBits;
541
pCurve->HighBitRestrictionPosition = pcParamsV2Ext->HighBitRestrictionPosition;
542
pCurve->HighBitRestrictionValue = pcParamsV2Ext->HighBitRestrictionValue;
543
544
// Make sure that the HighBitRestrictions make sense
545
// (see SymCryptIntGet/SetBits)
546
if ( (pCurve->HighBitRestrictionNumOfBits>32) ||
547
((pCurve->HighBitRestrictionNumOfBits>0) &&
548
(pCurve->HighBitRestrictionPosition + pCurve->HighBitRestrictionNumOfBits > pCurve->GOrdBitsize + pCurve->coFactorPower)) )
549
{
550
scError = SYMCRYPT_INVALID_ARGUMENT;
551
goto cleanup;
552
}
553
554
// Setting the magic
555
SYMCRYPT_SET_MAGIC( pCurve );
556
557
fSuccess = TRUE;
558
559
cleanup:
560
if (!fSuccess)
561
{
562
SymCryptWipe( pbCurve, pSizes->cbAlloc );
563
pCurve = NULL;
564
}
565
566
return pCurve;
567
}
568
569
PSYMCRYPT_ECURVE
570
SYMCRYPT_CALL
571
SymCryptEcurveCreate(
572
_In_ PSYMCRYPT_ECURVE_PARAMS pParams,
573
_In_ UINT32 flags,
574
_Out_writes_bytes_( cbCurve ) PBYTE pbCurve,
575
SIZE_T cbCurve,
576
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
577
SIZE_T cbScratch)
578
{
579
SYMCRYPT_ECURVE_SIZES sizes;
580
581
PSYMCRYPT_ECURVE pCurve = NULL;
582
583
if ( !SymCryptEcurveValidateAndComputeSizes(pParams, &sizes) )
584
{
585
goto cleanup;
586
}
587
588
if ( cbCurve < sizes.cbAlloc )
589
{
590
goto cleanup;
591
}
592
593
if ( cbScratch < sizes.cbScratch )
594
{
595
goto cleanup;
596
}
597
598
pCurve = SymCryptEcurveInitialize( pParams, flags, &sizes, pbCurve, pbScratch );
599
600
cleanup:
601
return pCurve;
602
}
603
604
PSYMCRYPT_ECURVE
605
SYMCRYPT_CALL
606
SymCryptEcurveAllocate(
607
_In_ PCSYMCRYPT_ECURVE_PARAMS pParams,
608
_In_ UINT32 flags )
609
{
610
SYMCRYPT_ECURVE_SIZES sizes;
611
612
PBYTE pbCurve = NULL;
613
PBYTE pbScratch = NULL;
614
615
PSYMCRYPT_ECURVE pCurve = NULL;
616
617
if ( !SymCryptEcurveValidateAndComputeSizes(pParams, &sizes) )
618
{
619
goto cleanup;
620
}
621
622
pbCurve = SymCryptCallbackAlloc( sizes.cbAlloc );
623
if ( pbCurve == NULL )
624
{
625
goto cleanup;
626
}
627
628
pbScratch = SymCryptCallbackAlloc( sizes.cbScratch );
629
if ( pbScratch == NULL )
630
{
631
goto cleanup;
632
}
633
634
pCurve = SymCryptEcurveInitialize( pParams, flags, &sizes, pbCurve, pbScratch );
635
if ( pCurve != NULL )
636
{
637
pbCurve = NULL;
638
}
639
640
cleanup:
641
if ( pbScratch != NULL )
642
{
643
SymCryptWipe( pbScratch, sizes.cbScratch );
644
SymCryptCallbackFree( pbScratch );
645
}
646
647
if ( pbCurve != NULL )
648
{
649
SymCryptCallbackFree( pbCurve );
650
}
651
652
return pCurve;
653
}
654
655
VOID
656
SYMCRYPT_CALL
657
SymCryptEcurveFree( _Out_ PSYMCRYPT_ECURVE pCurve )
658
{
659
SYMCRYPT_CHECK_MAGIC( pCurve );
660
661
SymCryptWipe( (PBYTE) pCurve, pCurve->cbAlloc );
662
663
SymCryptCallbackFree( pCurve );
664
}
665
666
UINT32
667
SYMCRYPT_CALL
668
SymCryptEcurveBitsizeofFieldModulus( _In_ PCSYMCRYPT_ECURVE pCurve )
669
{
670
return pCurve->FModBitsize;
671
}
672
673
UINT32
674
SYMCRYPT_CALL
675
SymCryptEcurveBitsizeofGroupOrder( _In_ PCSYMCRYPT_ECURVE pCurve )
676
{
677
return pCurve->GOrdBitsize;
678
}
679
680
UINT32
681
SYMCRYPT_CALL
682
SymCryptEcurveDigitsofFieldElement( _In_ PCSYMCRYPT_ECURVE pCurve )
683
{
684
return pCurve->FModDigits;
685
}
686
687
UINT32
688
SYMCRYPT_CALL
689
SymCryptEcurveSizeofFieldElement( _In_ PCSYMCRYPT_ECURVE pCurve )
690
{
691
return pCurve->FModBytesize;
692
}
693
694
UINT32
695
SYMCRYPT_CALL
696
SymCryptEcurveSizeofScalarMultiplier( _In_ PCSYMCRYPT_ECURVE pCurve )
697
{
698
return pCurve->GOrdBytesize;
699
}
700
701
PCSYMCRYPT_MODULUS
702
SYMCRYPT_CALL
703
SymCryptEcurveGroupOrder( _In_ PCSYMCRYPT_ECURVE pCurve )
704
{
705
return pCurve->GOrd;
706
}
707
708
UINT32
709
SYMCRYPT_CALL
710
SymCryptEcurveDigitsofScalarMultiplier( _In_ PCSYMCRYPT_ECURVE pCurve )
711
{
712
return SymCryptDigitsFromBits( pCurve->GOrdBitsize + pCurve->coFactorPower );
713
}
714
715
UINT32
716
SYMCRYPT_CALL
717
SymCryptEcurvePrivateKeyDefaultFormat( _In_ PCSYMCRYPT_ECURVE pCurve )
718
{
719
return pCurve->PrivateKeyDefaultFormat;
720
}
721
722
UINT32
723
SYMCRYPT_CALL
724
SymCryptEcurveHighBitRestrictionNumOfBits( _In_ PCSYMCRYPT_ECURVE pCurve )
725
{
726
return pCurve->HighBitRestrictionNumOfBits;
727
}
728
729
UINT32
730
SYMCRYPT_CALL
731
SymCryptEcurveHighBitRestrictionPosition( _In_ PCSYMCRYPT_ECURVE pCurve )
732
{
733
return pCurve->HighBitRestrictionPosition;
734
}
735
736
UINT32
737
SYMCRYPT_CALL
738
SymCryptEcurveHighBitRestrictionValue( _In_ PCSYMCRYPT_ECURVE pCurve )
739
{
740
return pCurve->HighBitRestrictionValue;
741
}
742
743
BOOLEAN
744
SYMCRYPT_CALL
745
SymCryptEcurveIsSame(
746
_In_ PCSYMCRYPT_ECURVE pCurve1,
747
_In_ PCSYMCRYPT_ECURVE pCurve2)
748
{
749
BOOLEAN fIsSameCurve = FALSE;
750
751
if ( pCurve1 == pCurve2 )
752
{
753
fIsSameCurve = TRUE;
754
goto cleanup;
755
}
756
757
if ( (pCurve1->type != pCurve2->type) ||
758
!SymCryptIntIsEqual (
759
SymCryptIntFromModulus( pCurve1->FMod ),
760
SymCryptIntFromModulus( pCurve2->FMod ) ) ||
761
!SymCryptModElementIsEqual ( pCurve1->FMod, pCurve1->A, pCurve2->A ) ||
762
!SymCryptModElementIsEqual ( pCurve1->FMod, pCurve1->B, pCurve2->B ) )
763
{
764
goto cleanup;
765
}
766
767
fIsSameCurve = TRUE;
768
769
cleanup:
770
return fIsSameCurve;
771
}
772
773