@@ -124,10 +124,10 @@ in the current version). This bound is used to ensure that no object sizes and s
124124have a value of magnitude more than 32 bits. Note that the computed upper bounds are very loose and the
125125actual 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
133133Digit 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
12651268VOID
@@ -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
18201835SYMCRYPT_CALL
18211836SymCryptModMultiExp (
18221837 _In_ PCSYMCRYPT_MODULUS pmMod ,
@@ -2003,7 +2018,11 @@ SIZE_T
20032018SYMCRYPT_CALL
20042019SymCryptRoundUpPow2Sizet ( 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//=====================================================
0 commit comments