/src/SymCrypt/lib/rsa_enc.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // rsa_enc.c RSA related algorithms |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | #include "precomp.h" |
8 | | |
9 | | // |
10 | | // Helper functions for RSA raw encrypt/decrypt (they do NOT allocate scratch space) |
11 | | // |
12 | | |
13 | | UINT32 |
14 | | SYMCRYPT_CALL |
15 | | SymCryptRsaCoreEncScratchSpace( _In_ PCSYMCRYPT_RSAKEY pkRsakey) |
16 | 0 | { |
17 | | // Bounded by 2^19 + 2^24 ~ 2^24 (see symcrypt_internal.h) |
18 | 0 | return SymCryptSizeofModElementFromModulus( pkRsakey->pmModulus ) + |
19 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
20 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ) ); |
21 | 0 | } |
22 | | |
23 | | SYMCRYPT_ERROR |
24 | | SymCryptRsaCoreVerifyInput( |
25 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
26 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
27 | | SIZE_T cbSrc, |
28 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
29 | | SIZE_T cbDst, |
30 | | _Out_writes_bytes_( cbScratch ) |
31 | | PBYTE pbScratch, |
32 | | SIZE_T cbScratch) |
33 | 0 | { |
34 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
35 | 0 | PSYMCRYPT_INT piTmpInteger = NULL; |
36 | 0 | UINT32 cbTmpInteger = 0; |
37 | |
|
38 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
39 | |
|
40 | 0 | if ( cbSrc > SymCryptRsakeySizeofModulus(pkRsakey) || |
41 | 0 | cbDst < SymCryptRsakeySizeofModulus(pkRsakey) ) |
42 | 0 | { |
43 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
44 | 0 | goto cleanup; |
45 | 0 | } |
46 | | |
47 | | // It is an error of value(pbSrc) >= modulus |
48 | | // We already know that cbSrc <= sizeof( modulus ) so we only have to run this check |
49 | | // if cbSrc == sizeof( modulus ) |
50 | | // No side channel issues here: we are only comparing the input to the public part of the key. |
51 | 0 | if (cbSrc == SymCryptRsakeySizeofModulus(pkRsakey)) |
52 | 0 | { |
53 | 0 | cbTmpInteger = SymCryptSizeofIntFromDigits( pkRsakey->nDigitsOfModulus ); |
54 | 0 | SYMCRYPT_ASSERT( cbScratch >= cbTmpInteger ); |
55 | 0 | piTmpInteger = SymCryptIntCreate( pbScratch, cbTmpInteger, pkRsakey->nDigitsOfModulus ); |
56 | |
|
57 | 0 | scError = SymCryptIntSetValue( pbSrc, cbSrc, numFormat, piTmpInteger ); |
58 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
59 | 0 | { |
60 | 0 | goto cleanup; |
61 | 0 | } |
62 | | |
63 | 0 | if (!SymCryptIntIsLessThan(piTmpInteger, SymCryptIntFromModulus(pkRsakey->pmModulus))) |
64 | 0 | { |
65 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
66 | 0 | goto cleanup; |
67 | 0 | } |
68 | 0 | } |
69 | | |
70 | 0 | cleanup: |
71 | 0 | return scError; |
72 | 0 | } |
73 | | |
74 | | |
75 | | SYMCRYPT_ERROR |
76 | | SYMCRYPT_CALL |
77 | | SymCryptRsaCoreEnc( |
78 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
79 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
80 | | SIZE_T cbSrc, |
81 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
82 | | UINT32 flags, |
83 | | _Out_writes_( cbDst ) PBYTE pbDst, |
84 | | SIZE_T cbDst, |
85 | | _Out_writes_bytes_( cbScratch ) |
86 | | PBYTE pbScratch, |
87 | | SIZE_T cbScratch ) |
88 | 0 | { |
89 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
90 | |
|
91 | 0 | PSYMCRYPT_MODELEMENT peRes = NULL; |
92 | 0 | UINT32 cbModElement = 0; |
93 | |
|
94 | 0 | PBYTE pbFnScratch = NULL; |
95 | 0 | SIZE_T cbFnScratch = 0; |
96 | |
|
97 | 0 | BYTE abExpIntBuffer[ SYMCRYPT_SIZEOF_INT_FROM_BITS( 64 ) + SYMCRYPT_ASYM_ALIGN_VALUE]; |
98 | 0 | PSYMCRYPT_INT piExp = NULL; |
99 | |
|
100 | 0 | UNREFERENCED_PARAMETER( flags ); |
101 | |
|
102 | 0 | scError = SymCryptRsaCoreVerifyInput(pkRsakey, pbSrc, cbSrc, numFormat, cbDst, pbScratch, cbScratch); |
103 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
104 | 0 | { |
105 | 0 | goto cleanup; |
106 | 0 | } |
107 | | |
108 | 0 | cbModElement = SymCryptSizeofModElementFromModulus( pkRsakey->pmModulus ); |
109 | |
|
110 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
111 | 0 | SYMCRYPT_ASSERT( cbScratch >= cbModElement + |
112 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
113 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ) )); |
114 | |
|
115 | 0 | pbFnScratch = pbScratch; |
116 | 0 | cbFnScratch = cbScratch; |
117 | |
|
118 | 0 | peRes = SymCryptModElementCreate( pbScratch, cbModElement, pkRsakey->pmModulus ); |
119 | 0 | SYMCRYPT_ASSERT( peRes != NULL ); |
120 | 0 | pbFnScratch += cbModElement; |
121 | 0 | cbFnScratch -= cbModElement; |
122 | | |
123 | | // Set the original value |
124 | 0 | scError = SymCryptModElementSetValue( pbSrc, cbSrc, numFormat, pkRsakey->pmModulus, peRes, pbFnScratch, cbFnScratch ); |
125 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
126 | 0 | { |
127 | 0 | goto cleanup; |
128 | 0 | } |
129 | | |
130 | | // Convert the public exponent to an Int |
131 | | // Future: we can optimize the ModExp to take an UINT64 |
132 | 0 | piExp = SymCryptIntCreate( SYMCRYPT_ASYM_ALIGN_UP(abExpIntBuffer), sizeof( abExpIntBuffer) - SYMCRYPT_ASYM_ALIGN_VALUE, 1 ); |
133 | 0 | if( piExp == NULL ) |
134 | 0 | { |
135 | 0 | scError = SYMCRYPT_HARDWARE_FAILURE; |
136 | 0 | goto cleanup; |
137 | 0 | } |
138 | 0 | SymCryptIntSetValueUint64( pkRsakey->au64PubExp[0], piExp ); |
139 | | |
140 | | // Modular Exponentiation |
141 | 0 | SymCryptModExp( |
142 | 0 | pkRsakey->pmModulus, |
143 | 0 | peRes, |
144 | 0 | piExp, |
145 | 0 | SymCryptIntBitsizeOfValue( piExp ), // This is a public value |
146 | 0 | SYMCRYPT_FLAG_DATA_PUBLIC, |
147 | 0 | peRes, |
148 | 0 | pbFnScratch, |
149 | 0 | cbFnScratch ); |
150 | | |
151 | | // Output the value |
152 | 0 | scError = SymCryptModElementGetValue( pkRsakey->pmModulus, peRes, pbDst, cbDst, numFormat, pbFnScratch, cbFnScratch ); |
153 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
154 | 0 | { |
155 | 0 | goto cleanup; |
156 | 0 | } |
157 | | |
158 | 0 | cleanup: |
159 | |
|
160 | 0 | if( piExp != NULL ) |
161 | 0 | { |
162 | 0 | SymCryptIntWipe( piExp ); |
163 | 0 | } |
164 | |
|
165 | 0 | return scError; |
166 | 0 | } |
167 | | |
168 | | UINT32 |
169 | | SYMCRYPT_CALL |
170 | | SymCryptRsaCoreDecCrtScratchSpace( _In_ PCSYMCRYPT_RSAKEY pkRsakey) |
171 | 0 | { |
172 | 0 | UINT32 cbModElementTotal = 0; |
173 | 0 | UINT32 nPrimes = pkRsakey->nPrimes; |
174 | |
|
175 | 0 | SYMCRYPT_ASSERT( nPrimes <= SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES ); |
176 | | // clamp nPrimes to SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES for scratch memory allocation purposes |
177 | | // SymCryptRsaCoreDecCrt will fail with invalid argument if there are too many primes later |
178 | 0 | nPrimes = SYMCRYPT_MIN( nPrimes, SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES ); |
179 | |
|
180 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
181 | 0 | { |
182 | 0 | cbModElementTotal += SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pkRsakey->nBitsOfPrimes[i]); |
183 | 0 | } |
184 | | |
185 | | // Bounded by 5*2^19 + 2^24 ~ 2^24 (see symcrypt_internal.h) |
186 | 0 | return 3*SymCryptSizeofIntFromDigits( pkRsakey->nDigitsOfModulus ) + |
187 | 0 | SymCryptSizeofIntFromDigits( pkRsakey->nMaxDigitsOfPrimes ) + |
188 | 0 | cbModElementTotal + |
189 | 0 | SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pkRsakey->nBitsOfModulus) + |
190 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
191 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ), |
192 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pkRsakey->nDigitsOfModulus, pkRsakey->nMaxDigitsOfPrimes ), |
193 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_CRT_SOLUTION( pkRsakey->nMaxDigitsOfPrimes ) ))); |
194 | 0 | } |
195 | | |
196 | | UINT32 |
197 | | SYMCRYPT_CALL |
198 | | SymCryptRsaCoreDecScratchSpace( _In_ PCSYMCRYPT_RSAKEY pkRsakey) |
199 | 0 | { |
200 | | // Bounded by 2^19 + 2^24 ~ 2^24 (see symcrypt_internal.h) |
201 | 0 | return SymCryptSizeofModElementFromModulus( pkRsakey->pmModulus ) + |
202 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
203 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ) ); |
204 | 0 | } |
205 | | |
206 | | SYMCRYPT_ERROR |
207 | | SYMCRYPT_CALL |
208 | | SymCryptRsaCoreDecCrt( |
209 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
210 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
211 | | SIZE_T cbSrc, |
212 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
213 | | UINT32 flags, |
214 | | _Out_writes_( cbDst ) PBYTE pbDst, |
215 | | SIZE_T cbDst, |
216 | | _Out_writes_bytes_( cbScratch ) |
217 | | PBYTE pbScratch, |
218 | | SIZE_T cbScratch ) |
219 | 0 | { |
220 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
221 | |
|
222 | 0 | PSYMCRYPT_INT piCiphertext = NULL; |
223 | 0 | PSYMCRYPT_INT piPlaintext = NULL; |
224 | 0 | UINT32 cbInt = 0; |
225 | |
|
226 | 0 | PSYMCRYPT_INT piTmp = NULL; |
227 | 0 | UINT32 cbTmp = 0; |
228 | |
|
229 | 0 | PSYMCRYPT_MODELEMENT peCrtElements[SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES] = { 0 }; |
230 | 0 | UINT32 cbModElements[SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES] = { 0 }; |
231 | 0 | UINT32 cbModElementTotal = 0; |
232 | | |
233 | | // Used to verify decryption |
234 | 0 | PSYMCRYPT_INT piVerify = NULL; // Size equal to cbInt |
235 | 0 | PSYMCRYPT_MODELEMENT peVerify = NULL; |
236 | 0 | UINT32 cbModElementVerify = 0; |
237 | |
|
238 | 0 | PBYTE pbFnScratch = NULL; |
239 | 0 | SIZE_T cbFnScratch = 0; |
240 | |
|
241 | 0 | UNREFERENCED_PARAMETER( flags ); |
242 | | |
243 | | // Make sure that the key has a private key |
244 | 0 | if (!pkRsakey->hasPrivateKey) |
245 | 0 | { |
246 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
247 | 0 | goto cleanup; |
248 | 0 | } |
249 | | |
250 | 0 | scError = SymCryptRsaCoreVerifyInput(pkRsakey, pbSrc, cbSrc, numFormat, cbDst, pbScratch, cbScratch); |
251 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
252 | 0 | { |
253 | 0 | goto cleanup; |
254 | 0 | } |
255 | | |
256 | | // Verify that the number of primes does not cause a stack overflow |
257 | 0 | if (pkRsakey->nPrimes > SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES) |
258 | 0 | { |
259 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
260 | 0 | goto cleanup; |
261 | 0 | } |
262 | | |
263 | 0 | cbInt = SymCryptSizeofIntFromDigits( pkRsakey->nDigitsOfModulus ); |
264 | 0 | cbTmp = SymCryptSizeofIntFromDigits( pkRsakey->nMaxDigitsOfPrimes ); |
265 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
266 | 0 | { |
267 | 0 | cbModElements[i] = SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pkRsakey->nBitsOfPrimes[i]); |
268 | 0 | cbModElementTotal += cbModElements[i]; |
269 | 0 | } |
270 | |
|
271 | 0 | cbModElementVerify = SymCryptSizeofModElementFromModulus( pkRsakey->pmModulus ); |
272 | |
|
273 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
274 | | // |
275 | | // From symcrypt_internal.h we have: |
276 | | // - sizeof results are upper bounded by 2^19 |
277 | | // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE) |
278 | | // - nPrimes is at most SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES = 2 |
279 | | // Thus the following calculation does not overflow cbScratch. |
280 | | // |
281 | 0 | SYMCRYPT_ASSERT( cbScratch >= |
282 | 0 | 3*cbInt + cbTmp + cbModElementTotal + cbModElementVerify + |
283 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
284 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ), |
285 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( pkRsakey->nDigitsOfModulus, pkRsakey->nMaxDigitsOfPrimes ), |
286 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_CRT_SOLUTION( pkRsakey->nMaxDigitsOfPrimes ) ))) ); |
287 | |
|
288 | 0 | pbFnScratch = pbScratch; |
289 | 0 | cbFnScratch = cbScratch; |
290 | |
|
291 | 0 | piPlaintext = SymCryptIntCreate( pbFnScratch, cbFnScratch, pkRsakey->nDigitsOfModulus ); |
292 | 0 | SYMCRYPT_ASSERT( piPlaintext != NULL ); |
293 | 0 | pbFnScratch += cbInt; |
294 | 0 | cbFnScratch -= cbInt; |
295 | |
|
296 | 0 | piCiphertext = SymCryptIntCreate( pbFnScratch, cbFnScratch, pkRsakey->nDigitsOfModulus ); |
297 | 0 | SYMCRYPT_ASSERT( piCiphertext != NULL ); |
298 | 0 | pbFnScratch += cbInt; |
299 | 0 | cbFnScratch -= cbInt; |
300 | |
|
301 | 0 | piTmp = SymCryptIntCreate( pbFnScratch, cbFnScratch, pkRsakey->nMaxDigitsOfPrimes ); |
302 | 0 | SYMCRYPT_ASSERT( piTmp != NULL ); |
303 | 0 | pbFnScratch += cbTmp; |
304 | 0 | cbFnScratch -= cbTmp; |
305 | |
|
306 | 0 | SYMCRYPT_ASSERT( pkRsakey->nPrimes <= SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES ); |
307 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
308 | 0 | { |
309 | 0 | peCrtElements[i] = SymCryptModElementCreate( pbFnScratch, cbFnScratch, pkRsakey->pmPrimes[i] ); |
310 | 0 | SYMCRYPT_ASSERT( peCrtElements[i] != NULL ); |
311 | 0 | pbFnScratch += cbModElements[i]; |
312 | 0 | cbFnScratch -= cbModElements[i]; |
313 | 0 | } |
314 | |
|
315 | 0 | piVerify = SymCryptIntCreate( pbFnScratch, cbFnScratch, pkRsakey->nDigitsOfModulus ); |
316 | 0 | SYMCRYPT_ASSERT( piVerify != NULL ); |
317 | 0 | pbFnScratch += cbInt; |
318 | 0 | cbFnScratch -= cbInt; |
319 | |
|
320 | 0 | peVerify = SymCryptModElementCreate( pbFnScratch, cbFnScratch, pkRsakey->pmModulus ); |
321 | 0 | SYMCRYPT_ASSERT( peVerify != NULL ); |
322 | 0 | pbFnScratch += cbModElementVerify; |
323 | 0 | cbFnScratch -= cbModElementVerify; |
324 | | |
325 | | // Set the ciphertext |
326 | 0 | scError = SymCryptIntSetValue( pbSrc, cbSrc, numFormat, piCiphertext ); |
327 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
328 | 0 | { |
329 | 0 | goto cleanup; |
330 | 0 | } |
331 | | |
332 | | // Modular exponentiations |
333 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
334 | 0 | { |
335 | | // c mod the prime |
336 | | // Note: For two equally sized primes we can use straight the faster SymCryptIntToModElement function |
337 | | // but for now this is the general case. |
338 | 0 | SymCryptIntDivMod( |
339 | 0 | piCiphertext, |
340 | 0 | SymCryptDivisorFromModulus(pkRsakey->pmPrimes[i]), |
341 | 0 | NULL, |
342 | 0 | piTmp, |
343 | 0 | pbFnScratch, |
344 | 0 | cbFnScratch ); |
345 | |
|
346 | 0 | SymCryptIntToModElement( piTmp, pkRsakey->pmPrimes[i], peCrtElements[i], pbFnScratch, cbFnScratch ); |
347 | | |
348 | | // Modular Exponentiation |
349 | 0 | SymCryptModExp( |
350 | 0 | pkRsakey->pmPrimes[i], |
351 | 0 | peCrtElements[i], |
352 | 0 | pkRsakey->piCrtPrivExps[i], // For now only the first exponent is allowed |
353 | 0 | pkRsakey->nBitsOfPrimes[i], // This is a public value |
354 | 0 | 0, // Side-channel safe modexp |
355 | 0 | peCrtElements[i], |
356 | 0 | pbFnScratch, |
357 | 0 | cbFnScratch ); |
358 | 0 | } |
359 | | |
360 | | // Solve the crt equations |
361 | 0 | scError = SymCryptCrtSolve( |
362 | 0 | pkRsakey->nPrimes, |
363 | 0 | (PCSYMCRYPT_MODULUS *) pkRsakey->pmPrimes, |
364 | 0 | (PSYMCRYPT_MODELEMENT *) pkRsakey->peCrtInverses, |
365 | 0 | peCrtElements, |
366 | 0 | 0, |
367 | 0 | piPlaintext, |
368 | 0 | pbFnScratch, |
369 | 0 | cbFnScratch ); |
370 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
371 | 0 | { |
372 | 0 | goto cleanup; |
373 | 0 | } |
374 | | |
375 | | /* |
376 | | A hardware error during RSA decryption can leak the |
377 | | prime factors. For example, suppose the message |
378 | | is M and you try to sign it with |
379 | | M^d for some decryption exponent d. |
380 | | Using the CRT, you compute M^d mod p correctly but |
381 | | M^d mod q incorrectly. Your supposed M^d (mod p*q) is |
382 | | then raised to an encryption exponent e |
383 | | by the verifier, detects an invalid signature. |
384 | | The verifier can also find p via a GCD and factor the modulus. |
385 | | |
386 | | To avoid this problem, re-encrypt the supposed M^d |
387 | | and verify our own signature. |
388 | | */ |
389 | | |
390 | | // Don't call the full encryption function just the modular exponentiation |
391 | | |
392 | 0 | SymCryptIntToModElement( piPlaintext, pkRsakey->pmModulus, peVerify, pbFnScratch, cbFnScratch ); |
393 | |
|
394 | 0 | SymCryptIntSetValueUint64( pkRsakey->au64PubExp[0], piTmp ); |
395 | | |
396 | | // Modular Exponentiation (Not side-channel safe) |
397 | 0 | SymCryptModExp( |
398 | 0 | pkRsakey->pmModulus, |
399 | 0 | peVerify, |
400 | 0 | piTmp, |
401 | 0 | SymCryptIntBitsizeOfValue( piTmp ), |
402 | 0 | SYMCRYPT_FLAG_DATA_PUBLIC, // Exponent is public |
403 | 0 | peVerify, |
404 | 0 | pbFnScratch, |
405 | 0 | cbFnScratch ); |
406 | |
|
407 | 0 | SymCryptModElementToInt( pkRsakey->pmModulus, peVerify, piVerify, pbFnScratch, cbFnScratch ); |
408 | |
|
409 | 0 | if (!SymCryptIntIsEqual( piCiphertext, piVerify )) |
410 | 0 | { |
411 | 0 | scError = SYMCRYPT_HARDWARE_FAILURE; |
412 | 0 | goto cleanup; |
413 | 0 | } |
414 | | |
415 | | // Output the result |
416 | 0 | scError = SymCryptIntGetValue( piPlaintext, pbDst, cbDst, numFormat ); |
417 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
418 | 0 | { |
419 | 0 | goto cleanup; |
420 | 0 | } |
421 | | |
422 | 0 | cleanup: |
423 | |
|
424 | 0 | return scError; |
425 | 0 | } |
426 | | |
427 | | SYMCRYPT_ERROR |
428 | | SYMCRYPT_CALL |
429 | | SymCryptRsaCoreDec( |
430 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
431 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
432 | | SIZE_T cbSrc, |
433 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
434 | | UINT32 flags, |
435 | | _Out_writes_( cbDst ) PBYTE pbDst, |
436 | | SIZE_T cbDst, |
437 | | _Out_writes_bytes_( cbScratch ) |
438 | | PBYTE pbScratch, |
439 | | SIZE_T cbScratch ) |
440 | 0 | { |
441 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
442 | |
|
443 | 0 | PSYMCRYPT_MODELEMENT peRes = NULL; |
444 | 0 | UINT32 cbModElement = 0; |
445 | |
|
446 | 0 | PBYTE pbFnScratch = NULL; |
447 | 0 | SIZE_T cbFnScratch = 0; |
448 | |
|
449 | 0 | UNREFERENCED_PARAMETER( flags ); |
450 | | |
451 | | // Make sure that the key has a private key |
452 | 0 | if ((cbSrc>SymCryptRsakeySizeofModulus(pkRsakey)) || |
453 | 0 | (!pkRsakey->hasPrivateKey) ) |
454 | 0 | { |
455 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
456 | 0 | goto cleanup; |
457 | 0 | } |
458 | | |
459 | 0 | cbModElement = SymCryptSizeofModElementFromModulus( pkRsakey->pmModulus ); |
460 | |
|
461 | 0 | UNREFERENCED_PARAMETER( cbScratch ); |
462 | 0 | SYMCRYPT_ASSERT( cbScratch >= cbModElement + |
463 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ), |
464 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP( pkRsakey->nDigitsOfModulus ) ) ); |
465 | |
|
466 | 0 | pbFnScratch = pbScratch; |
467 | 0 | cbFnScratch = cbScratch; |
468 | |
|
469 | 0 | peRes = SymCryptModElementCreate( pbScratch, cbModElement, pkRsakey->pmModulus ); |
470 | 0 | SYMCRYPT_ASSERT( peRes != NULL ); |
471 | 0 | pbFnScratch += cbModElement; |
472 | 0 | cbFnScratch -= cbModElement; |
473 | | |
474 | | // Set the ciphertext |
475 | 0 | scError = SymCryptModElementSetValue( pbSrc, cbSrc, numFormat, pkRsakey->pmModulus, peRes, pbFnScratch, cbFnScratch ); |
476 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
477 | 0 | { |
478 | 0 | goto cleanup; |
479 | 0 | } |
480 | | |
481 | | // Modular Exponentiation |
482 | 0 | SymCryptModExp( |
483 | 0 | pkRsakey->pmModulus, |
484 | 0 | peRes, |
485 | 0 | pkRsakey->piPrivExps[0], // For now only the first exponent is allowed |
486 | 0 | pkRsakey->nBitsOfModulus, // This is a public value |
487 | 0 | 0, // Side-channel safe modexp |
488 | 0 | peRes, |
489 | 0 | pbFnScratch, |
490 | 0 | cbFnScratch ); |
491 | | |
492 | | // Output the value |
493 | 0 | scError = SymCryptModElementGetValue( pkRsakey->pmModulus, peRes, pbDst, cbDst, numFormat, pbFnScratch, cbFnScratch ); |
494 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
495 | 0 | { |
496 | 0 | goto cleanup; |
497 | 0 | } |
498 | | |
499 | 0 | cleanup: |
500 | |
|
501 | 0 | return scError; |
502 | 0 | } |
503 | | |
504 | | |
505 | | // |
506 | | // Encryption / decryption functions |
507 | | // |
508 | | SYMCRYPT_ERROR |
509 | | SYMCRYPT_CALL |
510 | | SymCryptRsaRawEncrypt( |
511 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
512 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
513 | | SIZE_T cbSrc, |
514 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
515 | | UINT32 flags, |
516 | | _Out_writes_( cbDst ) PBYTE pbDst, |
517 | | SIZE_T cbDst ) |
518 | 0 | { |
519 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
520 | |
|
521 | 0 | PBYTE pbScratch = NULL; |
522 | 0 | UINT32 cbScratch = 0; |
523 | | |
524 | | // Make sure that the key may be used in Encrypt/Decrypt |
525 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
526 | 0 | { |
527 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
528 | 0 | goto cleanup; |
529 | 0 | } |
530 | | |
531 | 0 | cbScratch = SymCryptRsaCoreEncScratchSpace( pkRsakey ); |
532 | |
|
533 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
534 | 0 | if (pbScratch == NULL) |
535 | 0 | { |
536 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
537 | 0 | goto cleanup; |
538 | 0 | } |
539 | | |
540 | 0 | scError = SymCryptRsaCoreEnc( pkRsakey, pbSrc, cbSrc, numFormat, flags, pbDst, cbDst, pbScratch, cbScratch ); |
541 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
542 | 0 | { |
543 | 0 | goto cleanup; |
544 | 0 | } |
545 | | |
546 | 0 | scError = SYMCRYPT_NO_ERROR; |
547 | |
|
548 | 0 | cleanup: |
549 | 0 | if (pbScratch!=NULL) |
550 | 0 | { |
551 | 0 | SymCryptWipe(pbScratch,cbScratch); |
552 | 0 | SymCryptCallbackFree(pbScratch); |
553 | 0 | } |
554 | |
|
555 | 0 | return scError; |
556 | 0 | } |
557 | | |
558 | | SYMCRYPT_ERROR |
559 | | SYMCRYPT_CALL |
560 | | SymCryptRsaRawDecrypt( |
561 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
562 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
563 | | SIZE_T cbSrc, |
564 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
565 | | UINT32 flags, |
566 | | _Out_writes_( cbDst ) PBYTE pbDst, |
567 | | SIZE_T cbDst ) |
568 | 0 | { |
569 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
570 | |
|
571 | 0 | PBYTE pbScratch = NULL; |
572 | 0 | UINT32 cbScratch = 0; |
573 | | |
574 | | // Make sure that the key may be used in Encrypt/Decrypt |
575 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
576 | 0 | { |
577 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
578 | 0 | goto cleanup; |
579 | 0 | } |
580 | | |
581 | | // Make sure that the key has a private key |
582 | 0 | if (!pkRsakey->hasPrivateKey) |
583 | 0 | { |
584 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
585 | 0 | goto cleanup; |
586 | 0 | } |
587 | | |
588 | 0 | #define SYMCRYPT_CRT_DECRYPTION (1) // Set this to 0 to test the non-crt decryption |
589 | | |
590 | | // Scratch space |
591 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
592 | 0 | cbScratch = SymCryptRsaCoreDecCrtScratchSpace( pkRsakey ); |
593 | | #else |
594 | | cbScratch = SymCryptRsaCoreDecScratchSpace( pkRsakey ); |
595 | | #endif |
596 | |
|
597 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
598 | 0 | if (pbScratch == NULL) |
599 | 0 | { |
600 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
601 | 0 | goto cleanup; |
602 | 0 | } |
603 | | |
604 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
605 | 0 | scError = SymCryptRsaCoreDecCrt( pkRsakey, pbSrc, cbSrc, numFormat, flags, pbDst, cbDst, pbScratch, cbScratch ); |
606 | | #else |
607 | | scError = SymCryptRsaCoreDec( pkRsakey, pbSrc, cbSrc, numFormat, flags, pbDst, cbDst, pbScratch, cbScratch ); |
608 | | #endif |
609 | |
|
610 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
611 | 0 | { |
612 | 0 | goto cleanup; |
613 | 0 | } |
614 | | |
615 | 0 | scError = SYMCRYPT_NO_ERROR; |
616 | |
|
617 | 0 | cleanup: |
618 | 0 | if (pbScratch!=NULL) |
619 | 0 | { |
620 | 0 | SymCryptWipe(pbScratch,cbScratch); |
621 | 0 | SymCryptCallbackFree(pbScratch); |
622 | 0 | } |
623 | |
|
624 | 0 | return scError; |
625 | 0 | } |
626 | | |
627 | | SYMCRYPT_ERROR |
628 | | SYMCRYPT_CALL |
629 | | SymCryptRsaPkcs1Encrypt( |
630 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
631 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
632 | | SIZE_T cbSrc, |
633 | | UINT32 flags, |
634 | | SYMCRYPT_NUMBER_FORMAT nfDst, |
635 | | _Out_writes_opt_( cbDst ) PBYTE pbDst, |
636 | | SIZE_T cbDst, |
637 | | _Out_ SIZE_T *pcbDst ) |
638 | 0 | { |
639 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
640 | |
|
641 | 0 | PBYTE pbScratch = NULL; |
642 | 0 | SIZE_T cbScratch = 0; |
643 | |
|
644 | 0 | PBYTE pbTmp = NULL; |
645 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
646 | |
|
647 | 0 | cbScratch = cbTmp + SymCryptRsaCoreEncScratchSpace( pkRsakey ); |
648 | |
|
649 | 0 | UNREFERENCED_PARAMETER( flags ); |
650 | | |
651 | | // Make sure that the key may be used in Encrypt/Decrypt |
652 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
653 | 0 | { |
654 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
655 | 0 | goto cleanup; |
656 | 0 | } |
657 | | |
658 | 0 | *pcbDst = cbTmp; |
659 | | |
660 | | // Check if only *pcbDst is needed |
661 | 0 | if (pbDst == NULL) |
662 | 0 | { |
663 | 0 | scError = SYMCRYPT_NO_ERROR; |
664 | 0 | goto cleanup; |
665 | 0 | } |
666 | | |
667 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
668 | 0 | if (pbScratch == NULL) |
669 | 0 | { |
670 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
671 | 0 | goto cleanup; |
672 | 0 | } |
673 | | |
674 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
675 | |
|
676 | 0 | scError = SymCryptRsaPkcs1ApplyEncryptionPadding( |
677 | 0 | pbSrc, |
678 | 0 | cbSrc, |
679 | 0 | pbTmp, |
680 | 0 | cbTmp ); |
681 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
682 | 0 | { |
683 | 0 | goto cleanup; |
684 | 0 | } |
685 | | |
686 | 0 | scError = SymCryptRsaCoreEnc( |
687 | 0 | pkRsakey, |
688 | 0 | pbTmp, |
689 | 0 | cbTmp, |
690 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, // Always MSB first for RSA OAEP |
691 | 0 | flags, |
692 | 0 | pbDst, |
693 | 0 | cbDst, |
694 | 0 | pbScratch, |
695 | 0 | cbScratch - cbTmp ); |
696 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
697 | 0 | { |
698 | 0 | goto cleanup; |
699 | 0 | } |
700 | | |
701 | 0 | if (nfDst == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
702 | 0 | { |
703 | | // To implement this revert the buffer properly |
704 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
705 | 0 | goto cleanup; |
706 | 0 | } |
707 | | |
708 | 0 | scError = SYMCRYPT_NO_ERROR; |
709 | |
|
710 | 0 | cleanup: |
711 | 0 | if (pbScratch!=NULL) |
712 | 0 | { |
713 | 0 | SymCryptWipe(pbScratch,cbScratch); |
714 | 0 | SymCryptCallbackFree(pbScratch); |
715 | 0 | } |
716 | |
|
717 | 0 | return scError; |
718 | 0 | } |
719 | | |
720 | | // Ensure SymCryptRoundUpPow2Sizet below will not fail |
721 | | C_ASSERT((UINT32) ((SYMCRYPT_RSAKEY_MAX_BITSIZE_MODULUS + 7) / 8) <= ((SIZE_T_MAX / 2) + 1)); |
722 | | |
723 | | SYMCRYPT_ERROR |
724 | | SYMCRYPT_CALL |
725 | | SymCryptRsaPkcs1Decrypt( |
726 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
727 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
728 | | SIZE_T cbSrc, |
729 | | SYMCRYPT_NUMBER_FORMAT nfSrc, |
730 | | UINT32 flags, |
731 | | _Out_writes_opt_( cbDst ) PBYTE pbDst, |
732 | | SIZE_T cbDst, |
733 | | _Out_ SIZE_T *pcbDst ) |
734 | 0 | { |
735 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
736 | |
|
737 | 0 | PBYTE pbScratch = NULL; |
738 | 0 | SIZE_T cbScratch = 0; |
739 | |
|
740 | 0 | PBYTE pbTmp = NULL; |
741 | 0 | SIZE_T cbModulus = SymCryptRsakeySizeofModulus(pkRsakey); |
742 | 0 | SIZE_T cbTmp = SymCryptRoundUpPow2Sizet( cbModulus ); // tmp buffer needs to be a power of 2 |
743 | | |
744 | | // Make sure that the key may be used in Encrypt/Decrypt |
745 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
746 | 0 | { |
747 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
748 | 0 | goto cleanup; |
749 | 0 | } |
750 | | |
751 | | // Make sure that the key has a private key |
752 | 0 | if (!pkRsakey->hasPrivateKey) |
753 | 0 | { |
754 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
755 | 0 | goto cleanup; |
756 | 0 | } |
757 | | |
758 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
759 | 0 | cbScratch = cbTmp + SymCryptRsaCoreDecCrtScratchSpace( pkRsakey ); |
760 | | #else |
761 | | cbScratch = cbTmp + SymCryptRsaCoreDecScratchSpace( pkRsakey ); |
762 | | #endif |
763 | |
|
764 | 0 | UNREFERENCED_PARAMETER( flags ); |
765 | |
|
766 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
767 | 0 | if (pbScratch == NULL) |
768 | 0 | { |
769 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
770 | 0 | goto cleanup; |
771 | 0 | } |
772 | | |
773 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
774 | |
|
775 | 0 | if (nfSrc == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
776 | 0 | { |
777 | | // To implement this revert the buffer properly |
778 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
779 | 0 | goto cleanup; |
780 | 0 | } |
781 | | |
782 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
783 | 0 | scError = SymCryptRsaCoreDecCrt( |
784 | 0 | pkRsakey, |
785 | 0 | pbSrc, |
786 | 0 | cbSrc, |
787 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
788 | 0 | flags, |
789 | 0 | pbTmp, |
790 | 0 | cbModulus, |
791 | 0 | pbScratch, |
792 | 0 | cbScratch - cbTmp ); |
793 | | #else |
794 | | scError = SymCryptRsaCoreDec( |
795 | | pkRsakey, |
796 | | pbSrc, |
797 | | cbSrc, |
798 | | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
799 | | flags, |
800 | | pbTmp, |
801 | | cbModulus, |
802 | | pbScratch, |
803 | | cbScratch - cbTmp ); |
804 | | #endif |
805 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
806 | 0 | { |
807 | 0 | goto cleanup; |
808 | 0 | } |
809 | | |
810 | 0 | scError = SymCryptRsaPkcs1RemoveEncryptionPadding( |
811 | 0 | pbTmp, |
812 | 0 | cbModulus, |
813 | 0 | cbTmp, |
814 | 0 | pbDst, |
815 | 0 | cbDst, |
816 | 0 | pcbDst ); |
817 | | // The error that is returned from the encryption padding is confidential data |
818 | | // due to Bleichenbacher-style attacks. |
819 | | // Make sure we don't create a side-channel leak for it. |
820 | |
|
821 | 0 | cleanup: |
822 | 0 | if (pbScratch!=NULL) |
823 | 0 | { |
824 | 0 | SymCryptWipe(pbScratch,cbScratch); |
825 | 0 | SymCryptCallbackFree(pbScratch); |
826 | 0 | } |
827 | |
|
828 | 0 | return scError; |
829 | 0 | } |
830 | | |
831 | | SYMCRYPT_ERROR |
832 | | SYMCRYPT_CALL |
833 | | SymCryptRsaOaepEncrypt( |
834 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
835 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
836 | | SIZE_T cbSrc, |
837 | | _In_ PCSYMCRYPT_HASH hashAlgorithm, |
838 | | _In_reads_bytes_( cbLabel ) PCBYTE pbLabel, |
839 | | SIZE_T cbLabel, |
840 | | UINT32 flags, |
841 | | SYMCRYPT_NUMBER_FORMAT nfDst, |
842 | | _Out_writes_opt_( cbDst ) PBYTE pbDst, |
843 | | SIZE_T cbDst, |
844 | | _Out_ SIZE_T *pcbDst ) |
845 | 0 | { |
846 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
847 | |
|
848 | 0 | PBYTE pbScratch = NULL; |
849 | 0 | SIZE_T cbScratch = 0; |
850 | |
|
851 | 0 | PBYTE pbTmp = NULL; |
852 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
853 | |
|
854 | 0 | UNREFERENCED_PARAMETER( flags ); |
855 | | |
856 | | // Make sure that the key may be used in Encrypt/Decrypt |
857 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
858 | 0 | { |
859 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
860 | 0 | goto cleanup; |
861 | 0 | } |
862 | | |
863 | 0 | *pcbDst = cbTmp; |
864 | | |
865 | | // Check if only *pcbDst is needed |
866 | 0 | if (pbDst == NULL) |
867 | 0 | { |
868 | 0 | scError = SYMCRYPT_NO_ERROR; |
869 | 0 | goto cleanup; |
870 | 0 | } |
871 | | |
872 | | // The SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP macro does not |
873 | | // overflow cbScratch since cbTmp < 2^17. |
874 | 0 | cbScratch = cbTmp + SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( hashAlgorithm, cbTmp ), SymCryptRsaCoreEncScratchSpace( pkRsakey ) ); |
875 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
876 | 0 | if (pbScratch == NULL) |
877 | 0 | { |
878 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
879 | 0 | goto cleanup; |
880 | 0 | } |
881 | | |
882 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
883 | |
|
884 | 0 | scError = SymCryptRsaOaepApplyEncryptionPadding( |
885 | 0 | pbSrc, |
886 | 0 | cbSrc, |
887 | 0 | hashAlgorithm, |
888 | 0 | pbLabel, |
889 | 0 | cbLabel, |
890 | 0 | NULL, // Seed |
891 | 0 | 0, // cbSeed |
892 | 0 | pbTmp, |
893 | 0 | cbTmp, |
894 | 0 | pbScratch, |
895 | 0 | cbScratch - cbTmp ); |
896 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
897 | 0 | { |
898 | 0 | goto cleanup; |
899 | 0 | } |
900 | | |
901 | 0 | scError = SymCryptRsaCoreEnc( |
902 | 0 | pkRsakey, |
903 | 0 | pbTmp, |
904 | 0 | cbTmp, |
905 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, // Always MSB first for RSA OAEP |
906 | 0 | flags, |
907 | 0 | pbDst, |
908 | 0 | cbDst, |
909 | 0 | pbScratch, |
910 | 0 | cbScratch - cbTmp ); |
911 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
912 | 0 | { |
913 | 0 | goto cleanup; |
914 | 0 | } |
915 | | |
916 | 0 | if (nfDst == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
917 | 0 | { |
918 | | // To implement this revert the buffer properly |
919 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
920 | 0 | goto cleanup; |
921 | 0 | } |
922 | | |
923 | 0 | scError = SYMCRYPT_NO_ERROR; |
924 | |
|
925 | 0 | cleanup: |
926 | 0 | if (pbScratch!=NULL) |
927 | 0 | { |
928 | 0 | SymCryptWipe(pbScratch,cbScratch); |
929 | 0 | SymCryptCallbackFree(pbScratch); |
930 | 0 | } |
931 | |
|
932 | 0 | return scError; |
933 | 0 | } |
934 | | |
935 | | SYMCRYPT_ERROR |
936 | | SYMCRYPT_CALL |
937 | | SymCryptRsaOaepDecrypt( |
938 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
939 | | _In_reads_bytes_( cbSrc ) PCBYTE pbSrc, |
940 | | SIZE_T cbSrc, |
941 | | SYMCRYPT_NUMBER_FORMAT nfSrc, |
942 | | _In_ PCSYMCRYPT_HASH hashAlgorithm, |
943 | | _In_reads_bytes_( cbLabel ) PCBYTE pbLabel, |
944 | | SIZE_T cbLabel, |
945 | | UINT32 flags, |
946 | | _Out_writes_opt_( cbDst ) PBYTE pbDst, |
947 | | SIZE_T cbDst, |
948 | | _Out_ SIZE_T *pcbDst ) |
949 | 0 | { |
950 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
951 | 0 | SIZE_T cbDstResult = 0; // We always return a value into *pcbDst |
952 | |
|
953 | 0 | PBYTE pbScratch = NULL; |
954 | 0 | SIZE_T cbScratch = 0; |
955 | |
|
956 | 0 | PBYTE pbTmp = NULL; |
957 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
958 | |
|
959 | 0 | UNREFERENCED_PARAMETER( flags ); |
960 | | |
961 | | // Make sure that the key may be used in Encrypt/Decrypt |
962 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_ENCRYPT) == 0 ) |
963 | 0 | { |
964 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
965 | 0 | goto cleanup; |
966 | 0 | } |
967 | | |
968 | 0 | if (cbSrc > cbTmp) |
969 | 0 | { |
970 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
971 | 0 | goto cleanup; |
972 | 0 | } |
973 | | |
974 | | // Make sure that the key has a private key |
975 | 0 | if (!pkRsakey->hasPrivateKey) |
976 | 0 | { |
977 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
978 | 0 | goto cleanup; |
979 | 0 | } |
980 | | |
981 | | // The SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP macro does not |
982 | | // overflow cbScratch since cbTmp < 2^17. |
983 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
984 | 0 | cbScratch = cbTmp + SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( hashAlgorithm, cbSrc ), SymCryptRsaCoreDecCrtScratchSpace( pkRsakey ) ); |
985 | | #else |
986 | | cbScratch = cbTmp + SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_RSA_OAEP( hashAlgorithm, cbSrc ), SymCryptRsaCoreDecScratchSpace( pkRsakey ) ); |
987 | | #endif |
988 | |
|
989 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
990 | 0 | if (pbScratch == NULL) |
991 | 0 | { |
992 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
993 | 0 | goto cleanup; |
994 | 0 | } |
995 | | |
996 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
997 | |
|
998 | 0 | if (nfSrc == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
999 | 0 | { |
1000 | | // To implement this revert the buffer properly |
1001 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
1002 | 0 | goto cleanup; |
1003 | 0 | } |
1004 | | |
1005 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
1006 | 0 | scError = SymCryptRsaCoreDecCrt( |
1007 | 0 | pkRsakey, |
1008 | 0 | pbSrc, |
1009 | 0 | cbSrc, |
1010 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1011 | 0 | flags, |
1012 | 0 | pbTmp, |
1013 | 0 | cbTmp, |
1014 | 0 | pbScratch, |
1015 | 0 | cbScratch - cbTmp ); |
1016 | | #else |
1017 | | scError = SymCryptRsaCoreDec( |
1018 | | pkRsakey, |
1019 | | pbSrc, |
1020 | | cbSrc, |
1021 | | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1022 | | flags, |
1023 | | pbTmp, |
1024 | | cbTmp, |
1025 | | pbScratch, |
1026 | | cbScratch - cbTmp ); |
1027 | | #endif |
1028 | |
|
1029 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1030 | 0 | { |
1031 | 0 | goto cleanup; |
1032 | 0 | } |
1033 | | |
1034 | 0 | scError = SymCryptRsaOaepRemoveEncryptionPadding( |
1035 | 0 | pbTmp, |
1036 | 0 | cbTmp, |
1037 | 0 | hashAlgorithm, |
1038 | 0 | pbLabel, |
1039 | 0 | cbLabel, |
1040 | 0 | flags, |
1041 | 0 | pbDst, |
1042 | 0 | cbDst, |
1043 | 0 | &cbDstResult, |
1044 | 0 | pbScratch, |
1045 | 0 | cbScratch - cbTmp ); |
1046 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1047 | 0 | { |
1048 | 0 | goto cleanup; |
1049 | 0 | } |
1050 | | |
1051 | 0 | scError = SYMCRYPT_NO_ERROR; |
1052 | |
|
1053 | 0 | cleanup: |
1054 | 0 | if (pbScratch!=NULL) |
1055 | 0 | { |
1056 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1057 | 0 | SymCryptCallbackFree(pbScratch); |
1058 | 0 | } |
1059 | |
|
1060 | 0 | *pcbDst = cbDstResult; |
1061 | |
|
1062 | 0 | return scError; |
1063 | 0 | } |
1064 | | |
1065 | | // |
1066 | | // Signing / Verification functions |
1067 | | // |
1068 | | |
1069 | | SYMCRYPT_ERROR |
1070 | | SYMCRYPT_CALL |
1071 | | SymCryptRsaPkcs1Sign( |
1072 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1073 | | _In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue, |
1074 | | SIZE_T cbHashValue, |
1075 | | _In_ PCSYMCRYPT_OID pHashOIDs, |
1076 | | _In_ SIZE_T nOIDCount, |
1077 | | UINT32 flags, |
1078 | | SYMCRYPT_NUMBER_FORMAT nfSignature, |
1079 | | _Out_writes_opt_( cbSignature ) PBYTE pbSignature, |
1080 | | SIZE_T cbSignature, |
1081 | | _Out_ SIZE_T *pcbSignature ) |
1082 | 0 | { |
1083 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1084 | |
|
1085 | 0 | PBYTE pbScratch = NULL; |
1086 | 0 | SIZE_T cbScratch = 0; |
1087 | |
|
1088 | 0 | PBYTE pbTmp = NULL; |
1089 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
1090 | |
|
1091 | 0 | PCBYTE pbOID = NULL; |
1092 | 0 | SIZE_T cbOID = 0; |
1093 | |
|
1094 | 0 | UNREFERENCED_PARAMETER(nOIDCount); |
1095 | |
|
1096 | 0 | pbOID = pHashOIDs ? pHashOIDs->pbOID : NULL; |
1097 | 0 | cbOID = pHashOIDs ? pHashOIDs->cbOID : 0; |
1098 | | |
1099 | | // Make sure that the key may be used in Sign/Verify |
1100 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 ) |
1101 | 0 | { |
1102 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1103 | 0 | goto cleanup; |
1104 | 0 | } |
1105 | | |
1106 | | // Make sure that the key has a private key |
1107 | 0 | if (!pkRsakey->hasPrivateKey) |
1108 | 0 | { |
1109 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1110 | 0 | goto cleanup; |
1111 | 0 | } |
1112 | | |
1113 | 0 | *pcbSignature = cbTmp; |
1114 | | |
1115 | | // Check if only *pcbSignature is needed |
1116 | 0 | if (pbSignature == NULL) |
1117 | 0 | { |
1118 | 0 | scError = SYMCRYPT_NO_ERROR; |
1119 | 0 | goto cleanup; |
1120 | 0 | } |
1121 | | |
1122 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
1123 | 0 | cbScratch = cbTmp + SymCryptRsaCoreDecCrtScratchSpace( pkRsakey ); |
1124 | | #else |
1125 | | cbScratch = cbTmp + SymCryptRsaCoreDecScratchSpace( pkRsakey ); |
1126 | | #endif |
1127 | |
|
1128 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
1129 | 0 | if (pbScratch == NULL) |
1130 | 0 | { |
1131 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
1132 | 0 | goto cleanup; |
1133 | 0 | } |
1134 | | |
1135 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
1136 | |
|
1137 | 0 | scError = SymCryptRsaPkcs1ApplySignaturePadding( |
1138 | 0 | pbHashValue, |
1139 | 0 | cbHashValue, |
1140 | 0 | pbOID, |
1141 | 0 | cbOID, |
1142 | 0 | flags, |
1143 | 0 | pbTmp, |
1144 | 0 | cbTmp ); |
1145 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1146 | 0 | { |
1147 | 0 | goto cleanup; |
1148 | 0 | } |
1149 | | |
1150 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
1151 | 0 | scError = SymCryptRsaCoreDecCrt( |
1152 | 0 | pkRsakey, |
1153 | 0 | pbTmp, |
1154 | 0 | cbTmp, |
1155 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1156 | 0 | flags, |
1157 | 0 | pbSignature, |
1158 | 0 | cbSignature, |
1159 | 0 | pbScratch, |
1160 | 0 | cbScratch - cbTmp ); |
1161 | | #else |
1162 | | scError = SymCryptRsaCoreDec( |
1163 | | pkRsakey, |
1164 | | pbTmp, |
1165 | | cbTmp, |
1166 | | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1167 | | flags, |
1168 | | pbSignature, |
1169 | | cbSignature, |
1170 | | pbScratch, |
1171 | | cbScratch - cbTmp ); |
1172 | | #endif |
1173 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1174 | 0 | { |
1175 | 0 | goto cleanup; |
1176 | 0 | } |
1177 | | |
1178 | 0 | if (nfSignature == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
1179 | 0 | { |
1180 | | // To implement this revert the buffer properly |
1181 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
1182 | 0 | goto cleanup; |
1183 | 0 | } |
1184 | | |
1185 | 0 | scError = SYMCRYPT_NO_ERROR; |
1186 | |
|
1187 | 0 | cleanup: |
1188 | 0 | if (pbScratch!=NULL) |
1189 | 0 | { |
1190 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1191 | 0 | SymCryptCallbackFree(pbScratch); |
1192 | 0 | } |
1193 | |
|
1194 | 0 | return scError; |
1195 | 0 | } |
1196 | | |
1197 | | SYMCRYPT_ERROR |
1198 | | SYMCRYPT_CALL |
1199 | | SymCryptRsaPkcs1Verify( |
1200 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1201 | | _In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue, |
1202 | | SIZE_T cbHashValue, |
1203 | | _In_reads_bytes_( cbSignature ) PCBYTE pbSignature, |
1204 | | SIZE_T cbSignature, |
1205 | | SYMCRYPT_NUMBER_FORMAT nfSignature, |
1206 | | _In_reads_opt_( nOIDCount ) PCSYMCRYPT_OID pHashOIDs, |
1207 | | _In_ SIZE_T nOIDCount, |
1208 | | UINT32 flags ) |
1209 | 0 | { |
1210 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1211 | |
|
1212 | 0 | PBYTE pbScratch = NULL; |
1213 | 0 | SIZE_T cbScratch = 0; |
1214 | |
|
1215 | 0 | PBYTE pbTmp = NULL; |
1216 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
1217 | | |
1218 | | // Make sure that the key may be used in Sign/Verify |
1219 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 ) |
1220 | 0 | { |
1221 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1222 | 0 | goto cleanup; |
1223 | 0 | } |
1224 | | |
1225 | 0 | if (cbSignature > cbTmp) |
1226 | 0 | { |
1227 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1228 | 0 | goto cleanup; |
1229 | 0 | } |
1230 | | |
1231 | 0 | if (nfSignature == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
1232 | 0 | { |
1233 | | // To implement this revert the buffer properly |
1234 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
1235 | 0 | goto cleanup; |
1236 | 0 | } |
1237 | | |
1238 | | // The SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PKCS1 macro does not |
1239 | | // overflow cbScratch since cbTmp < 2^17. |
1240 | 0 | cbScratch = cbTmp + |
1241 | 0 | SYMCRYPT_MAX( SymCryptRsaCoreEncScratchSpace( pkRsakey ), |
1242 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PKCS1( cbTmp ) ); |
1243 | |
|
1244 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
1245 | 0 | if (pbScratch == NULL) |
1246 | 0 | { |
1247 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
1248 | 0 | goto cleanup; |
1249 | 0 | } |
1250 | | |
1251 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
1252 | |
|
1253 | 0 | scError = SymCryptRsaCoreEnc( |
1254 | 0 | pkRsakey, |
1255 | 0 | pbSignature, |
1256 | 0 | cbSignature, |
1257 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1258 | 0 | flags, |
1259 | 0 | pbTmp, |
1260 | 0 | cbTmp, |
1261 | 0 | pbScratch, |
1262 | 0 | cbScratch - cbTmp ); |
1263 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1264 | 0 | { |
1265 | 0 | goto cleanup; |
1266 | 0 | } |
1267 | | |
1268 | 0 | scError = SymCryptRsaPkcs1VerifySignaturePadding( |
1269 | 0 | pbHashValue, |
1270 | 0 | cbHashValue, |
1271 | 0 | pHashOIDs, |
1272 | 0 | nOIDCount, |
1273 | 0 | pbTmp, |
1274 | 0 | cbTmp, |
1275 | 0 | flags, |
1276 | 0 | pbScratch, |
1277 | 0 | cbScratch - cbTmp ); |
1278 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1279 | 0 | { |
1280 | 0 | goto cleanup; |
1281 | 0 | } |
1282 | | |
1283 | 0 | scError = SYMCRYPT_NO_ERROR; |
1284 | |
|
1285 | 0 | cleanup: |
1286 | 0 | if (pbScratch!=NULL) |
1287 | 0 | { |
1288 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1289 | 0 | SymCryptCallbackFree(pbScratch); |
1290 | 0 | } |
1291 | |
|
1292 | 0 | return scError; |
1293 | 0 | } |
1294 | | |
1295 | | SYMCRYPT_ERROR |
1296 | | SYMCRYPT_CALL |
1297 | | SymCryptRsaPssSign( |
1298 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1299 | | _In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue, |
1300 | | SIZE_T cbHashValue, |
1301 | | _In_ PCSYMCRYPT_HASH hashAlgorithm, |
1302 | | SIZE_T cbSalt, |
1303 | | UINT32 flags, |
1304 | | SYMCRYPT_NUMBER_FORMAT nfSignature, |
1305 | | _Out_writes_opt_( cbSignature ) PBYTE pbSignature, |
1306 | | SIZE_T cbSignature, |
1307 | | _Out_ SIZE_T *pcbSignature ) |
1308 | 0 | { |
1309 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1310 | |
|
1311 | 0 | PBYTE pbScratch = NULL; |
1312 | 0 | SIZE_T cbScratch = 0; |
1313 | |
|
1314 | 0 | PBYTE pbTmp = NULL; |
1315 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
1316 | | |
1317 | | // Make sure that the key may be used in Sign/Verify |
1318 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 ) |
1319 | 0 | { |
1320 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1321 | 0 | goto cleanup; |
1322 | 0 | } |
1323 | | |
1324 | 0 | if ( (cbHashValue > cbTmp) || |
1325 | 0 | (cbSalt > cbTmp) ) |
1326 | 0 | { |
1327 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1328 | 0 | goto cleanup; |
1329 | 0 | } |
1330 | | |
1331 | | // Make sure that the key has a private key |
1332 | 0 | if (!pkRsakey->hasPrivateKey) |
1333 | 0 | { |
1334 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1335 | 0 | goto cleanup; |
1336 | 0 | } |
1337 | | |
1338 | 0 | *pcbSignature = cbTmp; |
1339 | | |
1340 | | // Check if only *pcbSignature is needed |
1341 | 0 | if (pbSignature == NULL) |
1342 | 0 | { |
1343 | 0 | scError = SYMCRYPT_NO_ERROR; |
1344 | 0 | goto cleanup; |
1345 | 0 | } |
1346 | | |
1347 | | // The SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS macro does not |
1348 | | // overflow cbScratch since cbTmp < 2^17. |
1349 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
1350 | 0 | cbScratch = cbTmp + |
1351 | 0 | SYMCRYPT_MAX( SymCryptRsaCoreDecCrtScratchSpace( pkRsakey ), |
1352 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( hashAlgorithm, cbHashValue, cbTmp ) ); |
1353 | | #else |
1354 | | cbScratch = cbTmp + |
1355 | | SYMCRYPT_MAX( SymCryptRsaCoreDecScratchSpace( pkRsakey ), |
1356 | | SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( hashAlgorithm, cbHashValue, cbTmp ) ); |
1357 | | #endif |
1358 | |
|
1359 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
1360 | 0 | if (pbScratch == NULL) |
1361 | 0 | { |
1362 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
1363 | 0 | goto cleanup; |
1364 | 0 | } |
1365 | | |
1366 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
1367 | |
|
1368 | 0 | scError = SymCryptRsaPssApplySignaturePadding( |
1369 | 0 | pbHashValue, |
1370 | 0 | cbHashValue, |
1371 | 0 | hashAlgorithm, |
1372 | 0 | NULL, // For now only random salt supported |
1373 | 0 | cbSalt, |
1374 | 0 | pkRsakey->nBitsOfModulus, |
1375 | 0 | flags, |
1376 | 0 | pbTmp, |
1377 | 0 | cbTmp, |
1378 | 0 | pbScratch, |
1379 | 0 | cbScratch - cbTmp ); |
1380 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1381 | 0 | { |
1382 | 0 | goto cleanup; |
1383 | 0 | } |
1384 | | |
1385 | 0 | #if (SYMCRYPT_CRT_DECRYPTION) |
1386 | 0 | scError = SymCryptRsaCoreDecCrt( |
1387 | 0 | pkRsakey, |
1388 | 0 | pbTmp, |
1389 | 0 | cbTmp, |
1390 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1391 | 0 | flags, |
1392 | 0 | pbSignature, |
1393 | 0 | cbSignature, |
1394 | 0 | pbScratch, |
1395 | 0 | cbScratch - cbTmp ); |
1396 | | #else |
1397 | | scError = SymCryptRsaCoreDec( |
1398 | | pkRsakey, |
1399 | | pbTmp, |
1400 | | cbTmp, |
1401 | | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1402 | | flags, |
1403 | | pbSignature, |
1404 | | cbSignature, |
1405 | | pbScratch, |
1406 | | cbScratch - cbTmp ); |
1407 | | #endif |
1408 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1409 | 0 | { |
1410 | 0 | goto cleanup; |
1411 | 0 | } |
1412 | | |
1413 | 0 | if (nfSignature == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
1414 | 0 | { |
1415 | | // To implement this revert the buffer properly |
1416 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
1417 | 0 | goto cleanup; |
1418 | 0 | } |
1419 | | |
1420 | 0 | scError = SYMCRYPT_NO_ERROR; |
1421 | |
|
1422 | 0 | cleanup: |
1423 | 0 | if (pbScratch!=NULL) |
1424 | 0 | { |
1425 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1426 | 0 | SymCryptCallbackFree(pbScratch); |
1427 | 0 | } |
1428 | |
|
1429 | 0 | return scError; |
1430 | 0 | } |
1431 | | |
1432 | | SYMCRYPT_ERROR |
1433 | | SYMCRYPT_CALL |
1434 | | SymCryptRsaPssVerify( |
1435 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1436 | | _In_reads_bytes_( cbHashValue ) PCBYTE pbHashValue, |
1437 | | SIZE_T cbHashValue, |
1438 | | _In_reads_bytes_( cbSignature ) PCBYTE pbSignature, |
1439 | | SIZE_T cbSignature, |
1440 | | SYMCRYPT_NUMBER_FORMAT nfSignature, |
1441 | | _In_ PCSYMCRYPT_HASH hashAlgorithm, |
1442 | | SIZE_T cbSalt, |
1443 | | UINT32 flags ) |
1444 | 0 | { |
1445 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1446 | |
|
1447 | 0 | PBYTE pbScratch = NULL; |
1448 | 0 | SIZE_T cbScratch = 0; |
1449 | |
|
1450 | 0 | PBYTE pbTmp = NULL; |
1451 | 0 | SIZE_T cbTmp = SymCryptRsakeySizeofModulus(pkRsakey); |
1452 | | |
1453 | | // Make sure that the key may be used in Sign/Verify |
1454 | 0 | if ( (pkRsakey->fAlgorithmInfo & SYMCRYPT_FLAG_RSAKEY_SIGN) == 0 ) |
1455 | 0 | { |
1456 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1457 | 0 | goto cleanup; |
1458 | 0 | } |
1459 | | |
1460 | 0 | if ( (cbHashValue > cbTmp) || |
1461 | 0 | (cbSalt > cbTmp) || |
1462 | 0 | (cbSignature > cbTmp) ) |
1463 | 0 | { |
1464 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1465 | 0 | goto cleanup; |
1466 | 0 | } |
1467 | | |
1468 | 0 | if (nfSignature == SYMCRYPT_NUMBER_FORMAT_LSB_FIRST) |
1469 | 0 | { |
1470 | | // To implement this revert the buffer properly |
1471 | 0 | scError = SYMCRYPT_NOT_IMPLEMENTED; |
1472 | 0 | goto cleanup; |
1473 | 0 | } |
1474 | | |
1475 | | // The SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS macro does not |
1476 | | // overflow cbScratch since cbTmp < 2^17. |
1477 | 0 | cbScratch = cbTmp + |
1478 | 0 | SYMCRYPT_MAX( SymCryptRsaCoreEncScratchSpace( pkRsakey ), |
1479 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_RSA_PSS( hashAlgorithm, cbHashValue, cbTmp ) ); |
1480 | |
|
1481 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
1482 | 0 | if (pbScratch == NULL) |
1483 | 0 | { |
1484 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
1485 | 0 | goto cleanup; |
1486 | 0 | } |
1487 | | |
1488 | 0 | pbTmp = pbScratch + cbScratch - cbTmp; |
1489 | |
|
1490 | 0 | scError = SymCryptRsaCoreEnc( |
1491 | 0 | pkRsakey, |
1492 | 0 | pbSignature, |
1493 | 0 | cbSignature, |
1494 | 0 | SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, |
1495 | 0 | flags, |
1496 | 0 | pbTmp, |
1497 | 0 | cbTmp, |
1498 | 0 | pbScratch, |
1499 | 0 | cbScratch - cbTmp ); |
1500 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1501 | 0 | { |
1502 | 0 | goto cleanup; |
1503 | 0 | } |
1504 | | |
1505 | 0 | scError = SymCryptRsaPssVerifySignaturePadding( |
1506 | 0 | pbHashValue, |
1507 | 0 | cbHashValue, |
1508 | 0 | hashAlgorithm, |
1509 | 0 | cbSalt, |
1510 | 0 | pbTmp, |
1511 | 0 | cbTmp, |
1512 | 0 | pkRsakey->nBitsOfModulus, |
1513 | 0 | flags, |
1514 | 0 | pbScratch, |
1515 | 0 | cbScratch - cbTmp ); |
1516 | 0 | if (scError != SYMCRYPT_NO_ERROR) |
1517 | 0 | { |
1518 | 0 | goto cleanup; |
1519 | 0 | } |
1520 | | |
1521 | 0 | scError = SYMCRYPT_NO_ERROR; |
1522 | |
|
1523 | 0 | cleanup: |
1524 | 0 | if (pbScratch!=NULL) |
1525 | 0 | { |
1526 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1527 | 0 | SymCryptCallbackFree(pbScratch); |
1528 | 0 | } |
1529 | |
|
1530 | 0 | return scError; |
1531 | 0 | } |