Coverage Report

Created: 2024-11-21 07:03

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