/src/SymCrypt/lib/rsakey.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // rsakey.c RSA keys' related algorithms |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | #include "precomp.h" |
8 | | |
9 | 0 | #define RSA_DEFAULT_PUBLIC_EXPONENT (65537) |
10 | | |
11 | | PSYMCRYPT_RSAKEY |
12 | | SYMCRYPT_CALL |
13 | | SymCryptRsakeyAllocate( |
14 | | _In_ PCSYMCRYPT_RSA_PARAMS pParams, |
15 | | _In_ UINT32 flags ) |
16 | 0 | { |
17 | 0 | PVOID p; |
18 | 0 | SIZE_T cb; |
19 | 0 | PSYMCRYPT_RSAKEY res = NULL; |
20 | |
|
21 | 0 | UNREFERENCED_PARAMETER( flags ); |
22 | |
|
23 | 0 | SYMCRYPT_ASSERT( pParams != NULL ); |
24 | |
|
25 | 0 | cb = SymCryptSizeofRsakeyFromParams( pParams ); |
26 | |
|
27 | 0 | p = SymCryptCallbackAlloc( cb ); |
28 | |
|
29 | 0 | if ( p==NULL ) |
30 | 0 | { |
31 | 0 | goto cleanup; |
32 | 0 | } |
33 | | |
34 | 0 | res = SymCryptRsakeyCreate( p, cb, pParams ); |
35 | |
|
36 | 0 | cleanup: |
37 | 0 | return res; |
38 | 0 | } |
39 | | |
40 | | VOID |
41 | | SYMCRYPT_CALL |
42 | | SymCryptRsakeyFree( _Out_ PSYMCRYPT_RSAKEY pkObj ) |
43 | 0 | { |
44 | 0 | SYMCRYPT_CHECK_MAGIC( pkObj ); |
45 | 0 | SymCryptRsakeyWipe( pkObj ); |
46 | 0 | SymCryptCallbackFree( pkObj ); |
47 | 0 | } |
48 | | |
49 | | UINT32 |
50 | | SYMCRYPT_CALL |
51 | | SymCryptSizeofRsakeyFromParams( _In_ PCSYMCRYPT_RSA_PARAMS pParams ) |
52 | 0 | { |
53 | 0 | UINT32 nModulusDigits; |
54 | 0 | UINT32 res; |
55 | |
|
56 | 0 | SYMCRYPT_ASSERT( pParams != NULL ); |
57 | |
|
58 | 0 | nModulusDigits = SymCryptDigitsFromBits( pParams->nBitsOfModulus ); |
59 | | |
60 | | // |
61 | | // From symcrypt_internal.h we have: |
62 | | // - sizeof results are upper bounded by 2^19 |
63 | | // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE) |
64 | | // - nPrimes and nPubExps are bounded by SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES = 2 and |
65 | | // SYMCRYPT_RSAKEY_MAX_NUMOF_PUBEXPS = 1 |
66 | | // Thus the following calculation does not overflow the result. |
67 | | // |
68 | 0 | res = sizeof(SYMCRYPT_RSAKEY) + |
69 | 0 | SymCryptSizeofModulusFromDigits( nModulusDigits ) + // For Modulus |
70 | 0 | pParams->nPrimes * SymCryptSizeofModulusFromDigits( nModulusDigits ) + // For Primes |
71 | 0 | pParams->nPrimes * SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pParams->nBitsOfModulus ) + // For CrtInverses |
72 | 0 | pParams->nPubExp * SymCryptSizeofIntFromDigits( nModulusDigits ) + // For PrivExps |
73 | 0 | pParams->nPubExp * pParams->nPrimes * SymCryptSizeofIntFromDigits( nModulusDigits ); // For CrtPrivExps |
74 | | |
75 | | // Consistency check with the static macro (optimized away in production) |
76 | 0 | SYMCRYPT_ASSERT( res <= SYMCRYPT_SIZEOF_RSAKEY_FROM_PARAMS( pParams->nBitsOfModulus, pParams->nPrimes, pParams->nPubExp ) ); |
77 | |
|
78 | 0 | return res; |
79 | 0 | } |
80 | | |
81 | | PSYMCRYPT_RSAKEY |
82 | | SYMCRYPT_CALL |
83 | | SymCryptRsakeyCreate( |
84 | | _Out_writes_bytes_( cbBuffer ) PBYTE pbBuffer, |
85 | | SIZE_T cbBuffer, |
86 | | _In_ PCSYMCRYPT_RSA_PARAMS pParams ) |
87 | 0 | { |
88 | 0 | PSYMCRYPT_RSAKEY pkObj = NULL; |
89 | |
|
90 | 0 | PBYTE pbCurr = pbBuffer; |
91 | 0 | SIZE_T cbNeeded; |
92 | 0 | SIZE_T itemSize; |
93 | |
|
94 | 0 | SYMCRYPT_ASSERT( pParams != NULL ); |
95 | |
|
96 | 0 | cbNeeded = SymCryptSizeofRsakeyFromParams( pParams ); |
97 | |
|
98 | 0 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pbCurr ); |
99 | |
|
100 | 0 | if (( cbBuffer < cbNeeded ) || |
101 | 0 | ( pParams->nBitsOfModulus < SYMCRYPT_RSAKEY_MIN_BITSIZE_MODULUS ) || |
102 | 0 | ( pParams->nBitsOfModulus > SYMCRYPT_RSAKEY_MAX_BITSIZE_MODULUS ) || |
103 | 0 | ( pParams->nPubExp < 1 ) || |
104 | 0 | ( pParams->nPubExp > SYMCRYPT_RSAKEY_MAX_NUMOF_PUBEXPS ) || |
105 | 0 | ( pParams->nPrimes == 1 ) || |
106 | 0 | ( pParams->nPrimes > SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES ) ) |
107 | 0 | { |
108 | 0 | goto cleanup; |
109 | 0 | } |
110 | 0 | SYMCRYPT_ASSERT( cbBuffer >= sizeof( SYMCRYPT_RSAKEY ) ); |
111 | |
|
112 | 0 | pkObj = (PSYMCRYPT_RSAKEY) pbCurr; |
113 | | |
114 | | // Set all the parameters to 0 |
115 | 0 | SymCryptWipe( pbBuffer, cbBuffer ); |
116 | | |
117 | | // Main parameters of the RSAKEY |
118 | | // Everything is 0 until created |
119 | |
|
120 | 0 | pkObj->cbTotalSize = (UINT32) cbNeeded; |
121 | | // The result should always be within 4 GB, but we check to avoid security bugs |
122 | 0 | SYMCRYPT_ASSERT( pkObj->cbTotalSize == cbNeeded ); |
123 | |
|
124 | 0 | pkObj->hasPrivateKey = FALSE; |
125 | |
|
126 | 0 | pkObj->nSetBitsOfModulus = pParams->nBitsOfModulus; |
127 | 0 | pkObj->nDigitsOfModulus = SymCryptDigitsFromBits( pkObj->nSetBitsOfModulus ); // The modulus object has always this number of digits |
128 | |
|
129 | 0 | pkObj->nPrimes = pParams->nPrimes; |
130 | 0 | pkObj->nPubExp = pParams->nPubExp; |
131 | |
|
132 | 0 | pbCurr += sizeof( SYMCRYPT_RSAKEY ); |
133 | | |
134 | | // Modulus |
135 | 0 | itemSize = SymCryptSizeofModulusFromDigits( pkObj->nDigitsOfModulus ); |
136 | 0 | SYMCRYPT_ASSERT( cbBuffer >= sizeof( SYMCRYPT_RSAKEY ) + itemSize |
137 | 0 | + (pkObj->nPrimes*SymCryptSizeofModulusFromDigits( pkObj->nDigitsOfModulus )) |
138 | 0 | + (pkObj->nPrimes*SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pParams->nBitsOfModulus )) |
139 | 0 | + (pkObj->nPubExp*SymCryptSizeofIntFromDigits( pkObj->nDigitsOfModulus )) |
140 | 0 | + (pkObj->nPubExp*pkObj->nPrimes*SymCryptSizeofIntFromDigits( pkObj->nDigitsOfModulus )) ); |
141 | 0 | pkObj->pmModulus = SymCryptModulusCreate( |
142 | 0 | pbCurr, |
143 | 0 | itemSize, |
144 | 0 | pkObj->nDigitsOfModulus ); |
145 | 0 | SYMCRYPT_ASSERT( pkObj->pmModulus != NULL ); |
146 | 0 | pbCurr += itemSize; |
147 | | |
148 | | // For the remaining objects |
149 | | // defer creation until SymCryptRsakeyGenerate or |
150 | | // SymCryptRsakeySetValue |
151 | | |
152 | | // Primes |
153 | 0 | for (UINT32 i=0; i<pkObj->nPrimes; i++) |
154 | 0 | { |
155 | 0 | pkObj->pbPrimes[i] = pbCurr; |
156 | 0 | pbCurr += SymCryptSizeofModulusFromDigits( pkObj->nDigitsOfModulus ); |
157 | 0 | } |
158 | | |
159 | | // CRT Inverses of primes |
160 | 0 | for (UINT32 i=0; i<pkObj->nPrimes; i++) |
161 | 0 | { |
162 | 0 | pkObj->pbCrtInverses[i] = pbCurr; |
163 | 0 | pbCurr += SYMCRYPT_SIZEOF_MODELEMENT_FROM_BITS( pParams->nBitsOfModulus ); |
164 | 0 | } |
165 | | |
166 | | // Private exponents |
167 | 0 | for (UINT32 i=0; i<pkObj->nPubExp; i++) |
168 | 0 | { |
169 | 0 | pkObj->pbPrivExps[i] = pbCurr; |
170 | 0 | pbCurr += SymCryptSizeofIntFromDigits( pkObj->nDigitsOfModulus ); |
171 | 0 | } |
172 | | |
173 | | // Private exponents modulo each prime (minus 1) |
174 | 0 | for (UINT32 i=0; i<pkObj->nPubExp*pkObj->nPrimes; i++) |
175 | 0 | { |
176 | 0 | pkObj->pbCrtPrivExps[i] = pbCurr; |
177 | 0 | pbCurr += SymCryptSizeofIntFromDigits( pkObj->nDigitsOfModulus ); |
178 | 0 | } |
179 | | |
180 | | // Setting the magic |
181 | 0 | SYMCRYPT_SET_MAGIC( pkObj ); |
182 | |
|
183 | 0 | cleanup: |
184 | 0 | return pkObj; |
185 | 0 | } |
186 | | |
187 | | VOID |
188 | | SYMCRYPT_CALL |
189 | | SymCryptRsakeyWipe( _Out_ PSYMCRYPT_RSAKEY pkDst ) |
190 | 0 | { |
191 | | // Wipe the whole structure in one go. |
192 | 0 | SymCryptWipe( pkDst, pkDst->cbTotalSize ); |
193 | 0 | } |
194 | | |
195 | | #if 0 |
196 | | VOID |
197 | | SYMCRYPT_CALL |
198 | | SymCryptRsakeyCopy( |
199 | | _In_ PCSYMCRYPT_RSAKEY pkSrc, |
200 | | _Out_ PSYMCRYPT_RSAKEY pkDst ) |
201 | | { |
202 | | SymCryptFatal( 'rsac' ); |
203 | | // This function doesn't work correctly because subobjects might |
204 | | // not have been created yet. |
205 | | // Future: fix this |
206 | | |
207 | | // |
208 | | // in-place copy is somewhat common... |
209 | | // |
210 | | if( pkSrc != pkDst ) |
211 | | { |
212 | | pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo; |
213 | | pkDst->cbTotalSize = pkSrc->cbTotalSize; |
214 | | pkDst->hasPrivateKey = pkSrc->hasPrivateKey; |
215 | | pkDst->nSetBitsOfModulus = pkSrc->nSetBitsOfModulus; |
216 | | |
217 | | pkDst->nBitsOfModulus = pkSrc->nBitsOfModulus; |
218 | | pkDst->nDigitsOfModulus = pkSrc->nDigitsOfModulus; |
219 | | |
220 | | pkDst->nPubExp = pkSrc->nPubExp; |
221 | | for (UINT32 i=0; i<SYMCRYPT_RSAKEY_MAX_NUMOF_PUBEXPS; i++) |
222 | | { |
223 | | pkDst->au64PubExp[i] = pkSrc->au64PubExp[i]; |
224 | | } |
225 | | |
226 | | pkDst->nPrimes = pkSrc->nPrimes; |
227 | | for (UINT32 i=0; i<SYMCRYPT_RSAKEY_MAX_NUMOF_PRIMES; i++) |
228 | | { |
229 | | pkDst->nBitsOfPrimes[i] = pkSrc->nBitsOfPrimes[i]; |
230 | | pkDst->nDigitsOfPrimes[i] = pkSrc->nDigitsOfPrimes[i]; |
231 | | } |
232 | | |
233 | | // Copy the objects |
234 | | SymCryptModulusCopy( pkSrc->pmModulus, pkDst->pmModulus ); |
235 | | |
236 | | for (UINT32 i=0; i< pkSrc->nPrimes; i++) |
237 | | { |
238 | | SymCryptModulusCopy( pkSrc->pmPrimes[i], pkDst->pmPrimes[i] ); |
239 | | SymCryptModElementCopy( pkSrc->pmPrimes[i], pkSrc->peCrtInverses[i], pkDst->peCrtInverses[i] ); |
240 | | } |
241 | | |
242 | | for (UINT32 i=0; i< pkSrc->nPubExp; i++) |
243 | | { |
244 | | SymCryptIntCopy( pkSrc->piPrivExps[i], pkDst->piPrivExps[i] ); |
245 | | } |
246 | | |
247 | | for (UINT32 i=0; i< pkSrc->nPubExp*pkSrc->nPrimes; i++) |
248 | | { |
249 | | SymCryptIntCopy( pkSrc->piCrtPrivExps[i], pkDst->piCrtPrivExps[i] ); |
250 | | } |
251 | | } |
252 | | } |
253 | | #endif |
254 | | |
255 | | BOOLEAN |
256 | | SYMCRYPT_CALL |
257 | | SymCryptRsakeyHasPrivateKey( _In_ PCSYMCRYPT_RSAKEY pkRsakey ) |
258 | 0 | { |
259 | 0 | return pkRsakey->hasPrivateKey; |
260 | 0 | } |
261 | | |
262 | | UINT32 |
263 | | SYMCRYPT_CALL |
264 | | SymCryptRsakeySizeofModulus( _In_ PCSYMCRYPT_RSAKEY pkRsakey ) |
265 | 0 | { |
266 | 0 | return (pkRsakey->nBitsOfModulus + 7)/8; |
267 | 0 | } |
268 | | |
269 | | UINT32 |
270 | | SYMCRYPT_CALL |
271 | | SymCryptRsakeyModulusBits( _In_ PCSYMCRYPT_RSAKEY pkRsakey ) |
272 | 0 | { |
273 | 0 | return pkRsakey->nBitsOfModulus; |
274 | 0 | } |
275 | | |
276 | | UINT32 |
277 | | SYMCRYPT_CALL |
278 | | SymCryptRsakeySizeofPublicExponent( |
279 | | _In_ PCSYMCRYPT_RSAKEY pRsakey, |
280 | | UINT32 index ) |
281 | 0 | { |
282 | 0 | SYMCRYPT_ASSERT( index == 0 ); |
283 | 0 | UNREFERENCED_PARAMETER( index ); |
284 | 0 | return SymCryptUint64Bytesize( pRsakey->au64PubExp[0] ); |
285 | 0 | } |
286 | | |
287 | | UINT32 |
288 | | SYMCRYPT_CALL |
289 | | SymCryptRsakeySizeofPrime( |
290 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
291 | | UINT32 index ) |
292 | 0 | { |
293 | 0 | return (pkRsakey->nBitsOfPrimes[index] + 7)/8; |
294 | 0 | } |
295 | | |
296 | | UINT32 |
297 | | SYMCRYPT_CALL |
298 | | SymCryptRsakeyGetNumberOfPublicExponents( _In_ PCSYMCRYPT_RSAKEY pkRsakey ) |
299 | 0 | { |
300 | 0 | return pkRsakey->nPubExp; |
301 | 0 | } |
302 | | |
303 | | UINT32 |
304 | | SYMCRYPT_CALL |
305 | | SymCryptRsakeyGetNumberOfPrimes( _In_ PCSYMCRYPT_RSAKEY pkRsakey ) |
306 | 0 | { |
307 | 0 | return pkRsakey->nPrimes; |
308 | 0 | } |
309 | | |
310 | | VOID |
311 | | SYMCRYPT_CALL |
312 | | SymCryptRsakeyCreateAllObjects( _Inout_ PSYMCRYPT_RSAKEY pkRsakey ) |
313 | 0 | { |
314 | | // Primes |
315 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
316 | 0 | { |
317 | 0 | pkRsakey->pmPrimes[i] = SymCryptModulusCreate( |
318 | 0 | pkRsakey->pbPrimes[i], |
319 | 0 | SymCryptSizeofModulusFromDigits( pkRsakey->nDigitsOfPrimes[i] ), |
320 | 0 | pkRsakey->nDigitsOfPrimes[i] ); |
321 | 0 | SYMCRYPT_ASSERT( pkRsakey->pmPrimes[i] != NULL ); |
322 | 0 | } |
323 | | |
324 | | // CRT Inverses of primes |
325 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
326 | 0 | { |
327 | 0 | pkRsakey->peCrtInverses[i] = SymCryptModElementCreate( |
328 | 0 | pkRsakey->pbCrtInverses[i], |
329 | 0 | SymCryptSizeofModElementFromModulus( pkRsakey->pmPrimes[i] ), |
330 | 0 | pkRsakey->pmPrimes[i] ); |
331 | 0 | SYMCRYPT_ASSERT( pkRsakey->peCrtInverses[i] != NULL ); |
332 | 0 | } |
333 | | |
334 | | // Private exponents |
335 | 0 | for( UINT32 i=0; i<pkRsakey->nPubExp; i++ ) |
336 | 0 | { |
337 | 0 | pkRsakey->piPrivExps[i] = SymCryptIntCreate( |
338 | 0 | pkRsakey->pbPrivExps[i], |
339 | 0 | SymCryptSizeofIntFromDigits( pkRsakey->nDigitsOfModulus ), |
340 | 0 | pkRsakey->nDigitsOfModulus ); |
341 | 0 | SYMCRYPT_ASSERT( pkRsakey->piPrivExps[i] != NULL ); |
342 | 0 | } |
343 | | |
344 | | // Private exponents modulo each prime (minus 1) |
345 | 0 | for (UINT32 i=0; i<pkRsakey->nPubExp*pkRsakey->nPrimes; i++) |
346 | 0 | { |
347 | 0 | pkRsakey->piCrtPrivExps[i] = SymCryptIntCreate( |
348 | 0 | pkRsakey->pbCrtPrivExps[i], |
349 | 0 | SymCryptSizeofIntFromDigits( pkRsakey->nDigitsOfPrimes[i] ), |
350 | 0 | pkRsakey->nDigitsOfPrimes[i] ); |
351 | 0 | SYMCRYPT_ASSERT( pkRsakey->piCrtPrivExps[i] != NULL ); |
352 | 0 | } |
353 | 0 | } |
354 | | |
355 | | SYMCRYPT_ERROR |
356 | | SYMCRYPT_CALL |
357 | | SymCryptRsakeyCalculatePrivateFields( |
358 | | _Inout_ PSYMCRYPT_RSAKEY pkRsakey, |
359 | | _Out_ PSYMCRYPT_DIVISOR pdTmp, // Temporary of nMaxDigitsOfPrimes |
360 | | _Out_ PSYMCRYPT_INT piPhi, // Temporary of nDigitsOfModulus |
361 | | _Out_ PSYMCRYPT_INT piAcc, // Temporary of nMaxDigitsOfPrimes + nDigitsOfModulus |
362 | | _Out_writes_bytes_( cbScratch ) |
363 | | PBYTE pbScratch, |
364 | | SIZE_T cbScratch |
365 | | ) |
366 | 0 | { |
367 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
368 | 0 | BYTE tmpGcdBuf[ SYMCRYPT_SIZEOF_INT_FROM_BITS( 64 ) + SYMCRYPT_ASYM_ALIGN_VALUE]; |
369 | 0 | PSYMCRYPT_INT piTmpGcd; |
370 | | |
371 | | // Use pdTmp as int scratch |
372 | 0 | PSYMCRYPT_INT piScr = SymCryptIntFromDivisor(pdTmp); |
373 | | |
374 | | // We need a 1-digit tmp value to store the GCD in. |
375 | | // Simpler to put it on the stack than to add full scratch size computation support to this function |
376 | 0 | piTmpGcd = SymCryptIntCreate( SYMCRYPT_ASYM_ALIGN_UP( tmpGcdBuf ), sizeof( tmpGcdBuf ) - SYMCRYPT_ASYM_ALIGN_VALUE, SymCryptDigitsFromBits( 64 ) ); |
377 | | |
378 | | // Run the CRT generation |
379 | 0 | scError = SymCryptCrtGenerateInverses( pkRsakey->nPrimes, pkRsakey->pmPrimes, 0, pkRsakey->peCrtInverses, pbScratch, cbScratch); |
380 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
381 | 0 | { |
382 | 0 | goto cleanup; |
383 | 0 | } |
384 | | |
385 | | // Calculate Phi |
386 | 0 | SymCryptIntSetValueUint32( 1, piPhi ); |
387 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
388 | 0 | { |
389 | | // piScr can have the different number of digits than each prime |
390 | 0 | scError = SymCryptIntCopyMixedSize( SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), piScr ); |
391 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
392 | 0 | { |
393 | 0 | goto cleanup; |
394 | 0 | } |
395 | 0 | SymCryptIntSubUint32( piScr, 1, piScr ); // p-1 |
396 | 0 | SymCryptIntMulMixedSize( piScr, piPhi, piAcc, pbScratch, cbScratch ); |
397 | 0 | scError = SymCryptIntCopyMixedSize( piAcc, piPhi ); |
398 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
399 | 0 | { |
400 | 0 | goto cleanup; |
401 | 0 | } |
402 | 0 | } |
403 | | |
404 | | // Calculate the private exponents |
405 | 0 | for (UINT32 i=0; i<pkRsakey->nPubExp; i++) |
406 | 0 | { |
407 | | // IntExtendedGcd requirements: |
408 | | // - First argument > 0: piPhi as the product of p-1's |
409 | | // - Second argument: odd, verified below |
410 | | // We also reject public exponent 1, as that is obviously unsafe. |
411 | 0 | if( pkRsakey->au64PubExp[i] == 1 || (pkRsakey->au64PubExp[i] & 1) != 1) |
412 | 0 | { |
413 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
414 | 0 | goto cleanup; |
415 | 0 | } |
416 | | |
417 | | // Calculate D |
418 | 0 | SymCryptIntSetValueUint64( pkRsakey->au64PubExp[i], piScr ); |
419 | | |
420 | | // Calculate D |
421 | 0 | SymCryptIntExtendedGcd( |
422 | 0 | piPhi, |
423 | 0 | piScr, |
424 | 0 | SYMCRYPT_FLAG_GCD_INPUTS_NOT_BOTH_EVEN, |
425 | 0 | piTmpGcd, // Gcd |
426 | 0 | NULL, // Lcm |
427 | 0 | NULL, // InvSrc1ModSrc2 |
428 | 0 | pkRsakey->piPrivExps[i], |
429 | 0 | pbScratch, |
430 | 0 | cbScratch); |
431 | |
|
432 | 0 | if( !SymCryptIntIsEqualUint32( piTmpGcd, 1 ) ) |
433 | 0 | { |
434 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
435 | 0 | goto cleanup; |
436 | 0 | } |
437 | 0 | } |
438 | | |
439 | | //Calculate the private exponents modulo each prime minus 1 |
440 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
441 | 0 | { |
442 | 0 | scError = SymCryptIntCopyMixedSize( SymCryptIntFromModulus(pkRsakey->pmPrimes[i]), SymCryptIntFromDivisor(pdTmp) ); |
443 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
444 | 0 | { |
445 | 0 | goto cleanup; |
446 | 0 | } |
447 | | |
448 | | // IntToDivisor requirement: |
449 | | // Each prime has at least SYMCRYPT_RSAKEY_MIN_BITSIZE_PRIME bits --> P-1 > 0 |
450 | 0 | SymCryptIntSubUint32( SymCryptIntFromDivisor(pdTmp), 1, SymCryptIntFromDivisor(pdTmp) ); |
451 | 0 | SymCryptIntToDivisor( |
452 | 0 | SymCryptIntFromDivisor(pdTmp), |
453 | 0 | pdTmp, |
454 | 0 | pkRsakey->nPubExp, |
455 | 0 | 0, |
456 | 0 | pbScratch, |
457 | 0 | cbScratch ); |
458 | |
|
459 | 0 | for (UINT32 j=0; j<pkRsakey->nPubExp; j++) |
460 | 0 | { |
461 | 0 | SymCryptIntDivMod( |
462 | 0 | pkRsakey->piPrivExps[j], |
463 | 0 | pdTmp, |
464 | 0 | NULL, |
465 | 0 | piPhi, // Set it to Phi as each private exponent might have different size |
466 | 0 | pbScratch, |
467 | 0 | cbScratch ); |
468 | |
|
469 | 0 | scError = SymCryptIntCopyMixedSize( piPhi, pkRsakey->piCrtPrivExps[ j*pkRsakey->nPrimes + i ]); |
470 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
471 | 0 | { |
472 | 0 | goto cleanup; |
473 | 0 | } |
474 | 0 | } |
475 | 0 | } |
476 | | |
477 | 0 | cleanup: |
478 | 0 | return scError; |
479 | 0 | } |
480 | | |
481 | | SYMCRYPT_ERROR |
482 | | SYMCRYPT_CALL |
483 | | SymCryptRsakeyGenerate( |
484 | | _Inout_ PSYMCRYPT_RSAKEY pkRsakey, |
485 | | _In_reads_opt_( nPubExp ) PCUINT64 pu64PubExp, |
486 | | UINT32 nPubExp, |
487 | | _In_ UINT32 flags ) |
488 | 0 | { |
489 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
490 | | |
491 | | // 3 sizes of temporary elements: |
492 | | // - ndPrimes = number of digit size of each prime (we choose it to be the same for all primes) |
493 | | // - ndMod = pkRsakey->nDigitsOfModulus |
494 | | // - ndLarge = ndPrimes + ndMod |
495 | |
|
496 | 0 | UINT32 ndPrimes = 0; |
497 | |
|
498 | 0 | UINT32 cbPrimes = 0; |
499 | 0 | PSYMCRYPT_INT piLow = NULL; |
500 | 0 | PSYMCRYPT_INT piHigh = NULL; |
501 | |
|
502 | 0 | UINT32 cbDivisor = 0; |
503 | 0 | PSYMCRYPT_DIVISOR pdTmp = NULL; |
504 | |
|
505 | 0 | UINT32 ndMod = pkRsakey->nDigitsOfModulus; |
506 | 0 | UINT32 cbMod = 0; |
507 | 0 | PSYMCRYPT_INT piPhi = NULL; |
508 | |
|
509 | 0 | UINT32 ndLarge = 0; |
510 | 0 | UINT32 cbLarge = 0; |
511 | 0 | PSYMCRYPT_INT piAcc = NULL; |
512 | |
|
513 | 0 | PBYTE pbScratch = NULL; |
514 | 0 | UINT32 cbScratch = 0; |
515 | 0 | PBYTE pbFnScratch = NULL; |
516 | 0 | UINT32 cbFnScratch = 0; |
517 | |
|
518 | 0 | UINT32 maxTries = 0; // For the prime generation (and the modulus operations ?) |
519 | 0 | UINT32 primeBits = 0; |
520 | |
|
521 | 0 | const UINT64 defaultExponent = RSA_DEFAULT_PUBLIC_EXPONENT; |
522 | | |
523 | | // Ensure caller has specified what algorithm(s) the key will be used with |
524 | 0 | UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT; |
525 | | // Ensure only allowed flags are specified |
526 | 0 | UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags; |
527 | |
|
528 | 0 | if ( ( ( flags & ~allowedFlags ) != 0 ) || |
529 | 0 | ( ( flags & algorithmFlags ) == 0) ) |
530 | 0 | { |
531 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
532 | 0 | goto cleanup; |
533 | 0 | } |
534 | | |
535 | | // SymCryptRsaSignVerifyPct requires the generated key to be at least 496 bits to avoid fatal |
536 | | // Require caller to specify NO_FIPS for up to 1024 bits as running FIPS tests on too-small keys |
537 | | // does not make it FIPS certifiable and gives the wrong impression to callers |
538 | 0 | if ( ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 ) && |
539 | 0 | ( pkRsakey->nSetBitsOfModulus < SYMCRYPT_RSAKEY_FIPS_MIN_BITSIZE_MODULUS ) ) |
540 | 0 | { |
541 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
542 | 0 | goto cleanup; |
543 | 0 | } |
544 | | |
545 | | // Handle the default exponent case |
546 | 0 | if( pu64PubExp == NULL && nPubExp == 0 ) |
547 | 0 | { |
548 | 0 | pu64PubExp = &defaultExponent; |
549 | 0 | nPubExp = 1; |
550 | 0 | } |
551 | | |
552 | | // Make sure we have: |
553 | | // - exactly 2 primes |
554 | | // - the right number of public exponents |
555 | | // - exactly 1 public exponent |
556 | 0 | if (pkRsakey->nPrimes != 2 || nPubExp != pkRsakey->nPubExp || nPubExp != 1 ) |
557 | 0 | { |
558 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
559 | 0 | goto cleanup; |
560 | 0 | } |
561 | | |
562 | | // Copy the public exponent into the key |
563 | 0 | pkRsakey->au64PubExp[0] = pu64PubExp[0]; |
564 | | |
565 | | // Before doing anything calculate all the needed sizes |
566 | | // The size limits were checked in SymCryptRsakeyCreate which is the only way to create an Rsakey object. |
567 | 0 | pkRsakey->nBitsOfModulus = pkRsakey->nSetBitsOfModulus; // This will be the exact bit size of our modulus |
568 | |
|
569 | 0 | pkRsakey->nBitsOfPrimes[0] = (pkRsakey->nBitsOfModulus + 1)/2; |
570 | 0 | pkRsakey->nBitsOfPrimes[1] = pkRsakey->nBitsOfModulus/2; // The second prime is one bit smaller for odd-length moduli |
571 | |
|
572 | 0 | pkRsakey->nDigitsOfPrimes[0] = SymCryptDigitsFromBits(pkRsakey->nBitsOfPrimes[0]); |
573 | 0 | pkRsakey->nDigitsOfPrimes[1] = SymCryptDigitsFromBits(pkRsakey->nBitsOfPrimes[1]); |
574 | |
|
575 | 0 | pkRsakey->nMaxDigitsOfPrimes = SYMCRYPT_MAX(pkRsakey->nDigitsOfPrimes[0], pkRsakey->nDigitsOfPrimes[1]); |
576 | |
|
577 | 0 | ndPrimes = pkRsakey->nMaxDigitsOfPrimes; |
578 | 0 | ndLarge = ndPrimes + ndMod; |
579 | |
|
580 | 0 | primeBits = SYMCRYPT_MAX(pkRsakey->nBitsOfPrimes[0],pkRsakey->nBitsOfPrimes[1]); |
581 | 0 | maxTries = 100 * primeBits; |
582 | | |
583 | | // Create all the SymCryptObjects |
584 | 0 | SymCryptRsakeyCreateAllObjects( pkRsakey ); |
585 | | |
586 | | // Allocate the temp integers and the scratch space |
587 | | // All sizes are limited by the modulus sizes verified in SymCryptRsakeyCreate |
588 | 0 | cbPrimes = SymCryptSizeofIntFromDigits( ndPrimes ); |
589 | 0 | cbMod = SymCryptSizeofIntFromDigits( ndMod ); |
590 | 0 | cbLarge = SymCryptSizeofIntFromDigits( ndLarge ); |
591 | 0 | cbDivisor = SymCryptSizeofDivisorFromDigits( ndPrimes ); |
592 | |
|
593 | 0 | cbScratch = 2*cbPrimes + cbMod + cbLarge + cbDivisor + |
594 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_PRIME_GEN(ndPrimes), |
595 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(ndMod), |
596 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_MUL(ndMod), |
597 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_CRT_GENERATION(ndPrimes), |
598 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_EXTENDED_GCD(ndMod), |
599 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR(ndPrimes), |
600 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( ndMod, ndPrimes ) |
601 | 0 | )))))); |
602 | |
|
603 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
604 | 0 | if (pbScratch == NULL) |
605 | 0 | { |
606 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
607 | 0 | goto cleanup; |
608 | 0 | } |
609 | | |
610 | 0 | pbFnScratch = pbScratch; |
611 | 0 | cbFnScratch = cbScratch; |
612 | | |
613 | | // Create temporaries |
614 | | // dcl - this would be easier to review with one statement per line |
615 | 0 | piLow = SymCryptIntCreate( pbFnScratch, cbPrimes, ndPrimes ); pbFnScratch += cbPrimes; cbFnScratch -= cbPrimes; |
616 | 0 | piHigh = SymCryptIntCreate( pbFnScratch, cbPrimes, ndPrimes ); pbFnScratch += cbPrimes; cbFnScratch -= cbPrimes; |
617 | |
|
618 | 0 | piPhi = SymCryptIntCreate( pbFnScratch, cbMod, ndMod ); pbFnScratch += cbMod; cbFnScratch -= cbMod; |
619 | |
|
620 | 0 | piAcc = SymCryptIntCreate( pbFnScratch, cbLarge, ndLarge ); pbFnScratch += cbLarge; cbFnScratch -= cbLarge; |
621 | |
|
622 | 0 | pdTmp = SymCryptDivisorCreate( pbFnScratch, cbDivisor, ndPrimes ); pbFnScratch += cbDivisor; cbFnScratch -= cbDivisor; |
623 | | |
624 | | // ***Prime generation limits*** |
625 | | // |
626 | | // If nBitsOfModulus is even (main case) |
627 | | // Low limit = 2^{primeBits-1} + 2^{primeBits - 2} |
628 | | // High limit = 2^primeBits - 1 |
629 | | // |
630 | | // If nBitsOfModulus is odd we use different |
631 | | // limits for the two primes (until we have an integer sqrt function) |
632 | | // |
633 | | // For the first |
634 | | // Low limit = 2^{primeBits-1} + 2^{primeBits - 2} |
635 | | // High limit = 2^primeBits - 1 |
636 | | // For the second |
637 | | // Low limit = 2^{primeBits-2} + 2^{primeBits - 3} |
638 | | // High limit = 2^{primeBits-1} - 1 |
639 | | // |
640 | | // Notice that nBitsOfModulus is a public value. |
641 | | // |
642 | | // *** TODO: This works only for 2 primes to give modulus |
643 | | // of exactly nBitsOfModulus bits. |
644 | |
|
645 | 0 | SymCryptIntSetValueUint32( 3, piLow ); |
646 | 0 | SymCryptIntMulPow2( piLow, primeBits - 2, piLow ); |
647 | |
|
648 | 0 | SymCryptIntSetValueUint32( 1, piHigh ); |
649 | 0 | SymCryptIntMulPow2( piHigh, primeBits, piHigh ); |
650 | 0 | SymCryptIntSubUint32( piHigh, 1, piHigh ); |
651 | | |
652 | | // Generate primes and at the same time accumulate their product into piPhi |
653 | 0 | SymCryptIntSetValueUint32( 1, piPhi ); |
654 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
655 | 0 | { |
656 | 0 | if ( ((pkRsakey->nBitsOfModulus % 2)==1) && (i>0) ) |
657 | 0 | { |
658 | 0 | SymCryptIntDivPow2( piLow, 1, piLow ); |
659 | 0 | SymCryptIntDivPow2( piHigh, 1, piHigh ); |
660 | 0 | } |
661 | | |
662 | | // IntGenerateRandomPrime requirement: |
663 | | // piLow > 3 since nBitsOfModulus is bounded by |
664 | | // SYMCRYPT_RSAKEY_MIN_BITSIZE_MODULUS. |
665 | 0 | scError = SymCryptIntGenerateRandomPrime( |
666 | 0 | piLow, |
667 | 0 | piHigh, |
668 | 0 | pu64PubExp, |
669 | 0 | nPubExp, |
670 | 0 | maxTries, |
671 | 0 | 0, |
672 | 0 | SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), |
673 | 0 | pbFnScratch, |
674 | 0 | cbFnScratch); |
675 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
676 | 0 | { |
677 | 0 | goto cleanup; |
678 | 0 | } |
679 | | |
680 | | // IntToModulus requirement: |
681 | | // piLow > 0 --> pkRsakey->pmPrimes[i] > 0 |
682 | 0 | SymCryptIntToModulus( |
683 | 0 | SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), |
684 | 0 | pkRsakey->pmPrimes[i], |
685 | 0 | pkRsakey->nBitsOfModulus, // Average number of operations |
686 | 0 | SYMCRYPT_FLAG_MODULUS_PARITY_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME, |
687 | 0 | pbFnScratch, |
688 | 0 | cbFnScratch ); |
689 | |
|
690 | 0 | SymCryptIntMulMixedSize( SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), piPhi, piAcc, pbFnScratch, cbFnScratch ); // P_i * Product |
691 | 0 | scError = SymCryptIntCopyMixedSize( piAcc, piPhi ); // Move the result to piPhi |
692 | 0 | if (scError!=SYMCRYPT_NO_ERROR) |
693 | 0 | { |
694 | 0 | goto cleanup; |
695 | 0 | } |
696 | 0 | } |
697 | | |
698 | | // IntToModulus requirement: |
699 | | // piPhi product of non-zero primes --> piPhi > 0 |
700 | 0 | SymCryptIntCopy( piPhi, SymCryptIntFromModulus( pkRsakey->pmModulus ) ); |
701 | 0 | SymCryptIntToModulus( |
702 | 0 | SymCryptIntFromModulus( pkRsakey->pmModulus ), |
703 | 0 | pkRsakey->pmModulus, |
704 | 0 | pkRsakey->nBitsOfModulus, // Average number of operations |
705 | 0 | SYMCRYPT_FLAG_DATA_PUBLIC, |
706 | 0 | pbFnScratch, |
707 | 0 | cbFnScratch ); |
708 | |
|
709 | 0 | if ( SymCryptIntBitsizeOfValue( piPhi ) != pkRsakey->nBitsOfModulus) |
710 | 0 | { |
711 | 0 | scError = SYMCRYPT_EXTERNAL_FAILURE; // This should never happen (make it assert) |
712 | 0 | goto cleanup; |
713 | 0 | } |
714 | | |
715 | | // Calculate the rest of the fields |
716 | 0 | scError = SymCryptRsakeyCalculatePrivateFields( pkRsakey, pdTmp, piPhi, piAcc, pbFnScratch, cbFnScratch ); |
717 | 0 | if ( scError != SYMCRYPT_NO_ERROR ) |
718 | 0 | { |
719 | 0 | goto cleanup; |
720 | 0 | } |
721 | | |
722 | 0 | pkRsakey->hasPrivateKey = TRUE; |
723 | |
|
724 | 0 | pkRsakey->fAlgorithmInfo = flags; // We want to track all of the flags in the Rsakey |
725 | |
|
726 | 0 | if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) |
727 | 0 | { |
728 | | // Ensure RSA algorithm selftest is run before first use of RSA algorithm |
729 | | // Per FIPS 140-3 IG, this selftest cannot be a PCT |
730 | 0 | SYMCRYPT_RUN_SELFTEST_ONCE( |
731 | 0 | SymCryptRsaSelftest, |
732 | 0 | SYMCRYPT_SELFTEST_ALGORITHM_RSA); |
733 | | |
734 | | // Run SignVerify PCT on generated keypair |
735 | | // Our current understanding is that this PCT is sufficient for both RSA_SIGN and RSA_ENCRYPT |
736 | | |
737 | | // Unconditionally set the sign flag to enable SignVerify PCT on encrypt-only keypair |
738 | 0 | pkRsakey->fAlgorithmInfo |= SYMCRYPT_FLAG_RSAKEY_SIGN; |
739 | |
|
740 | 0 | SYMCRYPT_RUN_KEY_PCT( |
741 | 0 | SymCryptRsaSignVerifyPct, |
742 | 0 | pkRsakey, |
743 | 0 | SYMCRYPT_PCT_RSA_SIGN ); |
744 | | |
745 | | // Unset the sign flag before returning encrypt-only keypair |
746 | 0 | if ( ( flags & SYMCRYPT_FLAG_RSAKEY_SIGN ) == 0 ) |
747 | 0 | { |
748 | 0 | pkRsakey->fAlgorithmInfo ^= SYMCRYPT_FLAG_RSAKEY_SIGN; |
749 | 0 | } |
750 | 0 | } |
751 | |
|
752 | 0 | cleanup: |
753 | 0 | if (pbScratch!=NULL) |
754 | 0 | { |
755 | 0 | SymCryptWipe(pbScratch,cbScratch); |
756 | 0 | SymCryptCallbackFree(pbScratch); |
757 | 0 | } |
758 | |
|
759 | 0 | return scError; |
760 | 0 | } |
761 | | |
762 | | SYMCRYPT_ERROR |
763 | | SYMCRYPT_CALL |
764 | | SymCryptRsakeySetValue( |
765 | | _In_reads_bytes_( cbModulus ) PCBYTE pbModulus, |
766 | | SIZE_T cbModulus, |
767 | | _In_reads_( nPubExp ) PCUINT64 pu64PubExp, |
768 | | UINT32 nPubExp, |
769 | | _In_reads_( nPrimes ) PCBYTE * ppPrimes, |
770 | | _In_reads_( nPrimes ) SIZE_T * pcbPrimes, |
771 | | UINT32 nPrimes, |
772 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
773 | | UINT32 flags, |
774 | | _Out_ PSYMCRYPT_RSAKEY pkRsakey ) |
775 | 0 | { |
776 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
777 | | |
778 | | // 3 sizes of temporary elements: |
779 | | // - ndPrimes = max digitsize of prime buffers |
780 | | // - ndMod = pkRsakey->nDigitsOfModulus |
781 | | // - ndLarge = ndPrimes + ndMod |
782 | |
|
783 | 0 | UINT32 cbDivisor = 0; |
784 | 0 | PSYMCRYPT_DIVISOR pdTmp = NULL; |
785 | |
|
786 | 0 | UINT32 ndMod = 0; |
787 | 0 | UINT32 cbMod = 0; |
788 | 0 | PSYMCRYPT_INT piPhi = NULL; |
789 | |
|
790 | 0 | UINT32 cbLarge = 0; |
791 | 0 | PSYMCRYPT_INT piAcc = NULL; |
792 | |
|
793 | 0 | PBYTE pbScratch = NULL; |
794 | 0 | UINT32 cbScratch = 0; |
795 | 0 | PBYTE pbFnScratch = NULL; |
796 | 0 | UINT32 cbFnScratch = 0; |
797 | | |
798 | | // Ensure caller has specified what algorithm(s) the key will be used with |
799 | 0 | UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT; |
800 | | // Ensure only allowed flags are specified |
801 | 0 | UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION | algorithmFlags; |
802 | |
|
803 | 0 | if ( ( ( flags & ~allowedFlags ) != 0 ) || |
804 | 0 | ( ( flags & algorithmFlags ) == 0) ) |
805 | 0 | { |
806 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
807 | 0 | goto cleanup; |
808 | 0 | } |
809 | | |
810 | | // Check that minimal validation flag only specified with no fips |
811 | 0 | if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) && |
812 | 0 | ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) != 0 ) ) |
813 | 0 | { |
814 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
815 | 0 | goto cleanup; |
816 | 0 | } |
817 | | |
818 | | // Check if the arguments are correct |
819 | 0 | if ( (pbModulus==NULL) || (cbModulus==0) || // Modulus is needed |
820 | 0 | (nPubExp != 1) || (pu64PubExp==NULL) || // Exactly 1 public exponent is needed |
821 | 0 | ((nPrimes != 2) && (nPrimes!=0)) || |
822 | 0 | ((nPrimes == 2) && ((ppPrimes==NULL) || (pcbPrimes==NULL) || |
823 | 0 | (ppPrimes[0]==NULL) || (ppPrimes[1]==NULL) || |
824 | 0 | (pcbPrimes[0]==0) || (pcbPrimes[1]==0))) ) |
825 | 0 | { |
826 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
827 | 0 | goto cleanup; |
828 | 0 | } |
829 | | |
830 | 0 | ndMod = pkRsakey->nDigitsOfModulus; |
831 | | |
832 | | // Calculate scratch spaces |
833 | | // No integer overflows as all numbers are limited by ndMod which is checked during Create |
834 | 0 | if( nPrimes!=0 ) |
835 | 0 | { |
836 | 0 | cbMod = SymCryptSizeofIntFromDigits( ndMod ); |
837 | 0 | cbLarge = SymCryptSizeofIntFromDigits( 2 * ndMod ); // 2*ndMod is still < SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS) |
838 | 0 | cbDivisor = SymCryptSizeofDivisorFromDigits( ndMod ); |
839 | |
|
840 | 0 | cbScratch = cbMod + cbLarge + cbDivisor + |
841 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(ndMod), |
842 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_CRT_GENERATION(ndMod), |
843 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_EXTENDED_GCD(ndMod), |
844 | 0 | SYMCRYPT_MAX( SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_DIVISOR(ndMod), |
845 | 0 | SYMCRYPT_SCRATCH_BYTES_FOR_INT_DIVMOD( ndMod, ndMod ) |
846 | 0 | )))); |
847 | 0 | } |
848 | 0 | else |
849 | 0 | { |
850 | 0 | cbScratch = SYMCRYPT_SCRATCH_BYTES_FOR_INT_TO_MODULUS(ndMod); |
851 | 0 | } |
852 | |
|
853 | 0 | pbScratch = (PBYTE)SymCryptCallbackAlloc( cbScratch ); |
854 | 0 | if (pbScratch == NULL) |
855 | 0 | { |
856 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
857 | 0 | goto cleanup; |
858 | 0 | } |
859 | | |
860 | | // Modulus |
861 | 0 | scError = SymCryptIntSetValue( pbModulus, cbModulus, numFormat, SymCryptIntFromModulus( pkRsakey->pmModulus ) ); |
862 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
863 | 0 | { |
864 | 0 | goto cleanup; |
865 | 0 | } |
866 | | |
867 | | // Compute actual modulus size, and check that it isn't bigger than the created size |
868 | 0 | pkRsakey->nBitsOfModulus = SymCryptIntBitsizeOfValue(SymCryptIntFromModulus(pkRsakey->pmModulus)); |
869 | 0 | if (pkRsakey->nBitsOfModulus > pkRsakey->nSetBitsOfModulus) |
870 | 0 | { |
871 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
872 | 0 | goto cleanup; |
873 | 0 | } |
874 | | |
875 | 0 | if (pkRsakey->nBitsOfModulus < SYMCRYPT_RSAKEY_MIN_BITSIZE_MODULUS) |
876 | 0 | { |
877 | 0 | scError = SYMCRYPT_WRONG_KEY_SIZE; |
878 | 0 | goto cleanup; |
879 | 0 | } |
880 | | |
881 | | // IntToModulus requirement: |
882 | | // nBitsOfModulus >= SYMCRYPT_RSAKEY_MIN_BITSIZE_MODULUS --> pmModulus > 0 |
883 | 0 | SymCryptIntToModulus( |
884 | 0 | SymCryptIntFromModulus( pkRsakey->pmModulus ), |
885 | 0 | pkRsakey->pmModulus, |
886 | 0 | pkRsakey->nBitsOfModulus, |
887 | 0 | SYMCRYPT_FLAG_DATA_PUBLIC, |
888 | 0 | pbScratch, |
889 | 0 | cbScratch ); |
890 | | |
891 | | // Public exponents |
892 | 0 | pkRsakey->nPubExp = nPubExp; |
893 | 0 | for (UINT32 i = 0; i<pkRsakey->nPubExp; i++) |
894 | 0 | { |
895 | 0 | pkRsakey->au64PubExp[i] = pu64PubExp[i]; |
896 | 0 | } |
897 | | |
898 | | // Primes i.e. private key |
899 | 0 | if (nPrimes > 0) |
900 | 0 | { |
901 | 0 | pbFnScratch = pbScratch; |
902 | 0 | cbFnScratch = cbScratch; |
903 | | |
904 | | // Create temporaries |
905 | 0 | piPhi = SymCryptIntCreate( pbFnScratch, cbMod, ndMod ); pbFnScratch += cbMod; cbFnScratch -= cbMod; |
906 | 0 | piAcc = SymCryptIntCreate( pbFnScratch, cbLarge, 2 * ndMod ); pbFnScratch += cbLarge; cbFnScratch -= cbLarge; |
907 | 0 | pdTmp = SymCryptDivisorCreate( pbFnScratch, cbDivisor, ndMod ); pbFnScratch += cbDivisor; cbFnScratch -= cbDivisor; |
908 | |
|
909 | 0 | pkRsakey->nPrimes = nPrimes; |
910 | | |
911 | | // First fix the tight number of digits of each prime |
912 | 0 | pkRsakey->nMaxDigitsOfPrimes = 0; |
913 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
914 | 0 | { |
915 | 0 | #pragma warning(suppress: 26007) // "Incorrect Annotation" - cannot phrase array of pointers to arrays in SAL |
916 | 0 | scError = SymCryptIntSetValue( ppPrimes[i], pcbPrimes[i], numFormat, piPhi ); |
917 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
918 | 0 | { |
919 | 0 | goto cleanup; |
920 | 0 | } |
921 | | |
922 | 0 | pkRsakey->nBitsOfPrimes[i] = SymCryptIntBitsizeOfValue(piPhi); |
923 | 0 | pkRsakey->nDigitsOfPrimes[i] = SymCryptDigitsFromBits(pkRsakey->nBitsOfPrimes[i]); |
924 | |
|
925 | 0 | pkRsakey->nMaxDigitsOfPrimes = SYMCRYPT_MAX(pkRsakey->nMaxDigitsOfPrimes, pkRsakey->nDigitsOfPrimes[i]); |
926 | |
|
927 | 0 | if (pkRsakey->nBitsOfPrimes[i] < SYMCRYPT_RSAKEY_MIN_BITSIZE_PRIME) |
928 | 0 | { |
929 | 0 | scError = SYMCRYPT_WRONG_KEY_SIZE; |
930 | 0 | goto cleanup; |
931 | 0 | } |
932 | 0 | } |
933 | | |
934 | | // Create all the objects |
935 | 0 | SymCryptRsakeyCreateAllObjects(pkRsakey); |
936 | | |
937 | | // Set the values |
938 | 0 | for (UINT32 i=0; i<pkRsakey->nPrimes; i++) |
939 | 0 | { |
940 | 0 | #pragma warning(suppress: 26007) // "Incorrect Annotation" - cannot phrase array of pointers to arrays in SAL |
941 | 0 | scError = SymCryptIntSetValue( ppPrimes[i], pcbPrimes[i], numFormat, SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ) ); |
942 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
943 | 0 | { |
944 | 0 | goto cleanup; |
945 | 0 | } |
946 | | |
947 | | // Check that this prime is odd (should we check for primality?) |
948 | 0 | if ((SymCryptIntGetValueLsbits32(SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ))& 1)==0) |
949 | 0 | { |
950 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
951 | 0 | goto cleanup; |
952 | 0 | } |
953 | | |
954 | | // IntToModulus requirement: |
955 | | // nBitsOfPrimes >= SYMCRYPT_RSAKEY_MIN_BITSIZE_PRIME --> pmPrimes[i] > 0 |
956 | 0 | SymCryptIntToModulus( |
957 | 0 | SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), |
958 | 0 | pkRsakey->pmPrimes[i], |
959 | 0 | pkRsakey->nBitsOfModulus, // Average number of operations |
960 | 0 | SYMCRYPT_FLAG_MODULUS_PARITY_PUBLIC | SYMCRYPT_FLAG_MODULUS_PRIME, |
961 | 0 | pbFnScratch, |
962 | 0 | cbFnScratch ); |
963 | 0 | } |
964 | | |
965 | | // Calculate the rest of the fields |
966 | 0 | scError = SymCryptRsakeyCalculatePrivateFields( pkRsakey, pdTmp, piPhi, piAcc, pbFnScratch, cbFnScratch ); |
967 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
968 | 0 | { |
969 | 0 | goto cleanup; |
970 | 0 | } |
971 | | |
972 | | // Everything is set here |
973 | 0 | pkRsakey->hasPrivateKey = TRUE; |
974 | 0 | } |
975 | | |
976 | 0 | pkRsakey->fAlgorithmInfo = flags; // We want to track all of the flags in the Rsakey |
977 | |
|
978 | 0 | if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) |
979 | 0 | { |
980 | | // Ensure RSA algorithm selftest is run before first use of RSA algorithm |
981 | 0 | SYMCRYPT_RUN_SELFTEST_ONCE( |
982 | 0 | SymCryptRsaSelftest, |
983 | 0 | SYMCRYPT_SELFTEST_ALGORITHM_RSA); |
984 | |
|
985 | 0 | if( pkRsakey->hasPrivateKey ) |
986 | 0 | { |
987 | | // Unconditionally set the sign flag to enable SignVerify PCT on encrypt-only keypair |
988 | 0 | pkRsakey->fAlgorithmInfo |= SYMCRYPT_FLAG_RSAKEY_SIGN; |
989 | |
|
990 | 0 | SYMCRYPT_RUN_KEY_PCT( |
991 | 0 | SymCryptRsaSignVerifyPct, |
992 | 0 | pkRsakey, |
993 | 0 | SYMCRYPT_PCT_RSA_SIGN ); |
994 | | |
995 | | // Unset the sign flag before returning encrypt-only keypair |
996 | 0 | if ( ( flags & SYMCRYPT_FLAG_RSAKEY_SIGN ) == 0 ) |
997 | 0 | { |
998 | 0 | pkRsakey->fAlgorithmInfo ^= SYMCRYPT_FLAG_RSAKEY_SIGN; |
999 | 0 | } |
1000 | 0 | } |
1001 | 0 | } |
1002 | |
|
1003 | 0 | cleanup: |
1004 | 0 | if (pbScratch!=NULL) |
1005 | 0 | { |
1006 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1007 | 0 | SymCryptCallbackFree(pbScratch); |
1008 | 0 | } |
1009 | |
|
1010 | 0 | return scError; |
1011 | 0 | } |
1012 | | |
1013 | | SYMCRYPT_ERROR |
1014 | | SYMCRYPT_CALL |
1015 | | SymCryptRsakeyGetValue( |
1016 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1017 | | _Out_writes_bytes_( cbModulus ) PBYTE pbModulus, |
1018 | | SIZE_T cbModulus, |
1019 | | _Out_writes_opt_( nPubExp ) PUINT64 pu64PubExp, |
1020 | | UINT32 nPubExp, |
1021 | | _Out_writes_opt_( nPrimes ) PBYTE * ppPrimes, |
1022 | | _In_reads_opt_( nPrimes ) SIZE_T * pcbPrimes, |
1023 | | UINT32 nPrimes, |
1024 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
1025 | | UINT32 flags ) |
1026 | 0 | { |
1027 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1028 | |
|
1029 | 0 | UNREFERENCED_PARAMETER( flags ); |
1030 | | |
1031 | | // Check if private key needed but not there |
1032 | 0 | if ((nPrimes!=0) && (pkRsakey->hasPrivateKey == FALSE)) |
1033 | 0 | { |
1034 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1035 | 0 | goto cleanup; |
1036 | 0 | } |
1037 | | |
1038 | | // Modulus |
1039 | 0 | if (pbModulus!=NULL) |
1040 | 0 | { |
1041 | | // We'll get an error if cbModulus is 0 or too small |
1042 | 0 | scError = SymCryptIntGetValue( SymCryptIntFromModulus( pkRsakey->pmModulus ), pbModulus, cbModulus, numFormat ); |
1043 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
1044 | 0 | { |
1045 | 0 | goto cleanup; |
1046 | 0 | } |
1047 | 0 | } |
1048 | | |
1049 | | // Public exponents |
1050 | 0 | if( pu64PubExp != NULL ) |
1051 | 0 | { |
1052 | 0 | if( nPubExp != 1 ) |
1053 | 0 | { |
1054 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1055 | 0 | goto cleanup; |
1056 | 0 | } |
1057 | 0 | pu64PubExp[0] = pkRsakey->au64PubExp[0]; |
1058 | 0 | } |
1059 | | |
1060 | | // Primes i.e. private key |
1061 | 0 | if( nPrimes != 0 ) |
1062 | 0 | { |
1063 | 0 | if( nPrimes != 2 || ppPrimes == NULL || pcbPrimes == NULL ) |
1064 | 0 | { |
1065 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1066 | 0 | goto cleanup; |
1067 | 0 | } |
1068 | | |
1069 | 0 | for (UINT32 i=0; i<nPrimes; i++) |
1070 | 0 | { |
1071 | 0 | if (ppPrimes[i]!=NULL) |
1072 | 0 | { |
1073 | 0 | scError = SymCryptIntGetValue( SymCryptIntFromModulus( pkRsakey->pmPrimes[i] ), ppPrimes[i], pcbPrimes[i], numFormat ); |
1074 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
1075 | 0 | { |
1076 | 0 | goto cleanup; |
1077 | 0 | } |
1078 | 0 | } |
1079 | 0 | } |
1080 | 0 | } |
1081 | | |
1082 | 0 | cleanup: |
1083 | 0 | return scError; |
1084 | 0 | } |
1085 | | |
1086 | | SYMCRYPT_ERROR |
1087 | | SYMCRYPT_CALL |
1088 | | SymCryptRsakeyGetCrtValue( |
1089 | | _In_ PCSYMCRYPT_RSAKEY pkRsakey, |
1090 | | _Out_writes_(nCrtExponents) PBYTE * ppCrtExponents, |
1091 | | _In_reads_(nCrtExponents) SIZE_T * pcbCrtExponents, |
1092 | | UINT32 nCrtExponents, |
1093 | | _Out_writes_bytes_(cbCrtCoefficient) PBYTE pbCrtCoefficient, |
1094 | | SIZE_T cbCrtCoefficient, |
1095 | | _Out_writes_bytes_(cbPrivateExponent) PBYTE pbPrivateExponent, |
1096 | | SIZE_T cbPrivateExponent, |
1097 | | SYMCRYPT_NUMBER_FORMAT numFormat, |
1098 | | UINT32 flags) |
1099 | 0 | { |
1100 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1101 | 0 | PBYTE pbScratch = NULL; |
1102 | 0 | SIZE_T cbScratch = 0; |
1103 | |
|
1104 | 0 | UNREFERENCED_PARAMETER( flags ); |
1105 | | |
1106 | | // Check if the arguments are correct |
1107 | 0 | if ( (ppCrtExponents==NULL) && (nCrtExponents!=0) || |
1108 | 0 | (nCrtExponents != 0 && nCrtExponents != 2 )) |
1109 | 0 | { |
1110 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1111 | 0 | goto cleanup; |
1112 | 0 | } |
1113 | | |
1114 | | // Crt value can only be available we have private key. |
1115 | 0 | if (pkRsakey->hasPrivateKey == FALSE) |
1116 | 0 | { |
1117 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1118 | 0 | goto cleanup; |
1119 | 0 | } |
1120 | | |
1121 | | // Crt exponents |
1122 | 0 | for (UINT32 i=0; i<nCrtExponents; i++) |
1123 | 0 | { |
1124 | 0 | if (ppCrtExponents[i]!=NULL) |
1125 | 0 | { |
1126 | 0 | scError = SymCryptIntGetValue( pkRsakey->piCrtPrivExps[i], ppCrtExponents[i], pcbCrtExponents[i], numFormat ); |
1127 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
1128 | 0 | { |
1129 | 0 | goto cleanup; |
1130 | 0 | } |
1131 | 0 | } |
1132 | 0 | } |
1133 | | |
1134 | 0 | if (pbCrtCoefficient!=NULL) |
1135 | 0 | { |
1136 | 0 | cbScratch = SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( pkRsakey->nDigitsOfModulus ); |
1137 | 0 | pbScratch = SymCryptCallbackAlloc( cbScratch ); |
1138 | |
|
1139 | 0 | if (pbScratch==NULL) |
1140 | 0 | { |
1141 | 0 | scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE; |
1142 | 0 | goto cleanup; |
1143 | 0 | } |
1144 | | |
1145 | 0 | scError = SymCryptModElementGetValue( |
1146 | 0 | pkRsakey->pmPrimes[0], |
1147 | 0 | pkRsakey->peCrtInverses[0], |
1148 | 0 | pbCrtCoefficient, |
1149 | 0 | cbCrtCoefficient, |
1150 | 0 | numFormat, |
1151 | 0 | pbScratch, |
1152 | 0 | cbScratch); |
1153 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
1154 | 0 | { |
1155 | 0 | goto cleanup; |
1156 | 0 | } |
1157 | 0 | } |
1158 | | |
1159 | 0 | if (pbPrivateExponent!=NULL) |
1160 | 0 | { |
1161 | 0 | scError = SymCryptIntGetValue( pkRsakey->piPrivExps[0], pbPrivateExponent, cbPrivateExponent, numFormat ); |
1162 | 0 | if (scError != SYMCRYPT_NO_ERROR ) |
1163 | 0 | { |
1164 | 0 | goto cleanup; |
1165 | 0 | } |
1166 | 0 | } |
1167 | | |
1168 | 0 | cleanup: |
1169 | |
|
1170 | 0 | if (pbScratch!=NULL) |
1171 | 0 | { |
1172 | 0 | SymCryptWipe(pbScratch,cbScratch); |
1173 | 0 | SymCryptCallbackFree(pbScratch); |
1174 | 0 | } |
1175 | |
|
1176 | 0 | return scError; |
1177 | 0 | } |
1178 | | |
1179 | | SYMCRYPT_ERROR |
1180 | | SYMCRYPT_CALL |
1181 | | SymCryptRsakeyExtendKeyUsage( |
1182 | | _Inout_ PSYMCRYPT_RSAKEY pkRsakey, |
1183 | | UINT32 flags ) |
1184 | 0 | { |
1185 | 0 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
1186 | | |
1187 | | // Ensure caller has specified what algorithm(s) the key will be used with |
1188 | 0 | UINT32 algorithmFlags = SYMCRYPT_FLAG_RSAKEY_SIGN | SYMCRYPT_FLAG_RSAKEY_ENCRYPT; |
1189 | |
|
1190 | 0 | if ( ( ( flags & ~algorithmFlags ) != 0 ) || |
1191 | 0 | ( ( flags & algorithmFlags ) == 0) ) |
1192 | 0 | { |
1193 | 0 | scError = SYMCRYPT_INVALID_ARGUMENT; |
1194 | 0 | goto cleanup; |
1195 | 0 | } |
1196 | | |
1197 | 0 | pkRsakey->fAlgorithmInfo |= flags; |
1198 | |
|
1199 | 0 | cleanup: |
1200 | 0 | return scError; |
1201 | 0 | } |