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