Skip to content

Commit a5bd660

Browse files
Merged PR 6558632: Address the vast majority of other SymCryptFatals
+ In some cases replace with C_ASSERTs + In some cases replace with SYMCRYPT_ASSERTs (fail only in CHK build) + In some cases replace with SYMCRYPT_ASSERT and replace a faulty input with an input which will give a result which is incorrect but won't crash Related work items: #37153656, #35463330
1 parent e63a01d commit a5bd660

36 files changed

+500
-372
lines changed

inc/symcrypt.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,7 @@ SymCryptParallelSha256Init(
13951395
_Out_writes_( nStates ) PSYMCRYPT_SHA256_STATE pStates,
13961396
SIZE_T nStates );
13971397

1398-
VOID
1398+
SYMCRYPT_ERROR
13991399
SYMCRYPT_CALL
14001400
SymCryptParallelSha256Process(
14011401
_Inout_updates_( nStates ) PSYMCRYPT_SHA256_STATE pStates,
@@ -1412,7 +1412,7 @@ SymCryptParallelSha384Init(
14121412
_Out_writes_( nStates ) PSYMCRYPT_SHA384_STATE pStates,
14131413
SIZE_T nStates );
14141414

1415-
VOID
1415+
SYMCRYPT_ERROR
14161416
SYMCRYPT_CALL
14171417
SymCryptParallelSha384Process(
14181418
_Inout_updates_( nStates ) PSYMCRYPT_SHA384_STATE pStates,
@@ -1429,7 +1429,7 @@ SymCryptParallelSha512Init(
14291429
_Out_writes_( nStates ) PSYMCRYPT_SHA512_STATE pStates,
14301430
SIZE_T nStates );
14311431

1432-
VOID
1432+
SYMCRYPT_ERROR
14331433
SYMCRYPT_CALL
14341434
SymCryptParallelSha512Process(
14351435
_Inout_updates_( nStates ) PSYMCRYPT_SHA512_STATE pStates,
@@ -3546,7 +3546,7 @@ SymCryptChaCha20Crypt(
35463546
// The key stream used is the one generated from the key and nonce, starting at the specified
35473547
// offset into the key stream. This function updates the offset of the state by adding cbData to
35483548
// it so that the next call will use the next part of the key stream.
3549-
// Any attempt to use the key stream at offset >= 2^38 will result in a fatal error.
3549+
// Any attempt to use the key stream at offset >= 2^38 will result in catastrophic loss of security.
35503550
//
35513551

35523552
VOID
@@ -6270,14 +6270,12 @@ SymCryptMapUint32(
62706270
// This function is particularly useful when mapping error codes in situations where
62716271
// the actual error cannot be revealed through side channels.
62726272

6273-
#define SYMCRYPT_HARD_ASSERT( _x ) \
6273+
#if SYMCRYPT_DEBUG
6274+
#define SYMCRYPT_ASSERT( _x ) \
62746275
{\
62756276
if( !(_x) ){ SymCryptFatal( 'asrt' ); }\
62766277
}\
62776278
_Analysis_assume_( _x )
6278-
6279-
#if SYMCRYPT_DEBUG
6280-
#define SYMCRYPT_ASSERT( _x ) SYMCRYPT_HARD_ASSERT( _x )
62816279
#else
62826280
#define SYMCRYPT_ASSERT( _x ) \
62836281
_Analysis_assume_( _x )

inc/symcrypt_internal.h

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ typedef uint8_t BYTE;
209209
// Size_t
210210
typedef size_t SIZE_T;
211211

212+
#ifndef SIZE_T_MAX
213+
#define SIZE_T_MAX SIZE_MAX
214+
#endif
215+
212216
typedef long INT_PTR, *PINT_PTR;
213217
typedef unsigned long UINT_PTR, *PUINT_PTR;
214218

@@ -1688,11 +1692,11 @@ typedef const SYMCRYPT_ECPOINT * PCSYMCRYPT_ECPOINT;
16881692
//
16891693

16901694
SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_INT {
1691-
UINT32 type;
1692-
UINT32 nDigits; // digit size depends on run-time decisions...
1693-
UINT32 cbSize;
1694-
SYMCRYPT_MAGIC_FIELD
1695+
UINT32 type;
1696+
_Field_range_( 1, SYMCRYPT_FDEF_UPB_DIGITS ) UINT32 nDigits; // digit size depends on run-time decisions...
1697+
UINT32 cbSize;
16951698

1699+
SYMCRYPT_MAGIC_FIELD
16961700
SYMCRYPT_ASYM_ALIGN union {
16971701
struct {
16981702
UINT32 uint32[SYMCRYPT_ANYSIZE]; // FDEF: array UINT32[nDigits * # uint32 per digit]
@@ -1707,13 +1711,13 @@ SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_INT {
17071711
#define SYMCRYPT_FDEF_SIZEOF_INT_FROM_BITS( _bits ) SYMCRYPT_FDEF_SIZEOF_INT_FROM_DIGITS( SYMCRYPT_FDEF_DIGITS_FROM_BITS( _bits ))
17081712

17091713
SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_DIVISOR {
1710-
UINT32 type;
1711-
UINT32 nDigits; // digit size depends on run-time decisions...
1712-
UINT32 cbSize;
1714+
UINT32 type;
1715+
_Field_range_( 1, SYMCRYPT_FDEF_UPB_DIGITS ) UINT32 nDigits; // digit size depends on run-time decisions...
1716+
UINT32 cbSize;
17131717

1714-
UINT32 nBits; // # bits in divisor
1715-
SYMCRYPT_MAGIC_FIELD
1718+
UINT32 nBits; // # bits in divisor
17161719

1720+
SYMCRYPT_MAGIC_FIELD
17171721
union{
17181722
struct {
17191723
UINT64 W; // approximate inverse of the divisor. Some implementations will use 64 bits, others 32 bits.
@@ -1727,12 +1731,12 @@ SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_DIVISOR {
17271731
#define SYMCRYPT_FDEF_SIZEOF_DIVISOR_FROM_BITS( _bits ) SYMCRYPT_FDEF_SIZEOF_DIVISOR_FROM_DIGITS( SYMCRYPT_FDEF_DIGITS_FROM_BITS( _bits ))
17281732

17291733
SYMCRYPT_ASYM_ALIGN_STRUCT _SYMCRYPT_MODULUS {
1730-
UINT32 type;
1731-
UINT32 nDigits; // digit size depends on run-time decisions...
1732-
UINT32 cbSize; // Size of modulus object
1734+
UINT32 type;
1735+
_Field_range_( 1, SYMCRYPT_FDEF_UPB_DIGITS ) UINT32 nDigits; // digit size depends on run-time decisions...
1736+
UINT32 cbSize; // Size of modulus object
17331737

1734-
UINT32 flags; // The flag the modulus was created with
1735-
UINT32 cbModElement; // size of one modElement
1738+
UINT32 flags; // The flag the modulus was created with
1739+
UINT32 cbModElement; // size of one modElement
17361740

17371741
SYMCRYPT_MAGIC_FIELD
17381742
union{

inc/symcrypt_low_level.h

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ in the current version). This bound is used to ensure that no object sizes and s
124124
have a value of magnitude more than 32 bits. Note that the computed upper bounds are very loose and the
125125
actual values are much smaller.
126126
127-
Functions calls and arithmetic operations with values exceeding this bound will trigger a hard fail on the
128-
calling application. The rationale behind accepting this approach is that executing arithmetic operations
129-
with integers of such magnitude will consume so much CPU time that it will be indistinguishable from
130-
an application hang.
127+
Attempts to create objects larger than this bound will result in NULL being returned. Callers either have
128+
to ensure they do not exceed the bounds, or check that create objects are not NULL before using them. The
129+
rationale behind this approach is to avoid any potential route for malicious inputs to trigger DoS by
130+
taking excessive CPU time which would be indistinguishable from an application hang.
131131
132132
133133
Digit size and radix can vary widely; on some CPU steppings the library might use a digit that contains
@@ -191,7 +191,7 @@ a ModElement object.
191191
// The object will be able to store values up to R^nDigits where R is the digit radix.
192192
// Requirement:
193193
// - 1 <= nDigits <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)
194-
// If the value is outside these bounds the call will trigger a hard fail.
194+
// If the value is outside these bounds it will return NULL
195195
// - cbBuffer >= SymCryptSizeofXxxFromDigits( nDigits )
196196
// - (pbBuffer,cbBuffer) memory must be exclusively used by this object.
197197
// The last requirement ensures that all objects are non-overlapping (except for API functions
@@ -239,8 +239,8 @@ a ModElement object.
239239
// Memory size that is sufficient to store an XXX object with nDigits digits.
240240
// This is a runtime function as the # digits and size of a digit are run-time decision that depend on the CPU stepping.
241241
// Requirement:
242-
// - nDigits <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)
243-
// If the value is outside these bounds the call will trigger a hard fail.
242+
// - 1 <= nDigits <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)
243+
// If the value is outside these bounds the returned value will be 0 indicating failure.
244244
// This function is has the following property:
245245
// SymCryptSizeofXxxFromDigits( a + b ) <= SymCryptSizeofXxxFromDigits( a ) + SymCryptSizeofXxxFromDigits( b )
246246
// for all a and b.
@@ -274,8 +274,9 @@ a ModElement object.
274274
//
275275

276276
// The maximum number of bits in any integer value that the library supports. If the
277-
// caller's input exceed this bound then the result of the application will be
278-
// to hard fail.
277+
// caller's input exceed this bound then the the integer object will not be created.
278+
// The caller either must ensure the bound is not exceeded, or check for NULL before
279+
// using created SymCrypt objects.
279280
// The primary purpose of this limit is to avoid integer overlows in size computations.
280281
// Having a reasonable upper bound avoids all size overflows, even on 32-bit CPUs
281282
#define SYMCRYPT_INT_MAX_BITS ((UINT32)(1 << 20))
@@ -289,14 +290,14 @@ SymCryptDigitsFromBits( UINT32 nBits );
289290
// Remarks:
290291
// If nBits==0 the returned number is 1.
291292
//
293+
// If nBits exceeds SYMCRYPT_INT_MAX_BITS the function will return 0 to indicate an object with
294+
// this many bits is not supported.
295+
//
292296
// This is a run-time decision; the return value can depend on the exact CPU stepping
293297
// the program is running on, or run-time configurations.
294-
// It is always true that
298+
// For a and b in the range 0..SYMCRYPT_INT_MAX_BITS, it is always true that
295299
// SymCryptDigitsFromBits( a + b ) <= SymCryptDigitsFromBits( a ) + SymCryptDigitsFromBits( b )
296300
//
297-
// If nBits exceeds SYMCRYPT_INT_MAX_BITS the function will cause a hard fail
298-
// to the calling application.
299-
//
300301

301302
//========================================================================
302303
// INT objects
@@ -1139,6 +1140,7 @@ SymCryptIntExtendedGcd(
11391140
// - Lcm.nDigits >= Src1.nDigits + Src2.nDigits
11401141
// - InvSrc1ModSrc2.nDigits >= max(Src1.nDigits, Src2.nDigits) // Future work: Make these bounds Src2 and Src1 respectively.
11411142
// - InvSrc2ModSrc1.nDigits >= max(Src1.nDigits, Src2.nDigits)
1143+
// - if piInvSrc2ModSrc1 is not NULL, max( Src1.nDigits, Src2.nDigits ) * 2 <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)
11421144
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_EXTENDED_GCD( max( Src1.nDigits, Src2.nDigits ) )
11431145
//
11441146
// If only one inverse value is needed, it is most efficient to use only InvSrc1ModSrc2.
@@ -1240,10 +1242,11 @@ SymCryptCrtSolve(
12401242
// The number of inputs nCoprimes is public.
12411243
//
12421244
// Requirements:
1243-
// - nCoprimes >= 2
1245+
// - nCoprimes == 2
12441246
// - ppmCoprimes, ppeCrtInverses, and ppeCrtRemainders must be arrays of pointers of exactly nCoprimes elements. All
12451247
// of them non-NULL.
12461248
// - piSolution must be large enough to hold the result modulo the product of all the coprimes.
1249+
// - max( ppmCoprimes[0].nDigits, ppmCoprimes[1].nDigits ) * 2 <= SymCryptDigitsFromBits(SYMCRYPT_INT_MAX_BITS)
12471250
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_CRT_SOLUTION( nDigits ) where nDigits is the maximum number
12481251
// of digits of the input moduli.
12491252
//
@@ -1259,7 +1262,7 @@ SymCryptCreateTrialDivisionContext( UINT32 nDigits );
12591262
// The Trial division context can be used in multiple threads in parallel.
12601263
// The context should be freed with SymCryptFreeTrialDivisionContext after use.
12611264
// A context can be fairly large (100 kB) so freeing it is important.
1262-
// Returns NULL if out of memory.
1265+
// Returns NULL if out of memory or an invalid digit count is provided.
12631266
//
12641267

12651268
VOID
@@ -1365,6 +1368,7 @@ SymCryptIntGenerateRandomPrime(
13651368
// Requirements:
13661369
// - SymCryptIntBitsizeOfValue( piHigh ) <= SymCryptIntBitsizeOfObject(piDst)
13671370
// - piLow > 3
1371+
// - Each public exponent must be greater than 0
13681372
// - 0 <= nPubExp <= SYMCRYPT_RSAKEY_MAX_NUMOF_PUBEXPS
13691373
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_INT_PRIME_GEN( Dst.nDigits )
13701374
//
@@ -1420,7 +1424,7 @@ SymCryptIntToModulus(
14201424
_Out_writes_bytes_( cbScratch ) PBYTE pbScratch,
14211425
SIZE_T cbScratch );
14221426
//
1423-
// Create a modulus from an INT.
1427+
// Create a modulus from an INT.
14241428
// Requirements:
14251429
// - Src != 0
14261430
// - Dst.nDigits == Src.nDigits
@@ -1467,7 +1471,7 @@ SymCryptIntToModElement(
14671471
// Dst = Src mod Mod
14681472
// Requirements:
14691473
// - Dst.nDigits == Mod.nDigits
1470-
// - piSrc.nDigits <= 2 * MOd.nDigits
1474+
// - piSrc.nDigits <= 2 * Mod.nDigits
14711475
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )
14721476
//
14731477
// Note: the input is limited in size to be no more than twice the modulus size (in digits).
@@ -1613,7 +1617,7 @@ SymCryptModSetRandom(
16131617
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( Mod.nDigits )
16141618
//
16151619
// Random value is chosen uniformly from the set of allowed values.
1616-
// By default this function does not return the values 0, 1, or -1.
1620+
// By default this function does not return the values 0, 1, or -1 (see below NOTE for small moduli exception)
16171621
// Flags parameter can signal that these special values are allowed.
16181622
// flags parameter is published.
16191623
//
@@ -1624,8 +1628,19 @@ SymCryptModSetRandom(
16241628
// SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO
16251629
// SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE
16261630
// SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE
1627-
// Specifying ALLOW_ZERO is only valid if ALLOW_ONE is also specified.
1631+
// Specifying ALLOW_ZERO implies ALLOW_ONE, there is no way to allow 0 and disallow 1.
1632+
//
1633+
// NOTE:
1634+
// For very small moduli (1, 2, and 3), not allowing 0, 1, or -1 by default does not make sense because this would
1635+
// exclude all possible values! Instead the default behavior is to allow -1 for these moduli.
1636+
// Modulo 1 => return 0 by default
1637+
// Modulo 2 => return 1 by default
1638+
// may also return 0 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO is specified
1639+
// Modulo 3 => return 2 by default
1640+
// may also return 1 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE is specified, and
1641+
// may also return 0 or 1 if SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO is specified,
16281642
//
1643+
// Callers relying on not having 0, 1, or -1 are required to pass a larger modulus.
16291644

16301645
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ZERO (0x01)
16311646
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE (0x02)
@@ -1758,8 +1773,8 @@ SymCryptModInv(
17581773
//
17591774
// - pmMod: Modulus, must have the SYMCRYPT_FLAG_MODULUS_PRIME and SYMCRYPT_FLAG_DATA_PUBLIC flag set.
17601775
// Non-prime or non-public moduli are currently not supported.
1761-
// - peSrc: Source value, modulu pmMod
1762-
// - peDst: Destination value, mod element modulu pmMod
1776+
// - peSrc: Source value, modulo pmMod
1777+
// - peDst: Destination value, mod element modulo pmMod
17631778
// - flags: SYMCRYPT_FLAG_DATA_PUBLIC signals that peSrc is a public value.
17641779
// - pbScratch/cbScratch: scratch space >= SYMCRYPT_SCRATCH_BYTES_FOR_MODINV( nDigits( pmMod ) )
17651780
//
@@ -1816,7 +1831,7 @@ SymCryptModExp(
18161831

18171832
#define SYMCRYPT_SCRATCH_BYTES_FOR_MODMULTIEXP( _nDigits, _nBases, _nBitsExp ) SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_MODMULTIEXP( _nDigits, _nBases, _nBitsExp )
18181833

1819-
VOID
1834+
SYMCRYPT_ERROR
18201835
SYMCRYPT_CALL
18211836
SymCryptModMultiExp(
18221837
_In_ PCSYMCRYPT_MODULUS pmMod,
@@ -2003,7 +2018,11 @@ SIZE_T
20032018
SYMCRYPT_CALL
20042019
SymCryptRoundUpPow2Sizet( SIZE_T v );
20052020
// Round up to the next power of 2
2006-
2021+
//
2022+
// Requirements:
2023+
// v <= (SIZE_T_MAX / 2) + 1
2024+
// i.e. rounding v up to the next power of 2 fits within SIZE_T, so v is
2025+
// less than or equal to the maximum power of 2 representable in SIZE_T
20072026

20082027

20092028
//=====================================================

lib/IEEE802_11SaeCustom.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,11 @@ SymCrypt802_11SaeCustomInit(
510510
while( notFoundMask != 0 || counter < 40 )
511511
{
512512
counter += 1;
513-
SYMCRYPT_HARD_ASSERT( counter != 0 );
513+
if( counter == 0 )
514+
{
515+
scError = SYMCRYPT_INVALID_ARGUMENT;
516+
goto cleanup;
517+
}
514518

515519
// pwd-seed = Hmac-sha256( MacA || MacB , Password || counter )
516520
SymCryptHmacSha256Init( &hmacState, &hmacSeedKey );
@@ -537,7 +541,10 @@ SymCrypt802_11SaeCustomInit(
537541

538542
// Get the pwd-value into an integer
539543
scError = SymCryptIntSetValue( abValue, sizeof( abValue ), SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, piTmp );
540-
SYMCRYPT_HARD_ASSERT( scError == SYMCRYPT_NO_ERROR );
544+
if( scError != SYMCRYPT_NO_ERROR )
545+
{
546+
goto cleanup;
547+
}
541548

542549
// Check that it is less than P
543550
if( !SymCryptIntIsLessThan( piTmp, SymCryptIntFromModulus( pCurve->FMod ) ) )
@@ -581,7 +588,10 @@ SymCrypt802_11SaeCustomInit(
581588
0,
582589
pbScratch,
583590
cbScratch );
584-
SYMCRYPT_HARD_ASSERT( scError == SYMCRYPT_NO_ERROR );
591+
if( scError != SYMCRYPT_NO_ERROR )
592+
{
593+
goto cleanup;
594+
}
585595

586596
SymCryptEcpointMaskedCopy( pCurve, poPWECandidate, pState->poPWE, solutionMask );
587597
pState->counter |= (BYTE)(counter & solutionMask);

lib/ScsTable.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ SymCryptScsTableSetBuffer(
108108

109109

110110
C_ASSERT( SYMCRYPT_SCSTABLE_INTERLEAVE_SIZE == 16 || SYMCRYPT_SCSTABLE_INTERLEAVE_SIZE == 32 );
111+
// check that an interleave size is exactly 4 words
112+
C_ASSERT( SYMCRYPT_SCSTABLE_INTERLEAVE_SIZE == 4 * sizeof( SYMCRYPT_SCSTABLE_TYPE ) );
111113

112114
VOID
113115
SYMCRYPT_CALL
@@ -209,9 +211,6 @@ SymCryptScsTableLoadC(
209211
SYMCRYPT_ASSERT( cbData == pScsTable->elementSize );
210212
UNREFERENCED_PARAMETER( cbData );
211213

212-
// check that an interleave size is exactly 4 words
213-
SYMCRYPT_HARD_ASSERT(interleaveSize == 4 * sizeof( SYMCRYPT_SCSTABLE_TYPE ));
214-
215214
#if SYMCRYPT_SCSTABLE_USE64
216215
#define SCS_MASK_EQUAL32( _a, _b ) ( ~(UINT64) ((INT64) ((UINT64)0 - (_a ^ _b)) >> 32 ) )
217216
#else

0 commit comments

Comments
 (0)