Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/dsa.c
Line
Count
Source (jump to first uncovered line)
1
//
2
// dsa.c   DSA functions
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
// Truncating function according to the FIPS 186-4 standard
11
SYMCRYPT_ERROR
12
SYMCRYPT_CALL
13
SymCryptDsaTruncateHash(
14
    _In_                            PCSYMCRYPT_DLGROUP      pDlgroup,
15
    _In_reads_bytes_( cbHashValue ) PCBYTE                  pbHashValue,
16
                                    SIZE_T                  cbHashValue,
17
                                    UINT32                  flags,
18
    _Out_                           PSYMCRYPT_MODELEMENT    peMsghash,
19
    _Out_                           PSYMCRYPT_INT           piIntLarge,
20
    _Out_                           PSYMCRYPT_INT           piIntQ,
21
    _Out_writes_bytes_( cbScratch ) PBYTE                   pbScratch,
22
                                    SIZE_T                  cbScratch )
23
0
{
24
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
25
26
0
    UNREFERENCED_PARAMETER( flags );
27
28
    // Get the value of msghash into piIntLarge
29
0
    scError = SymCryptIntSetValue( pbHashValue, cbHashValue, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piIntLarge );
30
0
    if ( scError != SYMCRYPT_NO_ERROR )
31
0
    {
32
0
        goto cleanup;
33
0
    }
34
35
    // Truncate the rightmost bits if the value exceeds the size of the modulus Q
36
0
    if (SymCryptIntBitsizeOfValue(piIntLarge) > pDlgroup->nBitsOfQ)
37
0
    {
38
0
        SymCryptIntDivPow2( piIntLarge, SymCryptIntBitsizeOfValue(piIntLarge) - pDlgroup->nBitsOfQ, piIntLarge );
39
0
    }
40
41
0
    scError = SymCryptIntCopyMixedSize( piIntLarge, piIntQ );
42
0
    if ( scError != SYMCRYPT_NO_ERROR )
43
0
    {
44
        // This should never fail here as we truncated the IntLarge
45
0
        goto cleanup;
46
0
    }
47
48
    // Now we can call IntToModElement as they have the same digit size
49
0
    SymCryptIntToModElement( piIntQ, pDlgroup->pmQ, peMsghash, pbScratch, cbScratch );        // msghash mod Q
50
51
0
cleanup:
52
0
    return scError;
53
0
}
54
55
0
#define SYMCRYPT_MAX_DSA_SIGNATURE_COUNT (100)
56
57
SYMCRYPT_ERROR
58
SYMCRYPT_CALL
59
SymCryptDsaSignEx(
60
    _In_                                PCSYMCRYPT_DLKEY        pKey,
61
    _In_reads_bytes_( cbHashValue )     PCBYTE                  pbHashValue,
62
                                        SIZE_T                  cbHashValue,
63
    _In_opt_                            PCSYMCRYPT_INT          piK,
64
                                        SYMCRYPT_NUMBER_FORMAT  format,
65
                                        UINT32                  flags,
66
    _Out_writes_bytes_( cbSignature )   PBYTE                   pbSignature,
67
                                        SIZE_T                  cbSignature )
68
0
{
69
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
70
71
0
    PBYTE   pbScratch = NULL;
72
0
    SIZE_T  cbScratch = 0;
73
0
    PBYTE   pbScratchInternal = NULL;
74
0
    SIZE_T  cbScratchInternal = 0;
75
76
0
    SIZE_T  cbScratchInputK = 0;        // Extra scratch space needed if the caller specified a K
77
78
0
    PCSYMCRYPT_DLGROUP pDlgroup = pKey->pDlgroup;
79
0
    UINT32 nDigitsOfP = pDlgroup->nDigitsOfP;
80
0
    UINT32 nDigitsOfQ = pDlgroup->nDigitsOfQ;
81
82
0
    UINT32 ndIntLarge = 0;
83
84
0
    UINT32 cbIntLarge = 0;
85
0
    UINT32 cbIntQ = 0;
86
0
    UINT32 cbIntP = 0;
87
88
0
    UINT32 cbModelementP = 0;
89
0
    UINT32 cbModelementQ = 0;
90
91
    // Helper Integers
92
0
    PSYMCRYPT_INT piIntLarge = NULL;    // Safe size for all caller specified sizes
93
0
    PSYMCRYPT_INT piIntP = NULL;        // Same number of digits as P
94
0
    PSYMCRYPT_INT piIntQ = NULL;        // Same number of digits as Q
95
96
    // Elements modulo P
97
0
    PSYMCRYPT_MODELEMENT peRmodP = NULL;
98
99
    // Elements modulo Q
100
0
    PSYMCRYPT_MODELEMENT peMsghash = NULL;
101
0
    PSYMCRYPT_MODELEMENT peRmodQ = NULL;
102
0
    PSYMCRYPT_MODELEMENT peK = NULL;
103
0
    PSYMCRYPT_MODELEMENT peS = NULL;
104
105
0
    UINT32 signatureCount = 0;
106
107
0
    UNREFERENCED_PARAMETER( flags );
108
109
    // Make sure that the key may be used in DSA
110
0
    if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DSA) == 0) )
111
0
    {
112
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
113
0
        goto cleanup;
114
0
    }
115
116
    // Make sure that the group and the key have all the
117
    // information for dsa, i.e. prime q and private key
118
    // modulo q, and we are not using a named DH safe-prime
119
    // group
120
0
    if ((!pDlgroup->fHasPrimeQ) ||
121
0
        (!pKey->fHasPrivateKey) ||
122
0
        (!pKey->fPrivateModQ) ||
123
0
        (pDlgroup->isSafePrimeGroup))
124
0
    {
125
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
126
0
        goto cleanup;
127
0
    }
128
129
    // Calculate the digit size for the HashValue
130
0
    ndIntLarge = SymCryptDigitsFromBits( (UINT32)cbHashValue * 8 );
131
132
    // Calculate the sizes of temp objects
133
0
    cbIntLarge = SymCryptSizeofIntFromDigits(ndIntLarge);
134
0
    cbIntQ = SymCryptSizeofIntFromDigits(nDigitsOfQ);
135
0
    cbIntP = SymCryptSizeofIntFromDigits(nDigitsOfP);
136
137
0
    cbModelementP = SymCryptSizeofModElementFromModulus( pDlgroup-> pmP );
138
0
    cbModelementQ = SymCryptSizeofModElementFromModulus( pDlgroup-> pmQ );
139
140
    // Allocate scratch space
141
0
    cbScratchInputK = (piK==NULL)?0:SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD(SymCryptIntDigitsizeOfObject(piK),nDigitsOfQ);
142
143
    //
144
    // From symcrypt_internal.h we have:
145
    //      - sizeof results are upper bounded by 2^19
146
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
147
    // Thus the following calculation does not overflow cbScratch.
148
    //
149
0
    cbScratch = cbIntLarge + cbIntQ + cbIntP + cbModelementP + 4*cbModelementQ +
150
0
                SYMCRYPT_MAX( cbScratchInputK,
151
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfQ ),
152
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ),
153
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( nDigitsOfP ),
154
0
                     SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( nDigitsOfQ ) ))));
155
0
    pbScratch = SymCryptCallbackAlloc( cbScratch );
156
0
    if (pbScratch==NULL)
157
0
    {
158
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
159
0
        goto cleanup;
160
0
    }
161
162
    // Create the objects
163
0
    pbScratchInternal = pbScratch;
164
0
    cbScratchInternal = cbScratch;
165
166
0
    piIntLarge = SymCryptIntCreate(pbScratchInternal, cbIntLarge, ndIntLarge); pbScratchInternal += cbIntLarge; cbScratchInternal -= cbIntLarge;
167
0
    piIntQ = SymCryptIntCreate(pbScratchInternal, cbIntQ, nDigitsOfQ); pbScratchInternal += cbIntQ; cbScratchInternal -= cbIntQ;
168
0
    piIntP = SymCryptIntCreate(pbScratchInternal, cbIntP, nDigitsOfP); pbScratchInternal += cbIntP; cbScratchInternal -= cbIntP;
169
170
0
    peRmodP = SymCryptModElementCreate(pbScratchInternal, cbModelementP, pDlgroup->pmP); pbScratchInternal += cbModelementP; cbScratchInternal -= cbModelementP;
171
172
0
    peMsghash = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
173
0
    peRmodQ = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
174
0
    peK = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
175
0
    peS = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
176
177
    // Get the message into a modelement
178
0
    scError = SymCryptDsaTruncateHash(
179
0
                    pDlgroup,
180
0
                    pbHashValue,
181
0
                    cbHashValue,
182
0
                    flags,
183
0
                    peMsghash,
184
0
                    piIntLarge,
185
0
                    piIntQ,
186
0
                    pbScratchInternal,
187
0
                    cbScratchInternal );
188
0
    if (scError!=SYMCRYPT_NO_ERROR)
189
0
    {
190
0
        goto cleanup;
191
0
    }
192
193
    //
194
    // Main loop: Stop when both R and S are not zero (unless a specific k is provided)
195
    //
196
0
    while( TRUE )
197
0
    {
198
0
        if (piK==NULL)
199
0
        {
200
0
            SymCryptModSetRandom(
201
0
                pDlgroup->pmQ,
202
0
                peK,
203
0
                SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE|SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE,
204
0
                pbScratchInternal,
205
0
                cbScratchInternal );
206
207
0
            SymCryptModElementToInt(
208
0
                pDlgroup->pmQ,
209
0
                peK,
210
0
                piIntQ,
211
0
                pbScratchInternal,
212
0
                cbScratchInternal );
213
0
        }
214
0
        else
215
0
        {
216
0
            SymCryptIntDivMod(
217
0
                piK,
218
0
                SymCryptDivisorFromModulus( pDlgroup->pmQ ),
219
0
                NULL,
220
0
                piIntQ,
221
0
                pbScratchInternal,
222
0
                cbScratchInternal );
223
224
0
            SymCryptIntToModElement(
225
0
                piIntQ,
226
0
                pDlgroup->pmQ,
227
0
                peK,
228
0
                pbScratchInternal,
229
0
                cbScratchInternal );
230
231
            // Make sure that the K passed in is not zero
232
0
            if (SymCryptModElementIsZero(pDlgroup->pmQ, peK))
233
0
            {
234
0
                scError = SYMCRYPT_INVALID_ARGUMENT;
235
0
                goto cleanup;
236
0
            }
237
0
        }
238
239
        // Here piIntQ and peK hold the random exponent K
240
241
        // G^K mod P
242
0
        SymCryptModExp(
243
0
                pDlgroup->pmP,
244
0
                pDlgroup->peG,
245
0
                piIntQ,
246
0
                pDlgroup->nBitsOfQ,
247
0
                0,      // Side-channel safe
248
0
                peRmodP,
249
0
                pbScratchInternal,
250
0
                cbScratchInternal );
251
252
        // Convert to integer
253
0
        SymCryptModElementToInt(
254
0
                pDlgroup->pmP,
255
0
                peRmodP,
256
0
                piIntP,
257
0
                pbScratchInternal,
258
0
                cbScratchInternal );
259
260
        // Convert to mod Q
261
0
        SymCryptIntDivMod(
262
0
                piIntP,
263
0
                SymCryptDivisorFromModulus( pDlgroup->pmQ ),
264
0
                NULL,
265
0
                piIntQ,
266
0
                pbScratchInternal,
267
0
                cbScratchInternal );
268
269
        // Convert to modelement
270
0
        SymCryptIntToModElement(
271
0
                piIntQ,
272
0
                pDlgroup->pmQ,
273
0
                peRmodQ,
274
0
                pbScratchInternal,
275
0
                cbScratchInternal );
276
277
        // Invert k mod q
278
0
        scError = SymCryptModInv(
279
0
                pDlgroup->pmQ,
280
0
                peK,
281
0
                peK,    // In place
282
0
                0,
283
0
                pbScratchInternal,
284
0
                cbScratchInternal );
285
0
        if( scError != SYMCRYPT_NO_ERROR )
286
0
        {
287
0
            goto cleanup;
288
0
        }
289
290
        // Get the private key X to modelement
291
        // *** We are sure here that the digit
292
        // size of it is nDigitsOfQ
293
0
        SymCryptIntToModElement(
294
0
                pKey->piPrivateKey,
295
0
                pDlgroup->pmQ,
296
0
                peS,
297
0
                pbScratchInternal,
298
0
                cbScratchInternal );
299
300
        // X*R
301
0
        SymCryptModMul(
302
0
                pDlgroup->pmQ,
303
0
                peS,
304
0
                peRmodQ,
305
0
                peS,
306
0
                pbScratchInternal,
307
0
                cbScratchInternal );
308
309
        // H(m)+X*R
310
0
        SymCryptModAdd(
311
0
                pDlgroup->pmQ,
312
0
                peS,
313
0
                peMsghash,
314
0
                peS,
315
0
                pbScratchInternal,
316
0
                cbScratchInternal );
317
318
        // S = k^{-1}*(H(m)+X*R)
319
0
        SymCryptModMul(
320
0
                pDlgroup->pmQ,
321
0
                peK,
322
0
                peS,
323
0
                peS,
324
0
                pbScratchInternal,
325
0
                cbScratchInternal );
326
327
0
        if ( !( SymCryptModElementIsZero( pDlgroup->pmQ, peRmodQ ) |
328
0
                SymCryptModElementIsZero( pDlgroup->pmQ, peS ) ) )
329
0
        {
330
0
            break;
331
0
        }
332
333
0
        if (piK != NULL)
334
0
        {
335
            // piK resulted in 0 signature
336
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
337
0
            goto cleanup;
338
0
        }
339
340
0
        signatureCount++;
341
0
        if ( signatureCount >= SYMCRYPT_MAX_DSA_SIGNATURE_COUNT )
342
0
        {
343
            // We have not generated a non-zero signature after SYMCRYPT_MAX_DSA_SIGNATURE_COUNT attempts;
344
            // Something is wrong with the group setup
345
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
346
0
            goto cleanup;
347
0
        }
348
0
    }
349
350
    // Output R
351
0
    scError = SymCryptModElementGetValue(
352
0
                pDlgroup->pmQ,
353
0
                peRmodQ,
354
0
                pbSignature,
355
0
                cbSignature / 2,
356
0
                format,
357
0
                pbScratchInternal,
358
0
                cbScratchInternal );
359
0
    if ( scError != SYMCRYPT_NO_ERROR )
360
0
    {
361
0
        goto cleanup;
362
0
    }
363
364
    // Output S
365
0
    scError = SymCryptModElementGetValue(
366
0
                pDlgroup->pmQ,
367
0
                peS,
368
0
                pbSignature + cbSignature / 2,
369
0
                cbSignature / 2,
370
0
                format,
371
0
                pbScratchInternal,
372
0
                cbScratchInternal );
373
0
    if ( scError != SYMCRYPT_NO_ERROR )
374
0
    {
375
0
        goto cleanup;
376
0
    }
377
378
0
cleanup:
379
0
    if ( pbScratch != NULL )
380
0
    {
381
0
        SymCryptWipe( pbScratch, cbScratch );
382
0
        SymCryptCallbackFree( pbScratch );
383
0
    }
384
385
0
    if (scError != SYMCRYPT_NO_ERROR)
386
0
    {
387
0
        SymCryptWipe( pbSignature, cbSignature );
388
0
    }
389
390
0
    return scError;
391
0
}
392
393
SYMCRYPT_ERROR
394
SYMCRYPT_CALL
395
SymCryptDsaSign(
396
    _In_                                PCSYMCRYPT_DLKEY        pKey,
397
    _In_reads_bytes_( cbHashValue )     PCBYTE                  pbHashValue,
398
                                        SIZE_T                  cbHashValue,
399
                                        SYMCRYPT_NUMBER_FORMAT  format,
400
                                        UINT32                  flags,
401
    _Out_writes_bytes_( cbSignature )   PBYTE                   pbSignature,
402
                                        SIZE_T                  cbSignature )
403
0
{
404
0
    return SymCryptDsaSignEx( pKey, pbHashValue, cbHashValue, NULL, format, flags, pbSignature, cbSignature );
405
0
}
406
407
408
SYMCRYPT_ERROR
409
SYMCRYPT_CALL
410
SymCryptDsaVerify(
411
    _In_                                PCSYMCRYPT_DLKEY        pKey,
412
    _In_reads_bytes_( cbHashValue )     PCBYTE                  pbHashValue,
413
                                        SIZE_T                  cbHashValue,
414
    _In_reads_bytes_( cbSignature )     PCBYTE                  pbSignature,
415
                                        SIZE_T                  cbSignature,
416
                                        SYMCRYPT_NUMBER_FORMAT  format,
417
                                        UINT32                  flags )
418
0
{
419
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
420
0
    BOOLEAN fValidSignature = FALSE;
421
422
0
    PBYTE   pbScratch = NULL;
423
0
    SIZE_T  cbScratch = 0;
424
0
    PBYTE   pbScratchInternal = NULL;
425
0
    SIZE_T  cbScratchInternal = 0;
426
427
0
    PCSYMCRYPT_DLGROUP pDlgroup = pKey->pDlgroup;
428
0
    UINT32 nDigitsOfP = pDlgroup->nDigitsOfP;
429
0
    UINT32 nDigitsOfQ = pDlgroup->nDigitsOfQ;
430
431
0
    UINT32 ndIntLarge = 0;
432
433
0
    UINT32 cbIntLarge = 0;
434
0
    UINT32 cbIntQ = 0;
435
0
    UINT32 cbIntP = 0;
436
437
0
    UINT32 cbModelementP = 0;
438
0
    UINT32 cbModelementQ = 0;
439
440
0
    PSYMCRYPT_MODELEMENT peBases[2] = { NULL, NULL }; // Array with pointers to base points
441
442
    // Helper Integers
443
0
    PSYMCRYPT_INT piIntLarge = NULL;            // Safe size for all caller specified sizes
444
0
    PSYMCRYPT_INT piIntP = NULL;                // Same number of digits as P
445
0
    PSYMCRYPT_INT piIntQ[2] = { NULL, NULL };   // Same number of digits as Q
446
447
    // Elements modulo P
448
0
    PSYMCRYPT_MODELEMENT peResP = NULL;
449
450
    // Elements modulo Q
451
0
    PSYMCRYPT_MODELEMENT peR = NULL;
452
0
    PSYMCRYPT_MODELEMENT peS = NULL;
453
0
    PSYMCRYPT_MODELEMENT peT = NULL;    // Temp
454
455
0
    UNREFERENCED_PARAMETER( flags );
456
457
    // Make sure that the key may be used in DSA
458
0
    if ( ((pKey->fAlgorithmInfo & SYMCRYPT_FLAG_DLKEY_DSA) == 0) )
459
0
    {
460
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
461
0
        goto cleanup;
462
0
    }
463
464
    // Make sure that the group has a prime q, and we are not using a named DH safe-prime group
465
0
    if (!pDlgroup->fHasPrimeQ || pDlgroup->isSafePrimeGroup)
466
0
    {
467
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
468
0
        goto cleanup;
469
0
    }
470
471
    // Calculate the digit sizes
472
0
    ndIntLarge = SymCryptDigitsFromBits( (UINT32)cbHashValue * 8 );
473
0
    ndIntLarge = SYMCRYPT_MAX( ndIntLarge, SymCryptDigitsFromBits( (UINT32)cbSignature * 4 ) );  // pbSignature contains (R,S)
474
475
    // Calculate the sizes of temp objects
476
0
    cbIntLarge = SymCryptSizeofIntFromDigits(ndIntLarge);
477
0
    cbIntQ = SymCryptSizeofIntFromDigits(nDigitsOfQ);
478
0
    cbIntP = SymCryptSizeofIntFromDigits(nDigitsOfP);
479
480
0
    cbModelementP = SymCryptSizeofModElementFromModulus( pDlgroup-> pmP );
481
0
    cbModelementQ = SymCryptSizeofModElementFromModulus( pDlgroup-> pmQ );
482
483
    //
484
    // From symcrypt_internal.h we have:
485
    //      - sizeof results are upper bounded by 2^19
486
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
487
    // Thus the following calculation does not overflow cbScratch.
488
    //
489
0
    cbScratch = cbIntLarge + cbIntP + 2*cbIntQ + cbModelementP + 3*cbModelementQ +
490
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD(nDigitsOfP,nDigitsOfQ),
491
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfQ ),
492
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigitsOfP ),
493
0
                SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODMULTIEXP( SymCryptModulusDigitsizeOfObject(pDlgroup->pmP), 2, pDlgroup->nBitsOfQ ),
494
0
                     SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( nDigitsOfQ ) ))));
495
0
    pbScratch = SymCryptCallbackAlloc( cbScratch );
496
0
    if (pbScratch==NULL)
497
0
    {
498
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
499
0
        goto cleanup;
500
0
    }
501
502
    // Create the objects
503
0
    pbScratchInternal = pbScratch;
504
0
    cbScratchInternal = cbScratch;
505
506
0
    piIntLarge = SymCryptIntCreate(pbScratchInternal, cbIntLarge, ndIntLarge); pbScratchInternal += cbIntLarge; cbScratchInternal -= cbIntLarge;
507
0
    piIntP = SymCryptIntCreate(pbScratchInternal, cbIntP, nDigitsOfP); pbScratchInternal += cbIntP; cbScratchInternal -= cbIntP;
508
0
    piIntQ[0] = SymCryptIntCreate(pbScratchInternal, cbIntQ, nDigitsOfQ); pbScratchInternal += cbIntQ; cbScratchInternal -= cbIntQ;
509
0
    piIntQ[1] = SymCryptIntCreate(pbScratchInternal, cbIntQ, nDigitsOfQ); pbScratchInternal += cbIntQ; cbScratchInternal -= cbIntQ;
510
511
0
    peResP = SymCryptModElementCreate(pbScratchInternal, cbModelementP, pDlgroup->pmP); pbScratchInternal += cbModelementP; cbScratchInternal -= cbModelementP;
512
513
0
    peR = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
514
0
    peS = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
515
0
    peT = SymCryptModElementCreate(pbScratchInternal, cbModelementQ, pDlgroup->pmQ); pbScratchInternal += cbModelementQ; cbScratchInternal -= cbModelementQ;
516
517
    // Get R
518
0
    scError = SymCryptIntSetValue( pbSignature, cbSignature / 2, format, piIntLarge );
519
0
    if ( scError != SYMCRYPT_NO_ERROR )
520
0
    {
521
0
        goto cleanup;
522
0
    }
523
524
    // Check if R is less than Q
525
0
    if ( !SymCryptIntIsLessThan( piIntLarge, SymCryptIntFromModulus( pDlgroup->pmQ ) ) )
526
0
    {
527
0
        goto cleanup;
528
0
    }
529
530
    // R mod Q (use piIntQ[0] as temp space)
531
0
    scError = SymCryptIntCopyMixedSize( piIntLarge, piIntQ[0] );
532
0
    if ( scError != SYMCRYPT_NO_ERROR )
533
0
    {
534
        // This should never fail here as we verified that IntLarge is less than Q
535
0
        goto cleanup;
536
0
    }
537
0
    SymCryptIntToModElement( piIntQ[0], pDlgroup->pmQ, peR, pbScratchInternal, cbScratchInternal );
538
539
    // Check if R is zero
540
0
    if (SymCryptModElementIsZero( pDlgroup->pmQ, peR ))
541
0
    {
542
0
        goto cleanup;
543
0
    }
544
545
    // Get S
546
0
    scError = SymCryptIntSetValue( pbSignature + cbSignature / 2, cbSignature / 2, format, piIntLarge );
547
0
    if ( scError != SYMCRYPT_NO_ERROR )
548
0
    {
549
0
        goto cleanup;
550
0
    }
551
552
    // Check if S is less than Q
553
0
    if ( !SymCryptIntIsLessThan( piIntLarge, SymCryptIntFromModulus( pDlgroup->pmQ ) ) )
554
0
    {
555
0
        goto cleanup;
556
0
    }
557
558
    // S mod Q (use piIntQ[0] as temp space)
559
0
    scError = SymCryptIntCopyMixedSize( piIntLarge, piIntQ[0] );
560
0
    if ( scError != SYMCRYPT_NO_ERROR )
561
0
    {
562
        // This should never fail here as we verified that IntLarge is less than Q
563
0
        goto cleanup;
564
0
    }
565
0
    SymCryptIntToModElement( piIntQ[0], pDlgroup->pmQ, peS, pbScratchInternal, cbScratchInternal );
566
567
    // Check if S is zero
568
0
    if (SymCryptModElementIsZero( pDlgroup->pmQ, peS ))
569
0
    {
570
0
        goto cleanup;
571
0
    }
572
573
    // Calculate 1/S mod Q
574
    // S is part of the signature and therefore not a secret.
575
    // We mark it public to avoid the use of random blinding, which would require a source of randomness
576
    // just to verify a DSA signature.
577
0
    scError = SymCryptModInv( pDlgroup->pmQ, peS, peS, SYMCRYPT_FLAG_DATA_PUBLIC, pbScratchInternal, cbScratchInternal );
578
0
    if( scError != SYMCRYPT_NO_ERROR )
579
0
    {
580
0
        goto cleanup;
581
0
    }
582
583
    // Get the message into a modelement
584
0
    scError = SymCryptDsaTruncateHash(
585
0
                    pDlgroup,
586
0
                    pbHashValue,
587
0
                    cbHashValue,
588
0
                    flags,
589
0
                    peT,
590
0
                    piIntLarge,
591
0
                    piIntQ[0],
592
0
                    pbScratchInternal,
593
0
                    cbScratchInternal );
594
0
    if (scError!=SYMCRYPT_NO_ERROR)
595
0
    {
596
0
        goto cleanup;
597
0
    }
598
599
    // Calculate U1 = Hash(M)/S modQ
600
0
    SymCryptModMul(
601
0
            pDlgroup->pmQ,
602
0
            peT,
603
0
            peS,
604
0
            peT,
605
0
            pbScratchInternal,
606
0
            cbScratchInternal );
607
608
    // Convert U1 to integer
609
0
    SymCryptModElementToInt(
610
0
                pDlgroup->pmQ,
611
0
                peT,
612
0
                piIntQ[0],
613
0
                pbScratchInternal,
614
0
                cbScratchInternal );
615
616
    // Calculate U2 = R/S modQ
617
0
    SymCryptModMul(
618
0
            pDlgroup->pmQ,
619
0
            peR,
620
0
            peS,
621
0
            peT,
622
0
            pbScratchInternal,
623
0
            cbScratchInternal );
624
625
    // Convert U2 to integer
626
0
    SymCryptModElementToInt(
627
0
                pDlgroup->pmQ,
628
0
                peT,
629
0
                piIntQ[1],
630
0
                pbScratchInternal,
631
0
                cbScratchInternal );
632
633
    // Arrange the pointers for v = G^U1 * Y^U2
634
0
    peBases[0] = pDlgroup->peG;
635
0
    peBases[1] = pKey->pePublicKey;
636
637
    // v = G^U1 * Y^U2
638
0
    scError = SymCryptModMultiExp(
639
0
                pDlgroup->pmP,
640
0
                peBases,
641
0
                piIntQ,
642
0
                2,
643
0
                pDlgroup->nBitsOfQ,
644
0
                SYMCRYPT_FLAG_DATA_PUBLIC,
645
0
                peResP,
646
0
                pbScratchInternal,
647
0
                cbScratchInternal );
648
0
    if (scError!=SYMCRYPT_NO_ERROR)
649
0
    {
650
0
        goto cleanup;
651
0
    }
652
653
    // Convert V to a modelement modulo Q
654
0
    SymCryptModElementToInt(
655
0
                pDlgroup->pmP,
656
0
                peResP,
657
0
                piIntP,
658
0
                pbScratchInternal,
659
0
                cbScratchInternal );
660
0
    SymCryptIntDivMod(
661
0
                piIntP,
662
0
                SymCryptDivisorFromModulus( pDlgroup->pmQ ),
663
0
                NULL,
664
0
                piIntQ[0],
665
0
                pbScratchInternal,
666
0
                cbScratchInternal );
667
0
    SymCryptIntToModElement(
668
0
                piIntQ[0],
669
0
                pDlgroup->pmQ,
670
0
                peT,
671
0
                pbScratchInternal,
672
0
                cbScratchInternal );
673
674
    // Comparison V = R
675
0
    if (SymCryptModElementIsEqual( pDlgroup->pmQ, peT, peR ))
676
0
    {
677
0
        fValidSignature = TRUE;
678
0
    }
679
680
681
0
cleanup:
682
683
0
    if (!fValidSignature)
684
0
    {
685
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
686
0
    }
687
688
0
    if ( pbScratch != NULL )
689
0
    {
690
0
        SymCryptWipe( pbScratch, cbScratch );
691
0
        SymCryptCallbackFree( pbScratch );
692
0
    }
693
694
0
    return scError;
695
0
}