/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 | } |