Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/rsa_padding.c
Line
Count
Source (jump to first uncovered line)
1
//
2
// rsa_padding.c   RSA padding algorithms
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
7
#include "precomp.h"
8
9
0
#define ASN1_SEQUENCE_BYTE      (0x30)
10
0
#define ASN1_OCTET_STRING_BYTE  (0x04)
11
12
#define PKCS_BLOCKTYPE_1        (0x01)      // This is not used, added here for completeness
13
0
#define PKCS_BLOCKTYPE_2        (0x02)
14
15
//
16
// Note: we could optimize these OID lists by using the same byte sequence for
17
// the long and short versions.
18
//
19
const SYMCRYPT_OID SymCryptMd5OidList[] =
20
{
21
    {12, (BYTE *)"\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00"},
22
    {10, (BYTE *)"\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05"},
23
};
24
25
const SYMCRYPT_OID SymCryptSha1OidList[] =
26
{
27
    {9, (BYTE *)"\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00"},
28
    {7, (BYTE *)"\x06\x05\x2b\x0e\x03\x02\x1a"}
29
};
30
31
const SYMCRYPT_OID SymCryptSha256OidList[] =
32
{
33
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00"},
34
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01"}
35
};
36
37
const SYMCRYPT_OID SymCryptSha384OidList[] =
38
{
39
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00"},
40
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02"}
41
};
42
43
const SYMCRYPT_OID SymCryptSha512OidList[] =
44
{
45
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00"},
46
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03"}
47
};
48
49
const SYMCRYPT_OID SymCryptSha3_256OidList[] =
50
{
51
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08\x05\x00"},
52
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08"}
53
};
54
55
const SYMCRYPT_OID SymCryptSha3_384OidList[] =
56
{
57
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09\x05\x00"},
58
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09"}
59
};
60
61
const SYMCRYPT_OID SymCryptSha3_512OidList[] =
62
{
63
    {13, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0a\x05\x00"},
64
    {11, (BYTE *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0a"}
65
};
66
67
68
VOID
69
SYMCRYPT_CALL
70
SymCryptRsaPaddingMaskGeneration(
71
    _In_                        PCSYMCRYPT_HASH             hashAlgorithm,
72
    _In_                        PVOID                       pHashState,
73
    _In_reads_bytes_( cbSrc )   PCBYTE                      pbSrc,
74
                                SIZE_T                      cbSrc,
75
    _Out_writes_bytes_( cbDst ) PBYTE                       pbDst,
76
                                SIZE_T                      cbDst )
77
0
{
78
0
    SIZE_T              cIterations = 0;
79
80
0
    BYTE                rgbHash[SYMCRYPT_HASH_MAX_RESULT_SIZE] = { 0 };
81
0
    BYTE                rgbCount[sizeof(UINT32)] = { 0 };
82
0
    PBYTE               pbCount = NULL;
83
0
    SIZE_T              cbMaskRemaining = cbDst;
84
0
    PBYTE               pbMaskIndex = pbDst;
85
86
0
    BOOLEAN             fAvoidDWORDReverse = FALSE;
87
88
0
    SIZE_T              cbHashAlg = SymCryptHashResultSize( hashAlgorithm );
89
90
0
    cIterations = (cbDst + (cbHashAlg - 1)) / cbHashAlg;
91
0
    if (cIterations < 256)
92
0
    {
93
0
        fAvoidDWORDReverse = TRUE;
94
0
    }
95
96
0
    for (UINT32 i = 0; i < cIterations; i++)
97
0
    {
98
0
        SymCryptHashInit( hashAlgorithm, pHashState );
99
100
        // hash the seed
101
0
        SymCryptHashAppend( hashAlgorithm, pHashState, pbSrc, cbSrc );
102
103
        // Reverse the count bytes
104
0
        pbCount = (BYTE*)&i;
105
0
        if (fAvoidDWORDReverse)
106
0
        {
107
0
            rgbCount[3] = pbCount[0];
108
0
        }
109
0
        else
110
0
        {
111
0
            for (UINT32 j = 0; j < sizeof(UINT32); j++)
112
0
            {
113
0
                rgbCount[j] = pbCount[sizeof(UINT32) - j - 1];
114
0
            }
115
0
        }
116
117
        // hash the count
118
0
        SymCryptHashAppend( hashAlgorithm, pHashState, rgbCount, sizeof(UINT32) );
119
120
        // copy the bytes from this hash into the mask buffer
121
0
        if (cbMaskRemaining >= cbHashAlg)
122
0
        {
123
0
            SymCryptHashResult( hashAlgorithm, pHashState, pbMaskIndex, cbHashAlg );
124
125
0
            cbMaskRemaining -= cbHashAlg;
126
0
            pbMaskIndex += cbHashAlg;
127
0
        }
128
0
        else
129
0
        {
130
0
            SymCryptHashResult( hashAlgorithm, pHashState, rgbHash, cbHashAlg );
131
132
0
            memcpy( pbMaskIndex, rgbHash, cbMaskRemaining);
133
0
            break;
134
0
        }
135
0
    }
136
0
}
137
138
//
139
// PKCS1 Encryption Format:
140
//      0x00 || 0x02 || PS || 0x00 || M
141
//
142
//
143
SYMCRYPT_ERROR
144
SYMCRYPT_CALL
145
SymCryptRsaPkcs1ApplyEncryptionPadding(
146
    _In_reads_bytes_( cbPlaintext )     PCBYTE      pbPlaintext,
147
                                        SIZE_T      cbPlaintext,
148
    _Out_writes_bytes_( cbPkcs1Format ) PBYTE       pbPkcs1Format,
149
                                        SIZE_T      cbPkcs1Format )
150
0
{
151
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
152
153
    // Format: 00 02 <PS> 00 <M>
154
    // <PS> 8 or more padding bytes, random, all nonzero
155
    // <M> message, length between 0 and cbPKCS1Format - 11.
156
    // See RFC 3447 for more details.
157
158
0
    SIZE_T cbPS;
159
0
    SIZE_T i;
160
161
    // ensure output buffer is big enough (padding has 11 bytes overhead)
162
0
    if( cbPkcs1Format < (cbPlaintext + 11) )
163
0
    {
164
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
165
0
        goto cleanup;
166
0
    }
167
168
0
    cbPS = cbPkcs1Format - (cbPlaintext + 3);
169
170
0
    pbPkcs1Format[0] = 0x00;
171
0
    pbPkcs1Format[1] = PKCS_BLOCKTYPE_2;
172
173
0
    scError = SymCryptCallbackRandom( &pbPkcs1Format[2], cbPS );
174
0
    if( scError != SYMCRYPT_NO_ERROR )
175
0
    {
176
0
        goto cleanup;
177
0
    }
178
179
    // Make sure that none of the bytes in PS is zero (as per specs)
180
0
    for( i = 0; i < cbPS; i++ )
181
0
    {
182
0
        while( pbPkcs1Format[2 + i] == 0x00 )
183
0
        {
184
0
            scError = SymCryptCallbackRandom( &pbPkcs1Format[2+i], 1 );
185
0
            if( scError != SYMCRYPT_NO_ERROR )
186
0
            {
187
0
                goto cleanup;
188
0
            }
189
0
        }
190
0
    }
191
192
0
    pbPkcs1Format[2 + cbPS] = 0x00;
193
194
0
    memcpy(pbPkcs1Format + 3 + cbPS, pbPlaintext, cbPlaintext);
195
196
0
cleanup:
197
0
    return scError;
198
0
}
199
200
SYMCRYPT_ERROR
201
SYMCRYPT_CALL
202
SymCryptRsaPkcs1RemoveEncryptionPadding(
203
    _Inout_updates_bytes_( cbPkcs1Buffer )  PBYTE       pbPkcs1Format,
204
                                            SIZE_T      cbPkcs1Format,
205
                                            SIZE_T      cbPkcs1Buffer,
206
    _Out_writes_bytes_opt_( cbPlaintext )   PBYTE       pbPlaintext,
207
                                            SIZE_T      cbPlaintext,
208
    _Out_                                   SIZE_T     *pcbPlaintext )
209
0
{
210
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
211
0
    UINT32 mPaddingError = 0;
212
0
    UINT32 mBufferSizeError = 0;
213
214
0
    UINT32 cbPlaintextResult = 0;
215
0
    UINT32 i;
216
0
    UINT32 mByteIsZero;
217
0
    UINT32 mLengthFound;
218
0
    UINT32 iFirstZero;
219
0
    UINT32 cbPlaintextTruncated;
220
221
0
    SYMCRYPT_ASSERT( cbPkcs1Buffer >= cbPkcs1Format );
222
0
    SYMCRYPT_ASSERT( cbPkcs1Buffer >= 32 );                         // Requirements for SymcryptScsRotateBuffer
223
0
    SYMCRYPT_ASSERT( (cbPkcs1Buffer & (cbPkcs1Buffer - 1)) == 0 );  // must be a power of 2
224
0
    SYMCRYPT_ASSERT( cbPkcs1Buffer <= (1 << 30 ));                  // Ensure we can use 31-bit masking operations
225
226
    // Format: 00 02 <PS> 00 <M>
227
    // <PS> 8 or more padding bytes, random, all nonzero
228
    // <M> message, length between 0 and cbPKCS1Format - 11.
229
    // See RFC 3447 for more details.
230
    // We do not reveal the buffer contents through side-channels to avoid Bleichenbacher-style attacks
231
    // This includes the plaintext length, which is determined by the location of the 00 byte
232
233
0
    if ( cbPkcs1Format < 11 )
234
0
    {
235
        // cbPKCS1Format is public, so the if() is safe. 11 is the total overhead
236
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
237
0
        goto cleanup;
238
0
    }
239
    // this also implies that cbPkcs1Buffer >= 16
240
241
    // Check the leading bytes
242
0
    mPaddingError |= SymCryptMask32IsNonzeroU31( pbPkcs1Format[0] ); // First byte must be = 0
243
0
    mPaddingError |= SymCryptMask32NeqU31( pbPkcs1Format[1], PKCS_BLOCKTYPE_2 ); // Second byte must be = 2
244
245
0
    iFirstZero = 0;
246
0
    mLengthFound = 0;
247
0
    for (i = 2; i < cbPkcs1Format; i++)
248
0
    {
249
0
        mByteIsZero = SymCryptMask32IsZeroU31( pbPkcs1Format[i] );
250
251
        // remember the index of the first zero byte
252
0
        iFirstZero |= i & mByteIsZero & ~mLengthFound;
253
0
        mLengthFound |= mByteIsZero;
254
0
    }
255
0
    mPaddingError |= ~mLengthFound;
256
257
    // At this point:
258
    // - iFirstZero points to the first zero byte, or is 0 if there is no zero byte
259
    // - mPaddingError is set if no zero byte was found
260
261
    // It is an error if the first zero is at index < 10 as <PS> needs to be at least 8 bytes
262
0
    mPaddingError |= SymCryptMask32LtU31( iFirstZero, 10 );
263
264
    // Compute the # bytes of the message; 0 if there was a padding error
265
0
    cbPlaintextResult = ~mPaddingError & (cbPkcs1Format - iFirstZero - 1);
266
267
    // We're done if the caller didn't want the actual message, but only the size.
268
    // We do that before checking the size of the plaintext buffer so that callers who
269
    // only want the size do not get an error.
270
0
    if( pbPlaintext == NULL )
271
0
    {
272
        // Condition is public.
273
0
        goto cleanup;
274
0
    }
275
276
    // Checking that the output buffer is large enough is a bit tricky as we have a SIZE_T as
277
    // buffer size, but we like to work on 31-bit integers as they have better mask algorithm perf.
278
    // We can truncate the SIZE_T and check for equality, which is side-channel safe.
279
0
    cbPlaintextTruncated = ((UINT32) cbPlaintext) & 0x7fffffff;                 // Truncate to 31 bits
280
0
    if( cbPlaintextTruncated == cbPlaintext )
281
0
    {
282
        // Condition is public as we write the whole plaintext buffer anyway.
283
0
        mBufferSizeError = SymCryptMask32LtU31( cbPlaintextTruncated, cbPlaintextResult );
284
0
    }
285
286
    // The message starts at iFirstZero + 1, which is a variable location so we can't just memcpy it without
287
    // revealing information through side channels.
288
    // Instead we rotate the buffer left (side-channel safe) so that the message appears at the front.
289
    // Rotation constant is such that the message appears at the start.
290
0
    SymCryptScsRotateBuffer( pbPkcs1Format, cbPkcs1Buffer, (iFirstZero + 1) & (cbPkcs1Buffer - 1) );
291
292
    // The ScsCopy function can copy the data to the destination buffer, but the input buffer must be
293
    // as long as the output buffer. We can't just use cbPlaintext as the output buffer size, as it is
294
    // unbounded. But we can limit it to cbPkcs1Format as that is the public key size and is public.
295
0
    SymCryptScsCopy( pbPkcs1Format, cbPlaintextResult, pbPlaintext, SYMCRYPT_MIN( cbPlaintext, cbPkcs1Format ) );
296
297
0
cleanup:
298
    // Update scError with the two error masks. Padding error given highest priority.
299
0
    scError ^= mBufferSizeError & (scError ^ SYMCRYPT_BUFFER_TOO_SMALL);
300
0
    scError ^= mPaddingError & (scError ^ SYMCRYPT_INVALID_ARGUMENT);
301
302
0
    *pcbPlaintext = cbPlaintextResult;
303
0
    return scError;
304
0
}
305
306
//
307
// OAEP Encryption Format:
308
//                             +----------+---------+-------+
309
//                        DB = |  lHash   |    PS   |   M   |
310
//                             +----------+---------+-------+
311
//                                            |
312
//                  +----------+              V
313
//                  |   seed   |--> MGF ---> xor
314
//                  +----------+              |
315
//                        |                   |
316
//               +--+     V                   |
317
//               |00|    xor <----- MGF <-----|
318
//               +--+     |                   |
319
//                 |      |                   |
320
//                 V      V                   V
321
//               +--+----------+----------------------------+
322
//         EM =  |00|maskedSeed|          maskedDB          |
323
//               +--+----------+----------------------------+
324
//
325
// PS = zero or more bytes 0x00 || 0x01
326
//
327
SYMCRYPT_ERROR
328
SYMCRYPT_CALL
329
SymCryptRsaOaepApplyEncryptionPadding(
330
    _In_reads_bytes_( cbPlaintext )     PCBYTE          pbPlaintext,
331
                                        SIZE_T          cbPlaintext,
332
    _In_                                PCSYMCRYPT_HASH hashAlgorithm,
333
    _In_reads_bytes_( cbLabel )         PCBYTE          pbLabel,
334
                                        SIZE_T          cbLabel,
335
    _In_reads_bytes_opt_( cbSeed )      PCBYTE          pbSeed,
336
                                        SIZE_T          cbSeed,
337
    _Out_writes_bytes_( cbOaepFormat )  PBYTE           pbOaepFormat,
338
                                        SIZE_T          cbOaepFormat,
339
    _Out_writes_bytes_( cbScratch )     PBYTE           pbScratch,
340
                                        SIZE_T          cbScratch )
341
0
{
342
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
343
344
0
    PVOID   pHashState;
345
346
0
    PBYTE   pbSeedInternal;
347
0
    PBYTE   pbSeedMask;
348
0
    PBYTE   pbDB;
349
0
    PBYTE   pbDBMask;
350
351
0
    SIZE_T  cbDB;
352
0
    SIZE_T  cbPS;
353
354
0
    SIZE_T  cbHash = SymCryptHashResultSize( hashAlgorithm );
355
0
    SIZE_T  cbHashState = SymCryptHashStateSize( hashAlgorithm );
356
357
0
    UNREFERENCED_PARAMETER( cbScratch );
358
359
    // OAEP overhead is 2 + 2 * size of hash result
360
0
    if(  cbOaepFormat < (cbPlaintext + (cbHash * 2) + 2) ||
361
0
         ((pbSeed!=NULL) && (cbSeed>cbHash)) ||
362
0
         ((pbSeed==NULL) && (cbSeed!=0)) )
363
0
    {
364
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
365
0
        goto cleanup;
366
0
    }
367
368
0
    cbPS = cbOaepFormat - (cbPlaintext + (cbHash * 2) + 2);
369
0
    cbDB = cbOaepFormat - (cbHash + 1);
370
371
0
    SYMCRYPT_ASSERT( cbScratch >= cbHashState + (cbHash * 2) + (cbDB * 2) );
372
373
0
    pHashState = (PVOID) pbScratch;
374
0
    pbSeedInternal = pbScratch + cbHashState;
375
0
    pbSeedMask = pbSeedInternal + cbHash;
376
0
    pbDB = pbSeedMask + cbHash;
377
0
    pbDBMask = pbDB + cbDB;
378
379
    // hash the label
380
0
    SymCryptHash( hashAlgorithm, pbLabel, cbLabel, pbDB, cbHash );
381
382
0
    SymCryptWipe(pbDB + cbHash, cbPS);
383
0
    pbDB[cbHash + cbPS] = 0x01;
384
385
  // dcl - are we quite sure that none of these numbers are under attacker control?
386
0
    memcpy(pbDB + cbHash + cbPS + 1, pbPlaintext, cbPlaintext);
387
388
0
    if (NULL == pbSeed)
389
0
    {
390
        // generate the random seed (same length as the hash result)
391
0
        scError = SymCryptCallbackRandom( pbSeedInternal, cbHash );
392
0
        if (scError != SYMCRYPT_NO_ERROR)
393
0
        {
394
0
            goto cleanup;
395
0
        }
396
0
    }
397
0
    else
398
0
    {
399
0
        SymCryptWipe( pbSeedInternal, cbHash );
400
0
        memcpy(pbSeedInternal, pbSeed, cbSeed);
401
0
    }
402
403
    // MGF(seed)
404
0
    SymCryptRsaPaddingMaskGeneration(
405
0
                            hashAlgorithm,
406
0
                            pHashState,
407
0
                            pbSeedInternal,
408
0
                            cbHash,
409
0
                            pbDBMask,
410
0
                            cbDB);
411
412
    // set the most significant byte to 0x00
413
0
    pbOaepFormat[0] = 0x00;
414
415
    // XOR the DB and the mask MGF(seed)
416
0
    for (UINT32 i = 0; i < cbDB; i++)
417
0
    {
418
0
        pbOaepFormat[cbHash + 1 + i] = pbDB[i] ^ pbDBMask[i];
419
0
    }
420
421
    // MGF(masked DB)
422
0
    SymCryptRsaPaddingMaskGeneration(
423
0
                            hashAlgorithm,
424
0
                            pHashState,
425
0
                            pbOaepFormat + cbHash + 1,
426
0
                            cbDB,
427
0
                            pbSeedMask,
428
0
                            cbHash);
429
430
    // XOR the seed and the seed mask MGF(masked DB)
431
0
    for (UINT32 i = 0; i < cbHash; i++)
432
0
    {
433
0
        pbOaepFormat[1 + i] = pbSeedInternal[i] ^ pbSeedMask[i];
434
0
    }
435
436
0
    scError = SYMCRYPT_NO_ERROR;
437
438
0
cleanup:
439
440
0
    return scError;
441
0
}
442
443
SYMCRYPT_ERROR
444
SYMCRYPT_CALL
445
SymCryptRsaOaepRemoveEncryptionPadding(
446
    _In_reads_bytes_( cbOAEPFormat )
447
                                PCBYTE                      pbOAEPFormat,
448
                                SIZE_T                      cbOAEPFormat,
449
    _In_                        PCSYMCRYPT_HASH             hashAlgorithm,
450
    _In_reads_bytes_( cbLabel ) PCBYTE                      pbLabel,
451
                                SIZE_T                      cbLabel,
452
                                UINT32                      flags,
453
    _Out_writes_bytes_( cbPlaintext )
454
                                PBYTE                       pbPlaintext,
455
                                SIZE_T                      cbPlaintext,
456
    _Out_                       SIZE_T                      *pcbPlaintext,
457
    _Out_writes_bytes_( cbScratch )
458
                                PBYTE                       pbScratch,
459
                                SIZE_T                      cbScratch )
460
0
{
461
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
462
463
0
    PVOID   pHashState;
464
465
0
    PBYTE   pbSeedMask;
466
0
    PBYTE   pbSeed;
467
0
    PBYTE   pbDBMask;
468
0
    PBYTE   pbDB;
469
0
    PBYTE   pbLabelHash;
470
0
    UINT32  mPaddingError;
471
472
0
    SIZE_T  cbDB;
473
474
0
    SIZE_T  cnt = 0;
475
476
0
    SIZE_T  cbHashAlg = SymCryptHashResultSize( hashAlgorithm );
477
0
    SIZE_T  cbHashState = SymCryptHashStateSize( hashAlgorithm );
478
479
0
    UNREFERENCED_PARAMETER( cbScratch );
480
481
0
    if (flags != 0)
482
0
    {
483
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
484
0
        goto cleanup;
485
0
    }
486
487
    // check if the most significant byte is set to 0x00
488
0
    mPaddingError = SymCryptMask32IsNonzeroU31( pbOAEPFormat[0] );
489
490
    // Padding overhead is 2 hash values plus 2 bytes
491
0
    if( cbOAEPFormat < (2*cbHashAlg + 2) )
492
0
    {
493
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
494
0
        goto cleanup;
495
0
    }
496
497
0
    cbDB = cbOAEPFormat - (cbHashAlg + 1);
498
499
0
    SYMCRYPT_ASSERT( cbScratch >= cbHashState + (cbHashAlg * 3) + (cbDB * 2) );
500
501
0
    pHashState = (PVOID) pbScratch;
502
0
    pbSeedMask = pbScratch + cbHashState;
503
0
    pbSeed = pbSeedMask + cbHashAlg;
504
0
    pbDBMask = pbSeed + cbHashAlg;
505
0
    pbDB = pbDBMask + cbDB;
506
0
    pbLabelHash = pbDB + cbDB;
507
508
    // MGF(masked DB)
509
0
    SymCryptRsaPaddingMaskGeneration(
510
0
                            hashAlgorithm,
511
0
                            pHashState,
512
0
                            pbOAEPFormat + cbHashAlg + 1,
513
0
                            cbDB,
514
0
                            pbSeedMask,
515
0
                            cbHashAlg);
516
517
    // XOR the masked seed and the seed mask MGF(masked DB)
518
0
    for (UINT32 i = 0; i < cbHashAlg; i++)
519
0
    {
520
0
        pbSeed[i] = pbOAEPFormat[1 + i] ^ pbSeedMask[i];
521
0
    }
522
523
    // MGF(seed)
524
0
    SymCryptRsaPaddingMaskGeneration(
525
0
                            hashAlgorithm,
526
0
                            pHashState,
527
0
                            pbSeed,
528
0
                            cbHashAlg,
529
0
                            pbDBMask,
530
0
                            cbDB);
531
532
    // XOR the masked DB and the mask MGF(seed)
533
0
    for (UINT32 i = 0; i < cbDB; i++)
534
0
    {
535
0
        pbDB[i] = pbOAEPFormat[cbHashAlg + 1 + i] ^ pbDBMask[i];
536
0
    }
537
538
    // hash the label
539
0
    SymCryptHash( hashAlgorithm, pbLabel, cbLabel, pbLabelHash, cbHashAlg );
540
541
    // check the label hash
542
0
    mPaddingError |= SymCryptMask32IsZeroU31( SymCryptEqual( pbLabelHash, pbDB, cbHashAlg ) );
543
544
    //
545
    // At this point we have verified the leading 0 byte and the label hash, with any
546
    // errors in mPaddingError. We could continue to make the entire padding removal
547
    // side-channel safe like we do in the PKCS1 padding case, but that is not necessary.
548
    // The side-channel only leaks data if the attacker can trigger two different behaviours
549
    // and derive information from the difference.
550
    // This is relatively easy to do with something like a match on 1 or 2 bytes because the
551
    // chance of satisfying the check on a random input is still useful. But here we have
552
    // matched 33 bytes (assuming a 32-byte hash) and the Bleichenbacher style attacks don't
553
    // work beyond this point. Basically, these attacks produce ciphertexts without knowing
554
    // the corresponding plaintext, and the chance of the label hash matching is something
555
    // like 2^{-256}. So these ciphertexts will always fail right here, and there is no
556
    // difference of behaviour that leaks data to the attacker.
557
    // Thus, we can switch back to normal processing of the errors here.
558
    //
559
560
0
    if( mPaddingError != 0 )
561
0
    {
562
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
563
0
        goto cleanup;
564
0
    }
565
566
    // check the PS
567
0
    for (cnt = cbHashAlg; cnt < cbDB; cnt++)
568
0
    {
569
0
        if (pbDB[cnt] == 0x01)
570
0
        {
571
0
            cnt++;
572
0
            break;
573
0
        }
574
0
        else if (pbDB[cnt] != 0x00)
575
0
        {
576
0
            scError = SYMCRYPT_INVALID_ARGUMENT;
577
0
            goto cleanup;
578
0
        }
579
0
    }
580
581
    // the rest is data
582
0
    *pcbPlaintext = cbDB - cnt;
583
584
0
    if(NULL == pbPlaintext)
585
0
    {
586
0
        scError = SYMCRYPT_NO_ERROR;
587
0
        goto cleanup;
588
0
    }
589
590
0
    if (cbPlaintext < *pcbPlaintext)
591
0
    {
592
0
        scError = SYMCRYPT_BUFFER_TOO_SMALL;
593
0
        goto cleanup;
594
0
    }
595
596
0
    memcpy(pbPlaintext, pbDB + cnt, *pcbPlaintext);
597
598
0
    scError = SYMCRYPT_NO_ERROR;
599
600
0
cleanup:
601
602
0
    return scError;
603
0
}
604
605
//
606
// PKCS1 Signature Format:
607
//
608
SYMCRYPT_ERROR
609
SYMCRYPT_CALL
610
SymCryptRsaPkcs1ApplySignaturePadding(
611
    _In_reads_bytes_( cbHash )  PCBYTE                      pbHash,
612
                                SIZE_T                      cbHash,
613
    _In_reads_bytes_( cbHashOid )
614
                                PCBYTE                      pbHashOid,
615
                                SIZE_T                      cbHashOid,
616
                                UINT32                      flags,
617
    _Out_writes_bytes_( cbPKCS1Format )
618
                                PBYTE                       pbPKCS1Format,
619
                                SIZE_T                      cbPKCS1Format )
620
0
{
621
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
622
623
0
    SIZE_T cbEncoding;
624
0
    SIZE_T cbPadding;
625
0
    SIZE_T cbOidOffset;
626
627
0
    BOOLEAN fInsertASN1 = TRUE;
628
629
0
    if ((flags & ~SYMCRYPT_FLAG_RSA_PKCS1_NO_ASN1) != 0)
630
0
    {
631
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
632
0
        goto cleanup;
633
0
    }
634
635
0
    fInsertASN1 = ((flags & SYMCRYPT_FLAG_RSA_PKCS1_NO_ASN1) == 0);
636
637
0
    if (fInsertASN1)
638
0
    {
639
0
        if ( (pbHashOid!=NULL) && (cbHashOid>0) )
640
0
        {
641
            // determine the length of the ASN1 Encoding
642
            // 2 sequence bytes, 1 id byte and 3 length bytes
643
0
            cbEncoding = 6 + cbHashOid + cbHash;
644
0
        }
645
0
        else
646
0
        {
647
0
            if (cbHashOid > 0)
648
0
            {
649
                // The caller has passed a NULL hash and a non 0 size for it.
650
                // We can't guess the intent, hence we fail
651
0
                scError = SYMCRYPT_INVALID_ARGUMENT;
652
0
                goto cleanup;
653
0
            }
654
655
            // special case for MD5 hash without OID
656
0
            cbEncoding = 2 + cbHash;
657
0
        }
658
0
    }
659
0
    else
660
0
    {
661
0
        cbEncoding = cbHash;
662
0
    }
663
664
    // we don't support encodings longer than 128 bytes,
665
    // with this check we know that the length of the OID as
666
    // well as the length of the hash value will each fit in
667
    // one byte
668
0
    if (cbEncoding > 0x80)
669
0
    {
670
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
671
0
        goto cleanup;
672
0
    }
673
674
    // In a few scenarios (involving small RSA keys), the new large SHA
675
    // hashes are too big to be signed by the specified key.
676
    // There must be at least 8 bytes of 0xff.
677
0
    if (3 + 8 + cbEncoding > cbPKCS1Format)
678
0
    {
679
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
680
0
        goto cleanup;
681
0
    }
682
683
0
    cbPadding = cbPKCS1Format - 3 - cbEncoding;
684
685
686
    // insert the block type and delimiters
687
0
    pbPKCS1Format[0] = 0x00;
688
0
    pbPKCS1Format[1] = 0x01;
689
0
    pbPKCS1Format[2 + cbPadding] = 0x00;
690
691
    // insert the type 1 padding
692
0
    memset(pbPKCS1Format + 2, 0xff, cbPadding);
693
694
0
    if (fInsertASN1)
695
0
    {
696
0
        cbOidOffset = 1;
697
0
        if ( (pbHashOid!=NULL) && (cbHashOid>0) )
698
0
        {
699
            // insert the algorithm encoding
700
0
            pbPKCS1Format[2 + cbPadding + 1] = ASN1_SEQUENCE_BYTE;
701
0
            pbPKCS1Format[2 + cbPadding + 2] = (BYTE)cbEncoding - 2;
702
703
            // insert the sequence string byte, length of the hash and the hash value
704
0
            pbPKCS1Format[2 + cbPadding + 3] = ASN1_SEQUENCE_BYTE;
705
0
            pbPKCS1Format[2 + cbPadding + 4] = (BYTE)cbHashOid;
706
0
            cbOidOffset += 4;
707
0
            memcpy(pbPKCS1Format + 2 + cbPadding + cbOidOffset, pbHashOid, cbHashOid);
708
0
        }
709
710
        // insert the octet string byte, length of the hash and the hash value
711
0
        pbPKCS1Format[2 + cbPadding + cbOidOffset + cbHashOid] = ASN1_OCTET_STRING_BYTE;
712
0
        pbPKCS1Format[2 + cbPadding + cbOidOffset + cbHashOid + 1] = (BYTE)cbHash;
713
0
        memcpy(pbPKCS1Format + 2 + cbPadding + cbOidOffset + cbHashOid + 2, pbHash, cbHash);
714
0
    }
715
0
    else
716
0
    {
717
0
        memcpy(pbPKCS1Format + 3 + cbPadding, pbHash, cbHash);
718
0
    }
719
720
0
    scError = SYMCRYPT_NO_ERROR;
721
722
0
cleanup:
723
724
0
    return scError;
725
0
}
726
727
//
728
// Check if a PKCS1 padding is valid with regard to a hash oid
729
//
730
SYMCRYPT_ERROR
731
SYMCRYPT_CALL
732
SymCryptRsaPkcs1CheckSignaturePadding(
733
    _In_reads_bytes_( cbHash )  PCBYTE                      pbHash,
734
                                SIZE_T                      cbHash,
735
    _In_reads_bytes_( cbHashOid )
736
                                PCBYTE                      pbHashOid,
737
                                SIZE_T                      cbHashOid,
738
    _In_reads_bytes_( cbPKCS1Format )
739
                                PCBYTE                      pbPKCS1Format,
740
                                UINT32                      flags,
741
    _Out_writes_bytes_( cbPKCS1Format )
742
                                PBYTE                       pbScratch,
743
                                SIZE_T                      cbPKCS1Format)
744
0
{
745
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
746
747
0
    SymCryptWipe(pbScratch, cbPKCS1Format);
748
749
0
    scError = SymCryptRsaPkcs1ApplySignaturePadding(
750
0
                      pbHash,
751
0
                      cbHash,
752
0
                      pbHashOid,
753
0
                      cbHashOid,
754
0
                      flags,
755
0
                      pbScratch,
756
0
                      cbPKCS1Format );
757
0
    if (scError != SYMCRYPT_NO_ERROR)
758
0
    {
759
0
        goto cleanup;
760
0
    }
761
762
0
    if ( SymCryptEqual(pbScratch, pbPKCS1Format, cbPKCS1Format) )
763
0
    {
764
0
        scError = SYMCRYPT_NO_ERROR;
765
0
    }
766
0
    else
767
0
    {
768
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
769
0
    }
770
771
0
cleanup:
772
773
0
    return scError;
774
0
}
775
776
777
SYMCRYPT_ERROR
778
SYMCRYPT_CALL
779
SymCryptRsaPkcs1VerifySignaturePadding(
780
    _In_reads_bytes_( cbHash )  PCBYTE                      pbHash,
781
                                SIZE_T                      cbHash,
782
    _In_reads_( nOIDCount )     PCSYMCRYPT_OID              pHashOIDs,
783
    _In_                        SIZE_T                      nOIDCount,
784
    _In_reads_bytes_( cbPKCS1Format )
785
                                PCBYTE                      pbPKCS1Format,
786
                                SIZE_T                      cbPKCS1Format,
787
                                UINT32                      flags,
788
    _Out_writes_bytes_( cbScratch )
789
                                PBYTE                       pbScratch,
790
                                SIZE_T                      cbScratch )
791
0
{
792
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
793
0
    UINT32 i = 0;
794
795
0
    UNREFERENCED_PARAMETER( cbScratch );
796
0
    SYMCRYPT_ASSERT( cbScratch >= cbPKCS1Format );
797
798
0
    if ((flags & ~SYMCRYPT_FLAG_RSA_PKCS1_OPTIONAL_HASH_OID) != 0)
799
0
    {
800
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
801
0
        goto cleanup;
802
0
    }
803
804
    //
805
    // Verify padding and the hash value
806
    //
807
0
    if (pHashOIDs)
808
0
    {
809
0
        for (i = 0; i < nOIDCount; i++)
810
0
        {
811
0
            scError = SymCryptRsaPkcs1CheckSignaturePadding(
812
0
                              pbHash,
813
0
                              cbHash,
814
0
                              pHashOIDs[i].pbOID,
815
0
                              pHashOIDs[i].cbOID,
816
0
                              pbPKCS1Format,
817
0
                              0,
818
0
                              pbScratch,
819
0
                              cbPKCS1Format );
820
0
            if (scError == SYMCRYPT_NO_ERROR)
821
0
            {
822
0
                break;
823
0
            }
824
0
        }
825
0
    }
826
827
0
    if  ((pHashOIDs == NULL ) ||
828
0
         (scError != SYMCRYPT_NO_ERROR &&
829
0
          flags & SYMCRYPT_FLAG_RSA_PKCS1_OPTIONAL_HASH_OID))
830
0
    {
831
        // if no OID is passed in, or
832
        // OID is passed in but failed verification, but OID is optional
833
0
        scError = SymCryptRsaPkcs1CheckSignaturePadding(
834
0
                          pbHash,
835
0
                          cbHash,
836
0
                          NULL,
837
0
                          0,
838
0
                          pbPKCS1Format,
839
0
                          SYMCRYPT_FLAG_RSA_PKCS1_NO_ASN1,
840
0
                          pbScratch,
841
0
                          cbPKCS1Format );
842
0
    }
843
844
0
cleanup:
845
846
0
    return scError;
847
0
}
848
849
//
850
// PSS Signature Format:
851
//                        +--------+----------+----------+
852
//                   M' = |Padding1|  Hash M  |   salt   |
853
//                        +--------+----------+----------+
854
//                                       |
855
//             +--------+----------+     V
856
//       DB =  |Padding2|   salt   |   Hash
857
//             +--------+----------+     |
858
//                       |               |
859
//                       V               |    +--+
860
//                      xor <--- MGF <---|    |bc|
861
//                       |               |    +--+
862
//                       |               |      |
863
//                       V               V      V
864
//             +-------------------+----------+--+
865
//       EM =  |    maskedDB       |     H    |bc|
866
//             +-------------------+----------+--+
867
//
868
SYMCRYPT_ERROR
869
SYMCRYPT_CALL
870
SymCryptRsaPssApplySignaturePadding(
871
    _In_reads_bytes_( cbHash )  PCBYTE                      pbHash,
872
                                SIZE_T                      cbHash,
873
    _In_                        PCSYMCRYPT_HASH             hashAlgorithm,
874
    _In_reads_bytes_opt_( cbSalt )
875
                                PCBYTE                      pbSalt,
876
    _In_range_(0, cbPSSFormat)  SIZE_T                      cbSalt,
877
                                UINT32                      nBitsOfModulus,
878
                                UINT32                      flags,
879
    _Out_writes_bytes_( cbPSSFormat )
880
                                PBYTE                       pbPSSFormat,
881
                                SIZE_T                      cbPSSFormat,
882
    _Out_writes_bytes_( cbScratch )
883
                                PBYTE                       pbScratch,
884
                                SIZE_T                      cbScratch )
885
0
{
886
0
    SYMCRYPT_ERROR  scError = SYMCRYPT_NO_ERROR;
887
888
0
    PVOID   pHashState;
889
890
0
    PBYTE pbMPrime;
891
0
    PBYTE pbDB;
892
0
    PBYTE pbDBMask;
893
894
0
    SIZE_T cbDB;
895
0
    SIZE_T cbMPrime;
896
0
    SIZE_T cbPadding2;
897
898
0
    SIZE_T dwZeroBits  = 0; // Number of bits of the leftmost bit to be zeroed
899
900
0
    SIZE_T cbHashAlg = SymCryptHashResultSize( hashAlgorithm );
901
0
    SIZE_T cbHashState = SymCryptHashStateSize( hashAlgorithm );
902
903
0
    UNREFERENCED_PARAMETER( cbScratch );
904
905
0
    if ((cbPSSFormat == 0) || (pbPSSFormat == NULL))
906
0
    {
907
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
908
0
        goto cleanup;
909
0
    }
910
911
    // Corner case of RFC 3447 for PSS:
912
    //  If nBitsOfModulus == 1 mod 8, then emBits = nBitsOfModulus - 1 == 0 mod 8
913
    //  Thus the size of the input buffer in bytes is emLen = ceil(emBits /8),
914
    //  one smaller than the size of the modulus. Fix this here by setting the
915
    //  leftmost byte of the output equal to 0.
916
0
    if (nBitsOfModulus%8 == 1)
917
0
    {
918
0
        pbPSSFormat[0] = 0;
919
0
        pbPSSFormat++;
920
0
        cbPSSFormat--;
921
0
    }
922
923
0
    if ((flags!=0) ||
924
0
        (cbPSSFormat < (cbHashAlg + cbSalt + 2)) )
925
0
    {
926
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
927
0
        goto cleanup;
928
0
    }
929
930
0
    cbDB = cbPSSFormat - (cbHashAlg + 1);
931
0
    cbPadding2 = cbDB - cbSalt - 1;
932
0
    cbMPrime = 8 + cbHash + cbSalt;
933
934
0
    SYMCRYPT_ASSERT( cbScratch >= cbHashState + cbMPrime + (cbDB * 2) );
935
936
0
    pHashState = (PVOID) pbScratch;
937
0
    pbMPrime = pbScratch + cbHashState;
938
0
    pbDB = pbMPrime + cbMPrime;
939
0
    pbDBMask = pbDB + cbDB;
940
941
    // set up the M Prime
942
0
    SymCryptWipe(pbMPrime, 8);
943
0
    memcpy(pbMPrime + 8, pbHash, cbHash);
944
945
0
    if (NULL == pbSalt)
946
0
    {
947
        // generate the random salt
948
0
        scError = SymCryptCallbackRandom(
949
0
                            pbMPrime + 8 + cbHash,
950
0
                            cbSalt);
951
0
        if (scError != SYMCRYPT_NO_ERROR)
952
0
        {
953
0
            goto cleanup;
954
0
        }
955
0
    }
956
0
    else
957
0
    {
958
        // copy the salt passed
959
0
        memcpy(pbMPrime + 8 + cbHash, pbSalt, cbSalt);
960
0
    }
961
962
    // hash the MPrime
963
0
    SymCryptHash( hashAlgorithm, pbMPrime, cbMPrime, pbPSSFormat + cbDB, cbHashAlg );
964
965
    // copy the same salt into the DB
966
0
    SymCryptWipe(pbDB, cbPadding2);
967
0
    pbDB[cbPadding2] = 0x01;
968
0
    memcpy(pbDB + cbPadding2 + 1, pbMPrime + 8 + cbHash, cbSalt);
969
970
    // MGF(Hash of MPrime)
971
0
    SymCryptRsaPaddingMaskGeneration(
972
0
                            hashAlgorithm,
973
0
                            pHashState,
974
0
                            pbPSSFormat + cbDB,
975
0
                            cbHashAlg,
976
0
                            pbDBMask,
977
0
                            cbDB);
978
979
    // XOR the DB and the mask MGF(seed)
980
0
    for (UINT32 i = 0; i < cbDB; i++)
981
0
    {
982
0
        pbPSSFormat[i] = pbDB[i] ^ pbDBMask[i];
983
0
    }
984
985
    // calculate the number of bits to be zeroed
986
0
    dwZeroBits = 8*cbPSSFormat + 1 - nBitsOfModulus;
987
988
    // mask off dwZeroBits worth of the encoded message
989
0
    pbPSSFormat[0] &= (BYTE)(0xff >> dwZeroBits);
990
991
    // set the least significant byte of pbPSSFormat to bc
992
0
    pbPSSFormat[cbPSSFormat - 1] = 0xbc;
993
994
0
    scError = SYMCRYPT_NO_ERROR;
995
996
0
cleanup:
997
998
0
    return scError;
999
0
}
1000
1001
SYMCRYPT_ERROR
1002
SYMCRYPT_CALL
1003
SymCryptRsaPssVerifySignaturePadding(
1004
    _In_reads_bytes_( cbHash )  PCBYTE                      pbHash,
1005
                                SIZE_T                      cbHash,
1006
    _In_                        PCSYMCRYPT_HASH             hashAlgorithm,
1007
    _In_range_(0, cbPSSFormat)  SIZE_T                      cbSalt,
1008
    _In_reads_bytes_( cbPSSFormat )
1009
                                PCBYTE                      pbPSSFormat,
1010
                                SIZE_T                      cbPSSFormat,
1011
                                UINT32                      nBitsOfModulus,
1012
                                UINT32                      flags,
1013
    _Out_writes_bytes_( cbScratch )
1014
                                PBYTE                       pbScratch,
1015
                                SIZE_T                      cbScratch )
1016
0
{
1017
0
    SYMCRYPT_ERROR  scError = SYMCRYPT_NO_ERROR;
1018
1019
0
    PVOID   pHashState;
1020
1021
0
    PBYTE pbDBMask;
1022
0
    PBYTE pbMPrime;
1023
0
    PBYTE pbMPrimeHash;
1024
0
    PCBYTE pbHashOfMPrimeIndex;
1025
1026
0
    SIZE_T cbDB;
1027
0
    SIZE_T cbMPrime;
1028
0
    SIZE_T cbPadding2;
1029
0
    SIZE_T cbSaltObserved;
1030
1031
0
    SIZE_T dwZeroBits  = 0; // Number of bits of the leftmost bit to be zeroed
1032
1033
0
    SIZE_T cbHashAlg = SymCryptHashResultSize( hashAlgorithm );
1034
0
    SIZE_T cbHashState = SymCryptHashStateSize( hashAlgorithm );
1035
1036
0
    UNREFERENCED_PARAMETER( cbScratch );
1037
1038
0
    if (((flags & ~SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT) != 0) ||
1039
0
        (cbPSSFormat == 0) ||
1040
0
        (pbPSSFormat == NULL))
1041
0
    {
1042
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
1043
0
        goto cleanup;
1044
0
    }
1045
1046
    // Corner case of RFC 3447 for PSS:
1047
    //  If nBitsOfModulus == 1 mod 8, then emBits = nBitsOfModulus - 1 == 0 mod 8
1048
    //  Thus the size of the input buffer in bytes is emLen = ceil(emBits /8),
1049
    //  one smaller than the size of the modulus. Fix this here by checking that the
1050
    //  leftmost byte of the input equals 0.
1051
0
    if (nBitsOfModulus%8 == 1)
1052
0
    {
1053
0
        if (pbPSSFormat[0] != 0)
1054
0
        {
1055
0
            scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1056
0
            goto cleanup;
1057
0
        }
1058
0
        pbPSSFormat++;
1059
0
        cbPSSFormat--;
1060
0
    }
1061
1062
    // calculate the number of bits to be zeroed
1063
0
    dwZeroBits = 8*cbPSSFormat + 1 - nBitsOfModulus;
1064
1065
    // check the most significant dwZeroBits bits to ensure they're zero and
1066
    // check the least significant byte
1067
0
    if( (cbPSSFormat < (cbHashAlg + cbSalt + 2)) ||
1068
0
        (pbPSSFormat[0] & (BYTE)(0xff << (8 - dwZeroBits))) != 0 ||
1069
0
        pbPSSFormat[cbPSSFormat - 1] != 0xbc
1070
0
        )
1071
0
    {
1072
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1073
0
        goto cleanup;
1074
0
    }
1075
1076
0
    cbDB = cbPSSFormat - (cbHashAlg + 1);
1077
1078
0
    pHashState = (PVOID) pbScratch;
1079
0
    pbDBMask = pbScratch + cbHashState;
1080
1081
    // index to hash of M Prime
1082
0
    pbHashOfMPrimeIndex = pbPSSFormat + (cbPSSFormat - (cbHashAlg + 1));
1083
1084
    // MGF(masked DB)
1085
0
    SymCryptRsaPaddingMaskGeneration(
1086
0
            hashAlgorithm,
1087
0
            pHashState,
1088
0
            pbHashOfMPrimeIndex,
1089
0
            cbHashAlg,
1090
0
            pbDBMask,
1091
0
            cbDB);
1092
1093
    // XOR the DB and the DB mask and store the result in pbDBMask (not needed after this)
1094
0
    for (UINT32 i = 0; i < cbDB; i++)
1095
0
    {
1096
0
        pbDBMask[i] = pbPSSFormat[i] ^ pbDBMask[i];
1097
0
    }
1098
1099
    // mask off the first dwZeroBits
1100
0
    pbDBMask[0] &= (BYTE)(0xff >> dwZeroBits);
1101
1102
    // find the length of the all-zeroes padding2 in pbDBMask
1103
    // padding2 must be terminated by a 0x01 byte
1104
0
    for (cbPadding2 = 0; cbPadding2 < (cbDB - cbSalt); cbPadding2++)
1105
0
    {
1106
0
        if (pbDBMask[cbPadding2] == 0x01)
1107
0
        {
1108
            // we have reached the end of padding2
1109
0
            break;
1110
0
        }
1111
1112
0
        if (pbDBMask[cbPadding2] != 0x00)
1113
0
        {
1114
            // non-zero byte in what should be padding2
1115
0
            scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1116
0
            goto cleanup;
1117
0
        }
1118
0
    }
1119
1120
    // Here we have either:
1121
    // cbPadding2 == cbDB - cbSalt, which means the padding is too long
1122
    // or
1123
    // cbPadding2 <= cbDB - cbSalt - 1, and we have broken out of the loop when we found the 0x01 byte
1124
0
    if( cbPadding2 == cbDB - cbSalt )
1125
0
    {
1126
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1127
0
        goto cleanup;
1128
0
    }
1129
1130
0
    cbSaltObserved = cbDB - cbPadding2 - 1;
1131
    // cbSalt <= cbDB - cbPadding2 - 1 = cbSaltObserved
1132
    // so cbSaltObserved is acceptable value for signature verification
1133
    // with SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT
1134
1135
0
    if( ((flags & SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT) == 0) &&
1136
0
        cbSaltObserved != cbSalt )
1137
0
    {
1138
        // When SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT not specified,
1139
        // we require salt length observed to exactly match the caller provided salt length
1140
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1141
0
        goto cleanup;
1142
0
    }
1143
1144
0
    pbMPrime = pbDBMask + cbDB;
1145
0
    cbMPrime = 8 + cbHash + cbSaltObserved;
1146
0
    pbMPrimeHash = pbMPrime + cbMPrime;
1147
1148
0
    SYMCRYPT_ASSERT( cbScratch >= cbHashState + cbDB + cbMPrime + cbHashAlg );
1149
1150
    // create the M Prime
1151
0
    SymCryptWipe(pbMPrime, 8);
1152
0
    memcpy(pbMPrime + 8, pbHash, cbHash);
1153
0
    memcpy(pbMPrime + 8 + cbHash,
1154
0
           pbDBMask + (cbDB - cbSaltObserved),
1155
0
           cbSaltObserved);
1156
1157
    // hash the M Prime
1158
0
    SymCryptHash( hashAlgorithm, pbMPrime, cbMPrime, pbMPrimeHash, cbHashAlg );
1159
1160
0
    if ( !SymCryptEqual(pbPSSFormat + cbDB, pbMPrimeHash, cbHashAlg) )
1161
0
    {
1162
0
        scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1163
0
        goto cleanup;
1164
0
    }
1165
1166
0
    scError = SYMCRYPT_NO_ERROR;
1167
1168
0
cleanup:
1169
0
    return scError;
1170
0
}