Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/ec_dsa.c
15010 views
1
//
2
// ec_dsa.c ECDSA functions
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
/*
11
Sections 7.2.7 and 7.2.8 of the 29 August 2000
12
IEEE Standard Specifications for Public-Key Cryptography,
13
IEEE Std 1363-2000, list DSA versions of the elliptic
14
curve signature and verification primitives.
15
This file has draft interfaces,
16
17
7.2.7 ECSP_DSA (pages 35-36)
18
19
Inputs:
20
E -- An elliptic curve.
21
G (generator) -- A point on E of prime order r.
22
r -- See G.
23
s -- A secret exponent, 1 <= s < r (Private key)
24
msghash -- Hash of the message being signed.
25
26
Outputs:
27
c, d -- Two integers in the interval [1, r-1]
28
29
Algorithm:
30
1) Generate random exponent k, 1 <= k < r,
31
to be kept from adversary.
32
Compute KG = k*G in E.
33
Note KG <> (point at infinity).
34
2) Convert x(KG) (an element of GF(q))
35
to an integer FE2IP(x(KG)).
36
Let c = FE2IP(x(KG)) (mod r).
37
3) Compute d = (msghash + s*c)/k (mod r).
38
4) If c == 0 or d == 0, return to 1).
39
5) Output c and d as integers.
40
41
7.2.8 ECVP_DSA
42
43
Inputs:
44
E, G, r, msghash -- Same as in ECSP_DSA.
45
W -- The signer's public key. Equal to
46
s*G where s was passed to ECSP_DSA.
47
c, d -- A signature to be checked.
48
49
Output:
50
TRUE if signature OK, else FALSE.
51
52
Algorithm:
53
1) If c or d is not in [1, r-1], return FALSE.
54
2) Compute h1 = msghash/d (mod r)
55
and h2 = c/d (mod r).
56
3) Compute P = h1*G + h2*W.
57
If P == (point at infinity), return FALSE.
58
4) If c == FE2IP(x(P)) mod r, return TRUE.
59
Otherwise return FALSE.
60
61
FE2IP is a P1363 function that casts a field element to an
62
integer (MSB_FIRST). See Section 5.5.5 of P1363.
63
*/
64
65
//
66
// Truncating function according to the standard or
67
// the original CNG implementation:
68
//
69
// Initially both implementations truncate the last **bytes**
70
// of the hash that are over the group byte length. Then if
71
// the bit length of the hash is still bigger than the bit
72
// length of the group order, ...
73
//
74
// 1. According to the X9.62 standard, we do an appropriate right shift to the entire hash.
75
// An example of this is a 160-bit hash, but a 113-bit subgroup order. For this case:
76
// a. We would truncate cbHash to (113 + 7) / 8 = 15 bytes.
77
// b. Since 15*8 = 120 > 113 we need to right-shift by 7 bits.
78
// 2. According to the original CNG implementation, we mask an appropriate number of the
79
// topmost bits of the hash.
80
// In the same example as before we would zero out the top 7 bits.
81
//
82
SYMCRYPT_ERROR
83
SYMCRYPT_CALL
84
SymCryptEcDsaTruncateHash(
85
_In_ PCSYMCRYPT_ECURVE pCurve,
86
_In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue,
87
SIZE_T cbHashValue,
88
UINT32 flags,
89
_Out_ PSYMCRYPT_MODELEMENT peMsghash,
90
_Out_ PSYMCRYPT_INT piTmp,
91
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
92
SIZE_T cbScratch )
93
{
94
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
95
UINT32 uiBitsizeOfTmp = 0;
96
UINT32 uiBitsizeOfGroup = 0;
97
98
// Make sure that only the correct flags are set
99
if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
100
{
101
scError = SYMCRYPT_INVALID_ARGUMENT;
102
goto cleanup;
103
}
104
105
// Get the bitsize of the group order
106
uiBitsizeOfGroup = SymCryptEcurveBitsizeofGroupOrder( pCurve );
107
108
// Truncate the last bytes of the hash
109
if (cbHashValue*8 > uiBitsizeOfGroup)
110
{
111
cbHashValue = (uiBitsizeOfGroup + 7)/8;
112
}
113
114
// Get the value of msghash
115
scError = SymCryptIntSetValue( pbHashValue, cbHashValue, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTmp );
116
if ( scError != SYMCRYPT_NO_ERROR )
117
{
118
goto cleanup;
119
}
120
121
// Get the bit size of the hash
122
uiBitsizeOfTmp = (UINT32)cbHashValue * 8;
123
124
// If SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION is set, we don't do hash truncation.
125
// The caller can do their own truncation before calling into Symcrypt.
126
if ( ( flags & SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION ) == 0)
127
{
128
// ******** Standard truncation **************
129
// Shift right if needed
130
if ( uiBitsizeOfTmp > uiBitsizeOfGroup )
131
{
132
SymCryptIntDivPow2( piTmp, uiBitsizeOfTmp - uiBitsizeOfGroup, piTmp );
133
}
134
}
135
136
SymCryptIntToModElement( piTmp, pCurve->GOrd, peMsghash, pbScratch, cbScratch ); // msghash mod r
137
138
cleanup:
139
return scError;
140
}
141
142
#define SYMCRYPT_MAX_ECDSA_SIGNATURE_COUNT (100)
143
144
SYMCRYPT_ERROR
145
SYMCRYPT_CALL
146
SymCryptEcDsaSignEx(
147
_In_ PCSYMCRYPT_ECKEY pKey,
148
_In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue,
149
SIZE_T cbHashValue,
150
_In_opt_ PCSYMCRYPT_INT piK,
151
SYMCRYPT_NUMBER_FORMAT format,
152
UINT32 flags,
153
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
154
SIZE_T cbSignature )
155
{
156
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
157
158
PBYTE pbScratch = NULL;
159
SIZE_T cbScratch = 0;
160
SIZE_T cbScratchInternal = 0;
161
PBYTE pCurr = NULL;
162
163
PCSYMCRYPT_ECURVE pCurve = pKey->pCurve;
164
165
PSYMCRYPT_INT piTmp = NULL;
166
PSYMCRYPT_INT piMul = NULL;
167
PSYMCRYPT_ECPOINT poKG = NULL;
168
169
PSYMCRYPT_MODELEMENT peMsghash = NULL;
170
PSYMCRYPT_MODELEMENT peSigC = NULL;
171
PSYMCRYPT_MODELEMENT peSigD = NULL;
172
PSYMCRYPT_MODELEMENT peTmp = NULL;
173
174
PBYTE pbX = NULL;
175
176
UINT32 nDigitsInt = 0;
177
UINT32 nDigitsMul = 0;
178
179
UINT32 cbInt = 0;
180
UINT32 cbMul = 0;
181
UINT32 cbKG = 0;
182
UINT32 cbRs = 0;
183
UINT32 cbX = 0;
184
185
UINT32 signatureCount = 0;
186
UINT32 allowedFlags = SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION | SYMCRYPT_FLAG_DATA_PUBLIC;
187
UINT32 publicFlag = flags & SYMCRYPT_FLAG_DATA_PUBLIC;
188
UINT32 truncationFlag = flags & SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION;
189
190
// Make sure that the key may be used in ECDSA
191
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0) )
192
{
193
scError = SYMCRYPT_INVALID_ARGUMENT;
194
goto cleanup;
195
}
196
197
// Make sure only allowed flags are specified and
198
// there is a private key
199
if ( ((flags & ~(allowedFlags)) != 0) ||
200
(!pKey->hasPrivateKey) )
201
{
202
scError = SYMCRYPT_INVALID_ARGUMENT;
203
goto cleanup;
204
}
205
206
// Calculating the digits for the temporary integers
207
nDigitsInt = pCurve->GOrdDigits;
208
209
nDigitsMul = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
210
211
// Objects and scratch space size calculation
212
cbInt = SymCryptSizeofIntFromDigits( nDigitsInt );
213
cbMul = SymCryptSizeofIntFromDigits( nDigitsMul );
214
cbKG = SymCryptSizeofEcpointFromCurve( pCurve );
215
cbRs = SymCryptSizeofModElementFromModulus( pCurve->GOrd );
216
cbX = SymCryptEcurveSizeofFieldElement( pCurve );
217
218
cbScratchInternal = SYMCRYPT_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( pCurve );
219
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits ) );
220
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) );
221
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->GOrdDigits ) );
222
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
223
224
//
225
// From symcrypt_internal.h we have:
226
// - sizeof results are upper bounded by 2^19
227
// - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
228
// Thus the following calculation does not overflow cbScratch.
229
//
230
cbScratch = cbScratchInternal + cbInt + cbMul + cbKG + 4*cbRs + cbX;
231
232
// Scratch space allocation
233
pbScratch = SymCryptCallbackAlloc( cbScratch );
234
if ( pbScratch == NULL )
235
{
236
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
237
goto cleanup;
238
}
239
240
// Creating temporaries
241
pCurr = pbScratch + cbScratchInternal;
242
piTmp = SymCryptIntCreate( pCurr, cbInt, nDigitsInt );
243
pCurr += cbInt;
244
piMul = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
245
pCurr += cbMul;
246
poKG = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
247
pCurr += cbKG;
248
peMsghash = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
249
pCurr += cbRs;
250
peSigC = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
251
pCurr += cbRs;
252
peSigD = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
253
pCurr += cbRs;
254
peTmp = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
255
pCurr += cbRs;
256
pbX = pCurr;
257
258
SYMCRYPT_ASSERT( piTmp != NULL);
259
SYMCRYPT_ASSERT( piMul != NULL);
260
SYMCRYPT_ASSERT( poKG != NULL);
261
SYMCRYPT_ASSERT( peMsghash != NULL);
262
SYMCRYPT_ASSERT( peSigC != NULL);
263
SYMCRYPT_ASSERT( peSigD != NULL);
264
SYMCRYPT_ASSERT( peTmp != NULL);
265
266
// Truncate the message according to the flags
267
scError = SymCryptEcDsaTruncateHash(
268
pCurve,
269
pbHashValue,
270
cbHashValue,
271
truncationFlag,
272
peMsghash,
273
piTmp,
274
pbScratch,
275
cbScratchInternal );
276
if ( scError != SYMCRYPT_NO_ERROR )
277
{
278
goto cleanup;
279
}
280
281
//
282
// Main loop: Stop when both c and d are not zero (unless a specific k is provided)
283
//
284
while( TRUE )
285
{
286
if ( piK == NULL )
287
{
288
SymCryptEcpointSetRandom( pCurve, piMul, poKG, pbScratch, cbScratchInternal ); // Generate k and k*G
289
SymCryptIntToModElement( piMul, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal );
290
}
291
else
292
{
293
// Ensure that piK is in the range [1, GOrd-1]
294
if( SymCryptIntIsEqualUint32( piK, 0 ) ||
295
!SymCryptIntIsLessThan( piK, SymCryptIntFromModulus( pCurve->GOrd ) ) )
296
{
297
scError = SYMCRYPT_INVALID_ARGUMENT;
298
goto cleanup;
299
}
300
301
SymCryptIntCopy( piK, piMul );
302
SymCryptIntToModElement( piMul, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal );
303
304
scError = SymCryptEcpointScalarMul( pCurve, piMul, NULL, 0, poKG, pbScratch, cbScratchInternal ); // Generate k*G
305
if ( scError != SYMCRYPT_NO_ERROR )
306
{
307
goto cleanup;
308
}
309
}
310
311
scError = SymCryptModInv( pCurve->GOrd, peTmp, peTmp, publicFlag, pbScratch, cbScratchInternal ); // Invert k
312
if ( scError != SYMCRYPT_NO_ERROR )
313
{
314
goto cleanup;
315
}
316
317
// Get the x coordinates from KG
318
scError = SymCryptEcpointGetValue(
319
pCurve,
320
poKG,
321
SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
322
SYMCRYPT_ECPOINT_FORMAT_X,
323
pbX,
324
cbX,
325
publicFlag,
326
pbScratch,
327
cbScratchInternal );
328
if ( scError != SYMCRYPT_NO_ERROR )
329
{
330
goto cleanup;
331
}
332
333
// Store c = x(KG) as an integer
334
scError = SymCryptModElementSetValue( pbX, cbX, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, pCurve->GOrd, peSigC, pbScratch, cbScratch );
335
if ( scError != SYMCRYPT_NO_ERROR )
336
{
337
goto cleanup;
338
}
339
340
// Move the private key into peSigD
341
SymCryptIntToModElement( pKey->piPrivateKey, pCurve->GOrd, peSigD, pbScratch, cbScratchInternal );
342
343
// Multiply the private key by h since its internal format is "DivH"
344
for (UINT32 i=0; i<pCurve->coFactorPower; i++)
345
{
346
SymCryptModAdd( pCurve->GOrd, peSigD, peSigD, peSigD, pbScratch, cbScratchInternal );
347
}
348
349
SymCryptModMul( pCurve->GOrd, peSigC, peSigD, peSigD, pbScratch, cbScratchInternal ); // s * c
350
SymCryptModAdd( pCurve->GOrd, peMsghash, peSigD, peSigD, pbScratch, cbScratchInternal ); // msghash + s*c
351
SymCryptModMul( pCurve->GOrd, peSigD, peTmp, peSigD, pbScratch, cbScratchInternal ); // ( msghash + s*c ) / k
352
353
if ( !( SymCryptModElementIsZero( pCurve->GOrd, peSigC ) |
354
SymCryptModElementIsZero( pCurve->GOrd, peSigD ) ) )
355
{
356
break;
357
}
358
359
if (piK != NULL)
360
{
361
// piK resulted in 0 signature
362
scError = SYMCRYPT_INVALID_ARGUMENT;
363
goto cleanup;
364
}
365
366
signatureCount++;
367
if ( signatureCount >= SYMCRYPT_MAX_ECDSA_SIGNATURE_COUNT )
368
{
369
// We have not generated a non-zero signature after SYMCRYPT_MAX_ECDSA_SIGNATURE_COUNT attempts;
370
// Something is wrong with the group setup
371
scError = SYMCRYPT_INVALID_ARGUMENT;
372
goto cleanup;
373
}
374
}
375
376
// Output c
377
scError = SymCryptModElementGetValue( pCurve->GOrd, peSigC, pbSignature, cbSignature / 2, format, pbScratch, cbScratchInternal );
378
if ( scError != SYMCRYPT_NO_ERROR )
379
{
380
goto cleanup;
381
}
382
383
// Output d
384
scError = SymCryptModElementGetValue( pCurve->GOrd, peSigD, pbSignature + cbSignature / 2, cbSignature / 2, format, pbScratch, cbScratchInternal );
385
if ( scError != SYMCRYPT_NO_ERROR )
386
{
387
goto cleanup;
388
}
389
390
cleanup:
391
if ( pbScratch != NULL )
392
{
393
SymCryptWipe( pbScratch, cbScratch );
394
SymCryptCallbackFree( pbScratch );
395
}
396
397
if (scError != SYMCRYPT_NO_ERROR)
398
{
399
SymCryptWipe( pbSignature, cbSignature );
400
}
401
402
return scError;
403
}
404
405
406
SYMCRYPT_ERROR
407
SYMCRYPT_CALL
408
SymCryptEcDsaSign(
409
_In_ PCSYMCRYPT_ECKEY pKey,
410
_In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue,
411
SIZE_T cbHashValue,
412
SYMCRYPT_NUMBER_FORMAT format,
413
UINT32 flags,
414
_Out_writes_bytes_( cbSignature ) PBYTE pbSignature,
415
SIZE_T cbSignature )
416
{
417
// Make sure that only the correct flags are set
418
if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
419
{
420
return SYMCRYPT_INVALID_ARGUMENT;
421
}
422
423
// We must have a private key to perform PCT or signature
424
if( !pKey->hasPrivateKey || !(pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) )
425
{
426
return SYMCRYPT_INVALID_ARGUMENT;
427
}
428
429
// If the key was generated in SymCrypt and has not yet had a PCT performed - perform PCT before first use
430
SYMCRYPT_RUN_KEY_GEN_PCT(
431
SymCryptEcDsaPct,
432
pKey,
433
SYMCRYPT_PCT_ECDSA );
434
435
return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
436
}
437
438
SYMCRYPT_ERROR
439
SYMCRYPT_CALL
440
SymCryptEcDsaVerify(
441
_In_ PCSYMCRYPT_ECKEY pKey,
442
_In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue,
443
SIZE_T cbHashValue,
444
_In_reads_bytes_( cbSignature ) PCBYTE pbSignature,
445
SIZE_T cbSignature,
446
SYMCRYPT_NUMBER_FORMAT format,
447
UINT32 flags )
448
{
449
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
450
PBYTE pbScratch = NULL;
451
SIZE_T cbScratch = 0;
452
SIZE_T cbScratchInternal = 0;
453
PBYTE pCurr = NULL;
454
BOOLEAN fValidSignature = FALSE;
455
456
PCSYMCRYPT_ECURVE pCurve = pKey->pCurve;
457
458
PSYMCRYPT_INT piTmp = NULL;
459
PSYMCRYPT_INT piMul1 = NULL;
460
PSYMCRYPT_INT piMul2 = NULL;
461
PSYMCRYPT_ECPOINT poQ1 = NULL;
462
PSYMCRYPT_ECPOINT poQ2 = NULL;
463
464
PSYMCRYPT_MODELEMENT peMsghash = NULL;
465
PSYMCRYPT_MODELEMENT peSigC = NULL;
466
PSYMCRYPT_MODELEMENT peSigD = NULL;
467
PSYMCRYPT_MODELEMENT peTmp = NULL;
468
469
PBYTE pbX = NULL;
470
PCSYMCRYPT_ECPOINT poTable[2] = { 0 };
471
PCSYMCRYPT_INT piTable[2] = { 0 };
472
473
UINT32 nDigitsInt = 0;
474
UINT32 nDigitsMul = 0;
475
476
UINT32 cbInt = 0;
477
UINT32 cbMul = 0;
478
UINT32 cbKG = 0;
479
UINT32 cbRs = 0;
480
UINT32 cbX = 0;
481
482
// Make sure that the key may be used in ECDSA
483
if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0) )
484
{
485
scError = SYMCRYPT_INVALID_ARGUMENT;
486
goto cleanup;
487
}
488
489
// Make sure that only the correct flags are set
490
if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
491
{
492
scError = SYMCRYPT_INVALID_ARGUMENT;
493
goto cleanup;
494
}
495
496
// Calculating the digits for the temporary integer
497
nDigitsInt = SYMCRYPT_MAX( pCurve->FModDigits, pCurve->GOrdDigits );
498
nDigitsInt = SYMCRYPT_MAX( nDigitsInt, SymCryptDigitsFromBits( (UINT32)cbSignature * 4 ) ); // pbSignature contains (c,d)
499
500
nDigitsMul = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
501
502
// Objects and scratch space size calculation
503
cbInt = SymCryptSizeofIntFromDigits( nDigitsInt );
504
cbMul = SymCryptSizeofIntFromDigits( nDigitsMul );
505
cbKG = SymCryptSizeofEcpointFromCurve( pCurve );
506
cbRs = SymCryptSizeofModElementFromModulus( pCurve->GOrd );
507
cbX = SymCryptEcurveSizeofFieldElement( pCurve );
508
509
cbScratchInternal = SYMCRYPT_SCRATCH_BYTES_FOR_MULTI_SCALAR_ECURVE_OPERATIONS( pCurve, 2 );
510
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits ) );
511
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) );
512
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->GOrdDigits ) );
513
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
514
cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
515
516
//
517
// From symcrypt_internal.h we have:
518
// - sizeof results are upper bounded by 2^19
519
// - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
520
// Thus the following calculation does not overflow cbScratch.
521
//
522
cbScratch = cbScratchInternal + cbInt + 2*cbMul + 2*cbKG + 4*cbRs + cbX;
523
524
// Scratch space allocation
525
pbScratch = SymCryptCallbackAlloc( cbScratch );
526
if ( pbScratch == NULL )
527
{
528
scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
529
goto cleanup;
530
}
531
532
// Creating temporaries
533
pCurr = pbScratch + cbScratchInternal;
534
piTmp = SymCryptIntCreate( pCurr, cbInt, nDigitsInt );
535
pCurr += cbInt;
536
piMul1 = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
537
pCurr += cbMul;
538
piMul2 = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
539
pCurr += cbMul;
540
poQ1 = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
541
pCurr += cbKG;
542
poQ2 = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
543
pCurr += cbKG;
544
peMsghash = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
545
pCurr += cbRs;
546
peSigC = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
547
pCurr += cbRs;
548
peSigD = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
549
pCurr += cbRs;
550
peTmp = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
551
pCurr += cbRs;
552
pbX = pCurr;
553
554
SYMCRYPT_ASSERT( piTmp != NULL);
555
SYMCRYPT_ASSERT( piMul1 != NULL);
556
SYMCRYPT_ASSERT( piMul2 != NULL);
557
SYMCRYPT_ASSERT( poQ1 != NULL);
558
SYMCRYPT_ASSERT( poQ2 != NULL);
559
SYMCRYPT_ASSERT( peMsghash != NULL);
560
SYMCRYPT_ASSERT( peSigC != NULL);
561
SYMCRYPT_ASSERT( peSigD != NULL);
562
SYMCRYPT_ASSERT( peTmp != NULL);
563
564
// Get c
565
scError = SymCryptIntSetValue( pbSignature, cbSignature / 2, format, piTmp );
566
if ( scError != SYMCRYPT_NO_ERROR )
567
{
568
goto cleanup;
569
}
570
571
// Check if c is less than r
572
if ( !SymCryptIntIsLessThan( piTmp, SymCryptIntFromModulus( pCurve->GOrd ) ) )
573
{
574
goto cleanup;
575
}
576
577
// c mod r
578
SymCryptIntToModElement( piTmp, pCurve->GOrd, peSigC, pbScratch, cbScratchInternal );
579
580
// Check if c is zero
581
if (SymCryptModElementIsZero( pCurve->GOrd, peSigC ))
582
{
583
goto cleanup;
584
}
585
586
// Get d
587
scError = SymCryptIntSetValue( pbSignature + cbSignature / 2, cbSignature / 2, format, piTmp );
588
if ( scError != SYMCRYPT_NO_ERROR )
589
{
590
goto cleanup;
591
}
592
593
// Check if d is less than r
594
if ( !SymCryptIntIsLessThan( piTmp, SymCryptIntFromModulus( pCurve->GOrd ) ) )
595
{
596
goto cleanup;
597
}
598
599
// d mod r
600
SymCryptIntToModElement( piTmp, pCurve->GOrd, peSigD, pbScratch, cbScratchInternal );
601
602
// Check if d is zero
603
if (SymCryptModElementIsZero( pCurve->GOrd, peSigD ))
604
{
605
goto cleanup;
606
}
607
608
// Calculate 1/d mod r
609
// The D value is not secret; it is part of the signature.
610
// We mark it public to avoid the use of random blinding, which would require a source of randomness
611
// just to verify an ECDSA signature.
612
scError = SymCryptModInv( pCurve->GOrd, peSigD, peSigD, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratchInternal );
613
if( scError != SYMCRYPT_NO_ERROR )
614
{
615
goto cleanup;
616
}
617
618
// Truncate the message according to the flags
619
scError = SymCryptEcDsaTruncateHash(
620
pCurve,
621
pbHashValue,
622
cbHashValue,
623
flags,
624
peMsghash,
625
piTmp,
626
pbScratch,
627
cbScratchInternal );
628
if ( scError != SYMCRYPT_NO_ERROR )
629
{
630
goto cleanup;
631
}
632
633
SymCryptModMul( pCurve->GOrd, peMsghash, peSigD, peMsghash, pbScratch, cbScratchInternal ); // msghash / d = h1
634
SymCryptModMul( pCurve->GOrd, peSigC, peSigD, peTmp, pbScratch, cbScratchInternal ); // c / d = h2
635
636
SymCryptModElementToInt( pCurve->GOrd, peMsghash, piMul1, pbScratch, cbScratchInternal );
637
SymCryptModElementToInt( pCurve->GOrd, peTmp, piMul2, pbScratch, cbScratchInternal );
638
639
// h1*G + h2*W
640
piTable[0] = piMul1;
641
piTable[1] = piMul2;
642
643
poTable[0] = NULL; // The first base point is the generator G of the group
644
poTable[1] = pKey->poPublicKey;
645
646
scError = SymCryptEcpointMultiScalarMul( pCurve, piTable, poTable, 2, SYMCRYPT_FLAG_DATA_PUBLIC, poQ1, pbScratch, cbScratchInternal );
647
if ( scError != SYMCRYPT_NO_ERROR )
648
{
649
goto cleanup;
650
}
651
652
// Check for point at infinity
653
if ( SymCryptEcpointIsZero( pCurve, poQ1, pbScratch, cbScratchInternal ) )
654
{
655
goto cleanup;
656
}
657
658
// Get the x from poQ1
659
scError = SymCryptEcpointGetValue( pCurve, poQ1, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, SYMCRYPT_ECPOINT_FORMAT_X, pbX, cbX, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratchInternal);
660
if ( scError != SYMCRYPT_NO_ERROR )
661
{
662
goto cleanup;
663
}
664
665
// Store it in a big enough INT
666
scError = SymCryptIntSetValue( pbX, cbX, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTmp );
667
if ( scError != SYMCRYPT_NO_ERROR )
668
{
669
goto cleanup;
670
}
671
672
SymCryptIntToModElement( piTmp, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal ); // x mod r
673
674
// Comparison c = x
675
if (SymCryptModElementIsEqual( pCurve->GOrd, peSigC, peTmp ))
676
{
677
fValidSignature = TRUE;
678
}
679
680
cleanup:
681
682
if (!fValidSignature)
683
{
684
scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
685
}
686
687
if ( pbScratch != NULL )
688
{
689
SymCryptWipe( pbScratch, cbScratch );
690
SymCryptCallbackFree( pbScratch );
691
}
692
693
return scError;
694
}
695
696