diff --git a/Directory.Packages.props b/Directory.Packages.props index 581c71af..c0b25826 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,6 +10,14 @@ a package must only depend on Microsoft.Extensions.* packages within the [10.0.0,11.0.0) range). --> + + + + + - - - - diff --git a/shared/OpenIddict.Extensions/OpenIddictPolyfills.cs b/shared/OpenIddict.Extensions/OpenIddictPolyfills.cs index abe947f2..f778d16b 100644 --- a/shared/OpenIddict.Extensions/OpenIddictPolyfills.cs +++ b/shared/OpenIddict.Extensions/OpenIddictPolyfills.cs @@ -45,6 +45,60 @@ internal static class OpenIddictPolyfills #endif } + extension(CryptographicOperations) + { +#if !NET + /// + /// Determine the equality of two byte sequences in an amount of time which depends on + /// the length of the sequences, but not the values. + /// + /// The first buffer to compare. + /// The second buffer to compare. + /// + /// true if and have the same + /// values for and the same contents, false + /// otherwise. + /// + /// + /// This method compares two buffers' contents for equality in a manner which does not + /// leak timing information, making it ideal for use within cryptographic routines. + /// This method will short-circuit and return false only if + /// and have different lengths. + /// + /// Fixed-time behavior is guaranteed in all other cases, including if + /// and reference the same address. + /// + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] + public static bool FixedTimeEquals(ReadOnlySpan left, ReadOnlySpan right) + { + // Note: the logic used here is directly taken from the official implementation of + // the CryptographicOperations.FixedTimeEquals() method introduced in .NET Core 2.1. + // + // See https://github.com/dotnet/corefx/pull/27103 for more information. + + // Note: these null checks can be theoretically considered as early checks + // (which would defeat the purpose of a time-constant comparison method), + // but the expected string length is the only information an attacker + // could get at this stage, which is not critical where this method is used. + + if (left.Length != right.Length) + { + return false; + } + + var length = left.Length; + var accumulator = 0; + + for (var index = 0; index < length; index++) + { + accumulator |= left[index] - right[index]; + } + + return accumulator is 0; + } +#endif + } + extension(HMACSHA256) { #if !NET @@ -329,57 +383,3 @@ internal static class OpenIddictPolyfills_SHA512 #endif } } - -#if !NET -internal static class CryptographicOperations -{ - /// - /// Determine the equality of two byte sequences in an amount of time which depends on - /// the length of the sequences, but not the values. - /// - /// The first buffer to compare. - /// The second buffer to compare. - /// - /// true if and have the same - /// values for and the same contents, false - /// otherwise. - /// - /// - /// This method compares two buffers' contents for equality in a manner which does not - /// leak timing information, making it ideal for use within cryptographic routines. - /// This method will short-circuit and return false only if - /// and have different lengths. - /// - /// Fixed-time behavior is guaranteed in all other cases, including if - /// and reference the same address. - /// - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] - public static bool FixedTimeEquals(ReadOnlySpan left, ReadOnlySpan right) - { - // Note: the logic used here is directly taken from the official implementation of - // the CryptographicOperations.FixedTimeEquals() method introduced in .NET Core 2.1. - // - // See https://github.com/dotnet/corefx/pull/27103 for more information. - - // Note: these null checks can be theoretically considered as early checks - // (which would defeat the purpose of a time-constant comparison method), - // but the expected string length is the only information an attacker - // could get at this stage, which is not critical where this method is used. - - if (left.Length != right.Length) - { - return false; - } - - var length = left.Length; - var accumulator = 0; - - for (var index = 0; index < length; index++) - { - accumulator |= left[index] - right[index]; - } - - return accumulator is 0; - } -} -#endif