Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/ec_dsa.c
Line
Count
Source (jump to first uncovered line)
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
330
{
94
330
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
95
330
    UINT32 uiBitsizeOfTmp = 0;
96
330
    UINT32 uiBitsizeOfGroup = 0;
97
98
    // Make sure that only the correct flags are set
99
330
    if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
100
0
    {
101
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
102
0
        goto cleanup;
103
0
    }
104
105
    // Get the bitsize of the group order
106
330
    uiBitsizeOfGroup = SymCryptEcurveBitsizeofGroupOrder( pCurve );
107
108
    // Truncate the last bytes of the hash
109
330
    if (cbHashValue*8 > uiBitsizeOfGroup)
110
52
    {
111
52
        cbHashValue = (uiBitsizeOfGroup + 7)/8;
112
52
    }
113
114
    // Get the value of msghash
115
330
    scError = SymCryptIntSetValue( pbHashValue, cbHashValue, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTmp );
116
330
    if ( scError != SYMCRYPT_NO_ERROR )
117
0
    {
118
0
        goto cleanup;
119
0
    }
120
121
    // Get the bit size of the hash
122
330
    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
330
    if ( ( flags & SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION ) == 0)
127
330
    {
128
        // ******** Standard truncation **************
129
        // Shift right if needed
130
330
        if ( uiBitsizeOfTmp > uiBitsizeOfGroup )
131
6
        {
132
6
            SymCryptIntDivPow2( piTmp, uiBitsizeOfTmp - uiBitsizeOfGroup, piTmp );
133
6
        }
134
330
    }
135
136
330
    SymCryptIntToModElement( piTmp, pCurve->GOrd, peMsghash, pbScratch, cbScratch );        // msghash mod r
137
138
330
cleanup:
139
330
    return scError;
140
330
}
141
142
0
#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
139
{
156
139
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
157
158
139
    PBYTE   pbScratch = NULL;
159
139
    SIZE_T  cbScratch = 0;
160
139
    SIZE_T  cbScratchInternal = 0;
161
139
    PBYTE   pCurr = NULL;
162
163
139
    PCSYMCRYPT_ECURVE       pCurve = pKey->pCurve;
164
165
139
    PSYMCRYPT_INT           piTmp = NULL;
166
139
    PSYMCRYPT_INT           piMul = NULL;
167
139
    PSYMCRYPT_ECPOINT       poKG = NULL;
168
169
139
    PSYMCRYPT_MODELEMENT    peMsghash = NULL;
170
139
    PSYMCRYPT_MODELEMENT    peSigC = NULL;
171
139
    PSYMCRYPT_MODELEMENT    peSigD = NULL;
172
139
    PSYMCRYPT_MODELEMENT    peTmp = NULL;
173
174
139
    PBYTE                   pbX = NULL;
175
176
139
    UINT32  nDigitsInt = 0;
177
139
    UINT32  nDigitsMul = 0;
178
179
139
    UINT32  cbInt = 0;
180
139
    UINT32  cbMul = 0;
181
139
    UINT32  cbKG = 0;
182
139
    UINT32  cbRs = 0;
183
139
    UINT32  cbX  = 0;
184
185
139
    UINT32 signatureCount = 0;
186
187
    // Make sure that the key may be used in ECDSA
188
139
    if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0)  )
189
0
    {
190
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
191
0
        goto cleanup;
192
0
    }
193
194
    // Make sure we only specify the correct flags and that
195
    // there is a private key
196
139
    if ( ((flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0) ||
197
139
         (!pKey->hasPrivateKey) )
198
0
    {
199
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
200
0
        goto cleanup;
201
0
    }
202
203
    // Calculating the digits for the temporary integers
204
139
    nDigitsInt = pCurve->GOrdDigits;
205
206
139
    nDigitsMul = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
207
208
    // Objects and scratch space size calculation
209
139
    cbInt = SymCryptSizeofIntFromDigits( nDigitsInt );
210
139
    cbMul = SymCryptSizeofIntFromDigits( nDigitsMul );
211
139
    cbKG = SymCryptSizeofEcpointFromCurve( pCurve );
212
139
    cbRs = SymCryptSizeofModElementFromModulus( pCurve->GOrd );
213
139
    cbX  = SymCryptEcurveSizeofFieldElement( pCurve );
214
215
139
    cbScratchInternal = SYMCRYPT_SCRATCH_BYTES_FOR_SCALAR_ECURVE_OPERATIONS( pCurve );
216
139
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits ) );
217
139
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) );
218
139
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->GOrdDigits ) );
219
139
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
220
221
    //
222
    // From symcrypt_internal.h we have:
223
    //      - sizeof results are upper bounded by 2^19
224
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
225
    // Thus the following calculation does not overflow cbScratch.
226
    //
227
139
    cbScratch = cbScratchInternal + cbInt + cbMul + cbKG + 4*cbRs + cbX;
228
229
    // Scratch space allocation
230
139
    pbScratch = SymCryptCallbackAlloc( cbScratch );
231
139
    if ( pbScratch == NULL )
232
0
    {
233
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
234
0
        goto cleanup;
235
0
    }
236
237
    // Creating temporaries
238
139
    pCurr = pbScratch + cbScratchInternal;
239
139
    piTmp = SymCryptIntCreate( pCurr, cbInt, nDigitsInt );
240
139
    pCurr += cbInt;
241
139
    piMul = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
242
139
    pCurr += cbMul;
243
139
    poKG = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
244
139
    pCurr += cbKG;
245
139
    peMsghash = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
246
139
    pCurr += cbRs;
247
139
    peSigC = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
248
139
    pCurr += cbRs;
249
139
    peSigD = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
250
139
    pCurr += cbRs;
251
139
    peTmp = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
252
139
    pCurr += cbRs;
253
139
    pbX = pCurr;
254
255
139
    SYMCRYPT_ASSERT( piTmp != NULL);
256
139
    SYMCRYPT_ASSERT( piMul != NULL);
257
139
    SYMCRYPT_ASSERT( poKG != NULL);
258
139
    SYMCRYPT_ASSERT( peMsghash != NULL);
259
139
    SYMCRYPT_ASSERT( peSigC != NULL);
260
139
    SYMCRYPT_ASSERT( peSigD != NULL);
261
139
    SYMCRYPT_ASSERT( peTmp != NULL);
262
263
    // Truncate the message according to the flags
264
139
    scError = SymCryptEcDsaTruncateHash(
265
139
                    pCurve,
266
139
                    pbHashValue,
267
139
                    cbHashValue,
268
139
                    flags,
269
139
                    peMsghash,
270
139
                    piTmp,
271
139
                    pbScratch,
272
139
                    cbScratchInternal );
273
139
    if ( scError != SYMCRYPT_NO_ERROR )
274
0
    {
275
0
        goto cleanup;
276
0
    }
277
278
    //
279
    // Main loop: Stop when both c and d are not zero (unless a specific k is provided)
280
    //
281
139
    while( TRUE )
282
139
    {
283
139
        if ( piK == NULL )
284
0
        {
285
0
            SymCryptEcpointSetRandom( pCurve, piMul, poKG, pbScratch, cbScratchInternal );          // Generate k and k*G
286
0
            SymCryptIntToModElement( piMul, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal );
287
0
        }
288
139
        else
289
139
        {
290
            // Ensure that piK is in the range [1, GOrd-1]
291
139
            if( SymCryptIntIsEqualUint32( piK, 0 ) ||
292
139
                !SymCryptIntIsLessThan( piK, SymCryptIntFromModulus( pCurve->GOrd ) ) )
293
5
            {
294
5
                scError = SYMCRYPT_INVALID_ARGUMENT;
295
5
                goto cleanup;
296
5
            }
297
298
134
            SymCryptIntCopy( piK, piMul );
299
134
            SymCryptIntToModElement( piMul, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal );
300
301
134
            scError = SymCryptEcpointScalarMul( pCurve, piMul, NULL, 0, poKG, pbScratch, cbScratchInternal );  // Generate k*G
302
134
            if ( scError != SYMCRYPT_NO_ERROR )
303
0
            {
304
0
                goto cleanup;
305
0
            }
306
134
        }
307
308
134
        scError = SymCryptModInv( pCurve->GOrd, peTmp, peTmp, 0, pbScratch, cbScratchInternal );              // Invert k
309
134
        if ( scError != SYMCRYPT_NO_ERROR )
310
0
        {
311
0
            goto cleanup;
312
0
        }
313
314
        // Get the x coordinates from KG
315
134
        scError = SymCryptEcpointGetValue(
316
134
                        pCurve,
317
134
                        poKG,
318
134
                        SYMCRYPT_NUMBER_FORMAT_MSB_FIRST,
319
134
                        SYMCRYPT_ECPOINT_FORMAT_X,
320
134
                        pbX,
321
134
                        cbX,
322
134
                        0,
323
134
                        pbScratch,
324
134
                        cbScratchInternal );
325
134
        if ( scError != SYMCRYPT_NO_ERROR )
326
0
        {
327
0
            goto cleanup;
328
0
        }
329
330
        // Store c = x(KG) as an integer
331
134
        scError = SymCryptModElementSetValue( pbX, cbX, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, pCurve->GOrd, peSigC, pbScratch, cbScratch );
332
134
        if ( scError != SYMCRYPT_NO_ERROR )
333
0
        {
334
0
            goto cleanup;
335
0
        }
336
337
        // Move the private key into peSigD
338
134
        SymCryptIntToModElement( pKey->piPrivateKey, pCurve->GOrd, peSigD, pbScratch, cbScratchInternal );
339
340
        // Multiply the private key by h since its internal format is "DivH"
341
172
        for (UINT32 i=0; i<pCurve->coFactorPower; i++)
342
38
        {
343
38
            SymCryptModAdd( pCurve->GOrd, peSigD, peSigD, peSigD, pbScratch, cbScratchInternal );
344
38
        }
345
346
134
        SymCryptModMul( pCurve->GOrd, peSigC, peSigD, peSigD, pbScratch, cbScratchInternal );                   // s * c
347
134
        SymCryptModAdd( pCurve->GOrd, peMsghash, peSigD, peSigD, pbScratch, cbScratchInternal );                // msghash + s*c
348
134
        SymCryptModMul( pCurve->GOrd, peSigD, peTmp, peSigD, pbScratch, cbScratchInternal );                    // ( msghash + s*c ) / k
349
350
134
        if ( !( SymCryptModElementIsZero( pCurve->GOrd, peSigC ) |
351
134
                SymCryptModElementIsZero( pCurve->GOrd, peSigD ) ) )
352
134
        {
353
134
            break;
354
134
        }
355
356
0
        if (piK != NULL)
357
0
        {
358
            // piK resulted in 0 signature
359
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
360
0
            goto cleanup;
361
0
        }
362
363
0
        signatureCount++;
364
0
        if ( signatureCount >= SYMCRYPT_MAX_ECDSA_SIGNATURE_COUNT )
365
0
        {
366
            // We have not generated a non-zero signature after SYMCRYPT_MAX_ECDSA_SIGNATURE_COUNT attempts;
367
            // Something is wrong with the group setup
368
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
369
0
            goto cleanup;
370
0
        }
371
0
    }
372
373
    // Output c
374
134
    scError = SymCryptModElementGetValue( pCurve->GOrd, peSigC, pbSignature, cbSignature / 2, format, pbScratch, cbScratchInternal );
375
134
    if ( scError != SYMCRYPT_NO_ERROR )
376
0
    {
377
0
        goto cleanup;
378
0
    }
379
380
    // Output d
381
134
    scError = SymCryptModElementGetValue( pCurve->GOrd, peSigD, pbSignature + cbSignature / 2, cbSignature / 2, format, pbScratch, cbScratchInternal );
382
134
    if ( scError != SYMCRYPT_NO_ERROR )
383
0
    {
384
0
        goto cleanup;
385
0
    }
386
387
139
cleanup:
388
139
    if ( pbScratch != NULL )
389
139
    {
390
139
        SymCryptWipe( pbScratch, cbScratch );
391
139
        SymCryptCallbackFree( pbScratch );
392
139
    }
393
394
139
    if (scError != SYMCRYPT_NO_ERROR)
395
5
    {
396
5
        SymCryptWipe( pbSignature, cbSignature );
397
5
    }
398
399
139
    return scError;
400
134
}
401
402
403
SYMCRYPT_ERROR
404
SYMCRYPT_CALL
405
SymCryptEcDsaSign(
406
    _In_                                PCSYMCRYPT_ECKEY        pKey,
407
    _In_reads_bytes_( cbHashValue )     PCBYTE                  pbHashValue,
408
                                        SIZE_T                  cbHashValue,
409
                                        SYMCRYPT_NUMBER_FORMAT  format,
410
                                        UINT32                  flags,
411
    _Out_writes_bytes_( cbSignature )   PBYTE                   pbSignature,
412
                                        SIZE_T                  cbSignature )
413
0
{
414
    // We must have a private key to perform PCT or signature
415
0
    if( !pKey->hasPrivateKey || !(pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) )
416
0
    {
417
0
        return SYMCRYPT_INVALID_ARGUMENT;
418
0
    }
419
420
    // If the key was generated and a PCT has not yet been performed - perform PCT before first use
421
0
    SYMCRYPT_RUN_KEY_PCT(
422
0
        SymCryptEcDsaPct,
423
0
        pKey,
424
0
        SYMCRYPT_PCT_ECDSA );
425
426
0
    return SymCryptEcDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
427
0
}
428
429
SYMCRYPT_ERROR
430
SYMCRYPT_CALL
431
SymCryptEcDsaVerify(
432
    _In_                                PCSYMCRYPT_ECKEY        pKey,
433
    _In_reads_bytes_( cbHashValue )     PCBYTE                  pbHashValue,
434
                                        SIZE_T                  cbHashValue,
435
    _In_reads_bytes_( cbSignature )     PCBYTE                  pbSignature,
436
                                        SIZE_T                  cbSignature,
437
                                        SYMCRYPT_NUMBER_FORMAT  format,
438
                                        UINT32                  flags )
439
191
{
440
191
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
441
191
    PBYTE   pbScratch = NULL;
442
191
    SIZE_T  cbScratch = 0;
443
191
    SIZE_T  cbScratchInternal = 0;
444
191
    PBYTE   pCurr = NULL;
445
191
    BOOLEAN fValidSignature = FALSE;
446
447
191
    PCSYMCRYPT_ECURVE       pCurve = pKey->pCurve;
448
449
191
    PSYMCRYPT_INT           piTmp = NULL;
450
191
    PSYMCRYPT_INT           piMul1 = NULL;
451
191
    PSYMCRYPT_INT           piMul2 = NULL;
452
191
    PSYMCRYPT_ECPOINT       poQ1 = NULL;
453
191
    PSYMCRYPT_ECPOINT       poQ2 = NULL;
454
455
191
    PSYMCRYPT_MODELEMENT    peMsghash = NULL;
456
191
    PSYMCRYPT_MODELEMENT    peSigC = NULL;
457
191
    PSYMCRYPT_MODELEMENT    peSigD = NULL;
458
191
    PSYMCRYPT_MODELEMENT    peTmp = NULL;
459
460
191
    PBYTE                   pbX = NULL;
461
191
    PCSYMCRYPT_ECPOINT      poTable[2] = { 0 };
462
191
    PCSYMCRYPT_INT          piTable[2] = { 0 };
463
464
191
    UINT32  nDigitsInt = 0;
465
191
    UINT32  nDigitsMul = 0;
466
467
191
    UINT32  cbInt = 0;
468
191
    UINT32  cbMul = 0;
469
191
    UINT32  cbKG = 0;
470
191
    UINT32  cbRs = 0;
471
191
    UINT32  cbX  = 0;
472
473
    // Make sure that the key may be used in ECDSA
474
191
    if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) == 0)  )
475
0
    {
476
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
477
0
        goto cleanup;
478
0
    }
479
480
    // Make sure that only the correct flags are set
481
191
    if ( (flags & ~SYMCRYPT_FLAG_ECDSA_NO_TRUNCATION) != 0 )
482
0
    {
483
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
484
0
        goto cleanup;
485
0
    }
486
487
    // Calculating the digits for the temporary integer
488
191
    nDigitsInt = SYMCRYPT_MAX( pCurve->FModDigits, pCurve->GOrdDigits );
489
191
    nDigitsInt = SYMCRYPT_MAX( nDigitsInt, SymCryptDigitsFromBits( (UINT32)cbSignature * 4 ) );  // pbSignature contains (c,d)
490
491
191
    nDigitsMul = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
492
493
    // Objects and scratch space size calculation
494
191
    cbInt = SymCryptSizeofIntFromDigits( nDigitsInt );
495
191
    cbMul = SymCryptSizeofIntFromDigits( nDigitsMul );
496
191
    cbKG = SymCryptSizeofEcpointFromCurve( pCurve );
497
191
    cbRs = SymCryptSizeofModElementFromModulus( pCurve->GOrd );
498
191
    cbX  = SymCryptEcurveSizeofFieldElement( pCurve );
499
500
191
    cbScratchInternal = SYMCRYPT_SCRATCH_BYTES_FOR_MULTI_SCALAR_ECURVE_OPERATIONS( pCurve, 2 );
501
191
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->GOrdDigits ) );
502
191
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pCurve->FModDigits ) );
503
191
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( pCurve->GOrdDigits ) );
504
191
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_GETSET_VALUE_ECURVE_OPERATIONS( pCurve ) );
505
191
    cbScratchInternal = SYMCRYPT_MAX( cbScratchInternal, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_ECURVE_OPERATIONS( pCurve ) );
506
507
    //
508
    // From symcrypt_internal.h we have:
509
    //      - sizeof results are upper bounded by 2^19
510
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
511
    // Thus the following calculation does not overflow cbScratch.
512
    //
513
191
    cbScratch = cbScratchInternal + cbInt + 2*cbMul + 2*cbKG + 4*cbRs + cbX;
514
515
    // Scratch space allocation
516
191
    pbScratch = SymCryptCallbackAlloc( cbScratch );
517
191
    if ( pbScratch == NULL )
518
0
    {
519
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
520
0
        goto cleanup;
521
0
    }
522
523
    // Creating temporaries
524
191
    pCurr = pbScratch + cbScratchInternal;
525
191
    piTmp = SymCryptIntCreate( pCurr, cbInt, nDigitsInt );
526
191
    pCurr += cbInt;
527
191
    piMul1 = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
528
191
    pCurr += cbMul;
529
191
    piMul2 = SymCryptIntCreate( pCurr, cbMul, nDigitsMul );
530
191
    pCurr += cbMul;
531
191
    poQ1 = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
532
191
    pCurr += cbKG;
533
191
    poQ2 = SymCryptEcpointCreate( pCurr, cbKG, pCurve );
534
191
    pCurr += cbKG;
535
191
    peMsghash = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
536
191
    pCurr += cbRs;
537
191
    peSigC = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
538
191
    pCurr += cbRs;
539
191
    peSigD = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
540
191
    pCurr += cbRs;
541
191
    peTmp = SymCryptModElementCreate( pCurr, cbRs, pCurve->GOrd );
542
191
    pCurr += cbRs;
543
191
    pbX = pCurr;
544
545
191
    SYMCRYPT_ASSERT( piTmp != NULL);
546
191
    SYMCRYPT_ASSERT( piMul1 != NULL);
547
191
    SYMCRYPT_ASSERT( piMul2 != NULL);
548
191
    SYMCRYPT_ASSERT( poQ1 != NULL);
549
191
    SYMCRYPT_ASSERT( poQ2 != NULL);
550
191
    SYMCRYPT_ASSERT( peMsghash != NULL);
551
191
    SYMCRYPT_ASSERT( peSigC != NULL);
552
191
    SYMCRYPT_ASSERT( peSigD != NULL);
553
191
    SYMCRYPT_ASSERT( peTmp != NULL);
554
555
    // Get c
556
191
    scError = SymCryptIntSetValue( pbSignature, cbSignature / 2, format, piTmp );
557
191
    if ( scError != SYMCRYPT_NO_ERROR )
558
0
    {
559
0
        goto cleanup;
560
0
    }
561
562
    // Check if c is less than r
563
191
    if ( !SymCryptIntIsLessThan( piTmp, SymCryptIntFromModulus( pCurve->GOrd ) ) )
564
0
    {
565
0
        goto cleanup;
566
0
    }
567
568
    // c mod r
569
191
    SymCryptIntToModElement( piTmp, pCurve->GOrd, peSigC, pbScratch, cbScratchInternal );
570
571
    // Check if c is zero
572
191
    if (SymCryptModElementIsZero( pCurve->GOrd, peSigC ))
573
0
    {
574
0
        goto cleanup;
575
0
    }
576
577
    // Get d
578
191
    scError = SymCryptIntSetValue( pbSignature + cbSignature / 2, cbSignature / 2, format, piTmp );
579
191
    if ( scError != SYMCRYPT_NO_ERROR )
580
0
    {
581
0
        goto cleanup;
582
0
    }
583
584
    // Check if d is less than r
585
191
    if ( !SymCryptIntIsLessThan( piTmp, SymCryptIntFromModulus( pCurve->GOrd ) ) )
586
0
    {
587
0
        goto cleanup;
588
0
    }
589
590
    // d mod r
591
191
    SymCryptIntToModElement( piTmp, pCurve->GOrd, peSigD, pbScratch, cbScratchInternal );
592
593
    // Check if d is zero
594
191
    if (SymCryptModElementIsZero( pCurve->GOrd, peSigD ))
595
0
    {
596
0
        goto cleanup;
597
0
    }
598
599
    // Calculate 1/d mod r
600
    // The D value is not secret; it is part of the signature.
601
    // We mark it public to avoid the use of random blinding, which would require a source of randomness
602
    // just to verify an ECDSA signature.
603
191
    scError = SymCryptModInv( pCurve->GOrd, peSigD, peSigD, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratchInternal );
604
191
    if( scError != SYMCRYPT_NO_ERROR )
605
0
    {
606
0
        goto cleanup;
607
0
    }
608
609
    // Truncate the message according to the flags
610
191
    scError = SymCryptEcDsaTruncateHash(
611
191
                    pCurve,
612
191
                    pbHashValue,
613
191
                    cbHashValue,
614
191
                    flags,
615
191
                    peMsghash,
616
191
                    piTmp,
617
191
                    pbScratch,
618
191
                    cbScratchInternal );
619
191
    if ( scError != SYMCRYPT_NO_ERROR )
620
0
    {
621
0
        goto cleanup;
622
0
    }
623
624
191
    SymCryptModMul( pCurve->GOrd, peMsghash, peSigD, peMsghash, pbScratch, cbScratchInternal );     // msghash / d = h1
625
191
    SymCryptModMul( pCurve->GOrd, peSigC, peSigD, peTmp, pbScratch, cbScratchInternal );            // c / d = h2
626
627
191
    SymCryptModElementToInt( pCurve->GOrd, peMsghash, piMul1, pbScratch, cbScratchInternal );
628
191
    SymCryptModElementToInt( pCurve->GOrd, peTmp, piMul2, pbScratch, cbScratchInternal );
629
630
    // h1*G + h2*W
631
191
    piTable[0] = piMul1;
632
191
    piTable[1] = piMul2;
633
634
191
    poTable[0] = NULL;  // The first base point is the generator G of the group
635
191
    poTable[1] = pKey->poPublicKey;
636
637
191
    scError = SymCryptEcpointMultiScalarMul( pCurve, piTable, poTable, 2, SYMCRYPT_FLAG_DATA_PUBLIC, poQ1, pbScratch, cbScratchInternal );
638
191
    if ( scError != SYMCRYPT_NO_ERROR )
639
0
    {
640
0
        goto cleanup;
641
0
    }
642
643
    // Check for point at infinity
644
191
    if ( SymCryptEcpointIsZero( pCurve, poQ1, pbScratch, cbScratchInternal ) )
645
0
    {
646
0
        goto cleanup;
647
0
    }
648
649
    // Get the x from poQ1
650
191
    scError = SymCryptEcpointGetValue( pCurve, poQ1, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, SYMCRYPT_ECPOINT_FORMAT_X, pbX, cbX, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratch, cbScratchInternal);
651
191
    if ( scError != SYMCRYPT_NO_ERROR )
652
0
    {
653
0
        goto cleanup;
654
0
    }
655
656
    // Store it in a big enough INT
657
191
    scError = SymCryptIntSetValue( pbX, cbX, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTmp );
658
191
    if ( scError != SYMCRYPT_NO_ERROR )
659
0
    {
660
0
        goto cleanup;
661
0
    }
662
663
191
    SymCryptIntToModElement( piTmp, pCurve->GOrd, peTmp, pbScratch, cbScratchInternal );    // x mod r
664
665
    // Comparison c = x
666
191
    if (SymCryptModElementIsEqual( pCurve->GOrd, peSigC, peTmp ))
667
131
    {
668
131
        fValidSignature = TRUE;
669
131
    }
670
671
191
cleanup:
672
673
191
    if (!fValidSignature)
674
60
    {
675
60
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
676
60
    }
677
678
191
    if ( pbScratch != NULL )
679
191
    {
680
191
        SymCryptWipe( pbScratch, cbScratch );
681
191
        SymCryptCallbackFree( pbScratch );
682
191
    }
683
684
191
    return scError;
685
191
}