summary refs log tree commit diff
path: root/crypto/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/util')
-rw-r--r--crypto/src/util/Arrays.cs71
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