diff options
Diffstat (limited to 'crypto/src/util/Arrays.cs')
-rw-r--r-- | crypto/src/util/Arrays.cs | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index bd2a4faea..41e3c3195 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -1,4 +1,8 @@ using System; +using System.Runtime.CompilerServices; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER +using System.Security.Cryptography; +#endif using System.Text; using Org.BouncyCastle.Math; @@ -93,34 +97,46 @@ namespace Org.BouncyCastle.Utilities return true; } - /// <summary> - /// A constant time equals comparison - does not terminate early if - /// test will fail. - /// </summary> - /// <param name="a">first array</param> - /// <param name="b">second array</param> - /// <returns>true if arrays equal, false otherwise.</returns> + [Obsolete("Use 'FixedTimeEquals' instead")] public static bool ConstantTimeAreEqual(byte[] a, byte[] b) { + return FixedTimeEquals(a, b); + } + + [Obsolete("Use 'FixedTimeEquals' instead")] + public static bool ConstantTimeAreEqual(int len, byte[] a, int aOff, byte[] b, int bOff) + { + return FixedTimeEquals(len, a, aOff, b, bOff); + } + +#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER) + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] +#endif + public static bool FixedTimeEquals(byte[] a, byte[] b) + { if (null == a || null == b) return false; - if (a == b) - return true; - int len = System.Math.Min(a.Length, b.Length); - int nonEqual = a.Length ^ b.Length; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return CryptographicOperations.FixedTimeEquals(a, b); +#else + int len = a.Length; + if (len != b.Length) + return false; + + int d = 0; for (int i = 0; i < len; ++i) { - nonEqual |= (a[i] ^ b[i]); - } - for (int i = len; i < b.Length; ++i) - { - nonEqual |= (b[i] ^ ~b[i]); + d |= a[i] ^ b[i]; } - return 0 == nonEqual; + return 0 == d; +#endif } - public static bool ConstantTimeAreEqual(int len, byte[] a, int aOff, byte[] b, int bOff) +#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER) + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] +#endif + public static bool FixedTimeEquals(int len, byte[] a, int aOff, byte[] b, int bOff) { if (null == a) throw new ArgumentNullException("a"); @@ -133,27 +149,28 @@ namespace Org.BouncyCastle.Utilities if (bOff > (b.Length - len)) throw new IndexOutOfRangeException("'bOff' value invalid for specified length"); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return CryptographicOperations.FixedTimeEquals(a.AsSpan(aOff, len), b.AsSpan(bOff, len)); +#else int d = 0; for (int i = 0; i < len; ++i) { d |= a[aOff + i] ^ b[bOff + i]; } return 0 == d; +#endif } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + [Obsolete("Use 'FixedTimeEquals' instead")] public static bool ConstantTimeAreEqual(Span<byte> a, Span<byte> b) { - if (a.Length != b.Length) - throw new ArgumentException("Spans to compare must have equal length"); - - int d = 0; - for (int i = 0, count = a.Length; i < count; ++i) - { - d |= a[i] ^ b[i]; - } - return 0 == d; + return CryptographicOperations.FixedTimeEquals(a, b); + } + public static bool FixedTimeEquals(ReadOnlySpan<byte> a, ReadOnlySpan<byte> b) + { + return CryptographicOperations.FixedTimeEquals(a, b); } #endif |