Coverage Report

Created: 2024-11-21 07:03

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