summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-23 21:08:34 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-23 21:08:34 +0700
commit29a112bef25c63c03da142e665f027f00bd496b0 (patch)
treef5e2d730f84fc9f720a1e20b6b381c2bdefbee71
parentRound 4 modifications to HQC + removed some redundancy (diff)
downloadBouncyCastle.NET-ed25519-29a112bef25c63c03da142e665f027f00bd496b0.tar.xz
Use FixedTimeEquals
-rw-r--r--crypto/src/cmp/CertificateStatus.cs2
-rw-r--r--crypto/src/cmp/ProtectedPkiMessage.cs2
-rw-r--r--crypto/src/cms/SignerInformation.cs2
-rw-r--r--crypto/src/crypto/agreement/SM2KeyExchange.cs2
-rw-r--r--crypto/src/crypto/engines/DesEdeWrapEngine.cs2
-rw-r--r--crypto/src/crypto/engines/IesEngine.cs2
-rw-r--r--crypto/src/crypto/engines/RC2WrapEngine.cs2
-rw-r--r--crypto/src/crypto/engines/RFC3394WrapEngine.cs2
-rw-r--r--crypto/src/crypto/modes/CcmBlockCipher.cs4
-rw-r--r--crypto/src/crypto/modes/ChaCha20Poly1305.cs4
-rw-r--r--crypto/src/crypto/modes/GCMBlockCipher.cs4
-rw-r--r--crypto/src/crypto/modes/GcmSivBlockCipher.cs2
-rw-r--r--crypto/src/crypto/modes/KCcmBlockCipher.cs4
-rw-r--r--crypto/src/crypto/modes/OCBBlockCipher.cs4
-rw-r--r--crypto/src/crypto/signers/GenericSigner.cs2
-rw-r--r--crypto/src/crypto/signers/RsaDigestSigner.cs2
-rw-r--r--crypto/src/crypto/signers/X931Signer.cs2
-rw-r--r--crypto/src/openpgp/PgpEncryptedData.cs2
-rw-r--r--crypto/src/pkcs/Pkcs12Store.cs4
-rw-r--r--crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs2
-rw-r--r--crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs2
-rw-r--r--crypto/src/security/JksStore.cs4
-rw-r--r--crypto/src/tls/DtlsClientProtocol.cs2
-rw-r--r--crypto/src/tls/DtlsProtocol.cs2
-rw-r--r--crypto/src/tls/DtlsServerProtocol.cs2
-rw-r--r--crypto/src/tls/DtlsVerifier.cs4
-rw-r--r--crypto/src/tls/PskIdentity.cs2
-rw-r--r--crypto/src/tls/TlsClientProtocol.cs2
-rw-r--r--crypto/src/tls/TlsProtocol.cs4
-rw-r--r--crypto/src/tls/TlsServerProtocol.cs2
-rw-r--r--crypto/src/tls/TlsUtilities.cs2
-rw-r--r--crypto/src/tsp/TSPUtil.cs2
-rw-r--r--crypto/src/tsp/TimeStampResponse.cs2
-rw-r--r--crypto/src/tsp/TimeStampToken.cs2
-rw-r--r--crypto/src/util/Arrays.cs71
-rw-r--r--crypto/test/src/tls/test/MockSrpTlsServer.cs2
36 files changed, 88 insertions, 71 deletions
diff --git a/crypto/src/cmp/CertificateStatus.cs b/crypto/src/cmp/CertificateStatus.cs
index e697f73bc..53227d062 100644
--- a/crypto/src/cmp/CertificateStatus.cs
+++ b/crypto/src/cmp/CertificateStatus.cs
@@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Cmp
 
             byte[] digest = DigestUtilities.CalculateDigest(digAlg.Algorithm, cert.GetEncoded());
 
-            return Arrays.ConstantTimeAreEqual(certStatus.CertHash.GetOctets(), digest);
+            return Arrays.FixedTimeEquals(certStatus.CertHash.GetOctets(), digest);
         }
     }
 }
diff --git a/crypto/src/cmp/ProtectedPkiMessage.cs b/crypto/src/cmp/ProtectedPkiMessage.cs
index 6304b5200..8c9a4b152 100644
--- a/crypto/src/cmp/ProtectedPkiMessage.cs
+++ b/crypto/src/cmp/ProtectedPkiMessage.cs
@@ -116,7 +116,7 @@ namespace Org.BouncyCastle.Cmp
 
             IBlockResult result = Process(pkMacBuilder.Build(password).CreateCalculator());
 
-            return Arrays.ConstantTimeAreEqual(result.Collect(), m_pkiMessage.Protection.GetBytes());
+            return Arrays.FixedTimeEquals(result.Collect(), m_pkiMessage.Protection.GetBytes());
         }
 
         private TResult Process<TResult>(IStreamCalculator<TResult> streamCalculator)
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs
index bb74c86cc..84256d9f8 100644
--- a/crypto/src/cms/SignerInformation.cs
+++ b/crypto/src/cms/SignerInformation.cs
@@ -595,7 +595,7 @@ namespace Org.BouncyCastle.Cms
 
 					byte[] sigHash = digInfo.GetDigest();
 
-					return Arrays.ConstantTimeAreEqual(digest, sigHash);
+					return Arrays.FixedTimeEquals(digest, sigHash);
 				}
 				else if (algorithm.Equals("DSA"))
 				{
diff --git a/crypto/src/crypto/agreement/SM2KeyExchange.cs b/crypto/src/crypto/agreement/SM2KeyExchange.cs
index 986d98421..5db156f9c 100644
--- a/crypto/src/crypto/agreement/SM2KeyExchange.cs
+++ b/crypto/src/crypto/agreement/SM2KeyExchange.cs
@@ -127,7 +127,7 @@ namespace Org.BouncyCastle.Crypto.Agreement
 
                 byte[] s1 = S1(mDigest, U, inner);
 
-                if (!Arrays.ConstantTimeAreEqual(s1, confirmationTag))
+                if (!Arrays.FixedTimeEquals(s1, confirmationTag))
                     throw new InvalidOperationException("confirmation tag mismatch");
 
                 return new byte[][] { rv, S2(mDigest, U, inner)};
diff --git a/crypto/src/crypto/engines/DesEdeWrapEngine.cs b/crypto/src/crypto/engines/DesEdeWrapEngine.cs
index e05f9f555..c1f93eef9 100644
--- a/crypto/src/crypto/engines/DesEdeWrapEngine.cs
+++ b/crypto/src/crypto/engines/DesEdeWrapEngine.cs
@@ -305,7 +305,7 @@ namespace Org.BouncyCastle.Crypto.Engines
             byte[]	key,
             byte[]	checksum)
         {
-			return Arrays.ConstantTimeAreEqual(CalculateCmsKeyChecksum(key), checksum);
+			return Arrays.FixedTimeEquals(CalculateCmsKeyChecksum(key), checksum);
         }
 
 		private static byte[] reverse(byte[] bs)
diff --git a/crypto/src/crypto/engines/IesEngine.cs b/crypto/src/crypto/engines/IesEngine.cs
index 307cc7a80..33fc4141b 100644
--- a/crypto/src/crypto/engines/IesEngine.cs
+++ b/crypto/src/crypto/engines/IesEngine.cs
@@ -139,7 +139,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 
             byte[] T1 = Arrays.CopyOfRange(in_enc, inOff, inOff + macBuf.Length);
 
-            if (!Arrays.ConstantTimeAreEqual(T1, macBuf))
+            if (!Arrays.FixedTimeEquals(T1, macBuf))
                 throw (new InvalidCipherTextException("Invalid MAC."));
 
             return M;
diff --git a/crypto/src/crypto/engines/RC2WrapEngine.cs b/crypto/src/crypto/engines/RC2WrapEngine.cs
index 91ac7ded2..bc50f0db4 100644
--- a/crypto/src/crypto/engines/RC2WrapEngine.cs
+++ b/crypto/src/crypto/engines/RC2WrapEngine.cs
@@ -361,7 +361,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 			byte[]	key,
 			byte[]	checksum)
 		{
-			return Arrays.ConstantTimeAreEqual(CalculateCmsKeyChecksum(key), checksum);
+			return Arrays.FixedTimeEquals(CalculateCmsKeyChecksum(key), checksum);
 		}
 	}
 }
diff --git a/crypto/src/crypto/engines/RFC3394WrapEngine.cs b/crypto/src/crypto/engines/RFC3394WrapEngine.cs
index 4bb0e2114..e68e45365 100644
--- a/crypto/src/crypto/engines/RFC3394WrapEngine.cs
+++ b/crypto/src/crypto/engines/RFC3394WrapEngine.cs
@@ -169,7 +169,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 				}
 			}
 
-			if (!Arrays.ConstantTimeAreEqual(a, iv))
+			if (!Arrays.FixedTimeEquals(a, iv))
 				throw new InvalidCipherTextException("checksum failed");
 
 			return block;
diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs
index 3569ac2b7..e002c1f71 100644
--- a/crypto/src/crypto/modes/CcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/CcmBlockCipher.cs
@@ -345,7 +345,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 CalculateMac(output, outOff, outputLen, calculatedMacBlock);
 
-                if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock))
+                if (!Arrays.FixedTimeEquals(macBlock, calculatedMacBlock))
                     throw new InvalidCipherTextException("mac check in CCM failed");
             }
 
@@ -439,7 +439,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 CalculateMac(output[..outputLen], calculatedMacBlock);
 
-                if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock))
+                if (!Arrays.FixedTimeEquals(macBlock, calculatedMacBlock))
                     throw new InvalidCipherTextException("mac check in CCM failed");
             }
 
diff --git a/crypto/src/crypto/modes/ChaCha20Poly1305.cs b/crypto/src/crypto/modes/ChaCha20Poly1305.cs
index 2fce81e22..4b0ad0cca 100644
--- a/crypto/src/crypto/modes/ChaCha20Poly1305.cs
+++ b/crypto/src/crypto/modes/ChaCha20Poly1305.cs
@@ -588,7 +588,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 FinishData(State.DecFinal);
 
-                if (!Arrays.ConstantTimeAreEqual(MacSize, mMac, 0, mBuf, resultLen))
+                if (!Arrays.FixedTimeEquals(MacSize, mMac, 0, mBuf, resultLen))
                     throw new InvalidCipherTextException("mac check in ChaCha20Poly1305 failed");
 
                 break;
@@ -648,7 +648,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 FinishData(State.DecFinal);
 
-                if (!Arrays.ConstantTimeAreEqual(MacSize, mMac, 0, mBuf, resultLen))
+                if (!Arrays.FixedTimeEquals(MacSize, mMac, 0, mBuf, resultLen))
                     throw new InvalidCipherTextException("mac check in ChaCha20Poly1305 failed");
 
                 break;
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index ce5faf91f..f75235cf2 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -730,7 +730,7 @@ namespace Org.BouncyCastle.Crypto.Modes
                 // Retrieve the T value from the message and compare to calculated one
                 byte[] msgMac = new byte[macSize];
                 Array.Copy(bufBlock, extra, msgMac, 0, macSize);
-                if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac))
+                if (!Arrays.FixedTimeEquals(this.macBlock, msgMac))
                     throw new InvalidCipherTextException("mac check in GCM failed");
             }
 
@@ -842,7 +842,7 @@ namespace Org.BouncyCastle.Crypto.Modes
                 // Retrieve the T value from the message and compare to calculated one
                 Span<byte> msgMac = stackalloc byte[macSize];
                 bufBlock.AsSpan(extra, macSize).CopyTo(msgMac);
-                if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac))
+                if (!Arrays.FixedTimeEquals(this.macBlock, msgMac))
                     throw new InvalidCipherTextException("mac check in GCM failed");
             }
 
diff --git a/crypto/src/crypto/modes/GcmSivBlockCipher.cs b/crypto/src/crypto/modes/GcmSivBlockCipher.cs
index 14f908da3..7246b59c1 100644
--- a/crypto/src/crypto/modes/GcmSivBlockCipher.cs
+++ b/crypto/src/crypto/modes/GcmSivBlockCipher.cs
@@ -670,7 +670,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
             /* Derive and check the tag */
             byte[] myTag = CalculateTag();
-            if (!Arrays.ConstantTimeAreEqual(myTag, myExpected))
+            if (!Arrays.FixedTimeEquals(myTag, myExpected))
             {
                 Reset();
                 throw new InvalidCipherTextException("mac check failed");
diff --git a/crypto/src/crypto/modes/KCcmBlockCipher.cs b/crypto/src/crypto/modes/KCcmBlockCipher.cs
index 5fb8d77c6..c13c41543 100644
--- a/crypto/src/crypto/modes/KCcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/KCcmBlockCipher.cs
@@ -354,7 +354,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 Array.Copy(buffer, 0, calculatedMac, 0, macSize);
 
-                if (!Arrays.ConstantTimeAreEqual(mac, calculatedMac))
+                if (!Arrays.FixedTimeEquals(mac, calculatedMac))
                 {
                     throw new InvalidCipherTextException("mac check failed");
                 }
@@ -465,7 +465,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 calculatedMac.CopyFrom(buffer);
 
-                if (!Arrays.ConstantTimeAreEqual(mac.AsSpan(0, macSize), calculatedMac))
+                if (!Arrays.FixedTimeEquals(mac.AsSpan(0, macSize), calculatedMac))
                     throw new InvalidCipherTextException("mac check failed");
 
                 Reset();
diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs
index e67b4e9af..9ae60805e 100644
--- a/crypto/src/crypto/modes/OCBBlockCipher.cs
+++ b/crypto/src/crypto/modes/OCBBlockCipher.cs
@@ -439,7 +439,7 @@ namespace Org.BouncyCastle.Crypto.Modes
             else
             {
                 // Compare the tag from the message with the calculated one
-                if (!Arrays.ConstantTimeAreEqual(macBlock, tag))
+                if (!Arrays.FixedTimeEquals(macBlock, tag))
                     throw new InvalidCipherTextException("mac check in OCB failed");
             }
 
@@ -529,7 +529,7 @@ namespace Org.BouncyCastle.Crypto.Modes
             else
             {
                 // Compare the tag from the message with the calculated one
-                if (!Arrays.ConstantTimeAreEqual(macBlock, tag))
+                if (!Arrays.FixedTimeEquals(macBlock, tag))
                     throw new InvalidCipherTextException("mac check in OCB failed");
             }
 
diff --git a/crypto/src/crypto/signers/GenericSigner.cs b/crypto/src/crypto/signers/GenericSigner.cs
index 2a416eeb7..36a9cc9a5 100644
--- a/crypto/src/crypto/signers/GenericSigner.cs
+++ b/crypto/src/crypto/signers/GenericSigner.cs
@@ -109,7 +109,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     sig = tmp;
                 }
 
-                return Arrays.ConstantTimeAreEqual(sig, hash);
+                return Arrays.FixedTimeEquals(sig, hash);
             }
             catch (Exception)
             {
diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs
index 296e4b016..77d9b9ac3 100644
--- a/crypto/src/crypto/signers/RsaDigestSigner.cs
+++ b/crypto/src/crypto/signers/RsaDigestSigner.cs
@@ -176,7 +176,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (sig.Length == expected.Length)
             {
-                return Arrays.ConstantTimeAreEqual(sig, expected);
+                return Arrays.FixedTimeEquals(sig, expected);
             }
             else if (sig.Length == expected.Length - 2)  // NULL left out
             {
diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs
index e40ad88a7..9db4e1642 100644
--- a/crypto/src/crypto/signers/X931Signer.cs
+++ b/crypto/src/crypto/signers/X931Signer.cs
@@ -184,7 +184,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f);
 #endif
 
-            bool rv = Arrays.ConstantTimeAreEqual(block, fBlock);
+            bool rv = Arrays.FixedTimeEquals(block, fBlock);
 
             Arrays.Fill(block, 0x00);
             Arrays.Fill<byte>(fBlock, 0x00);
diff --git a/crypto/src/openpgp/PgpEncryptedData.cs b/crypto/src/openpgp/PgpEncryptedData.cs
index bad4cb8cd..0a8bd6c42 100644
--- a/crypto/src/openpgp/PgpEncryptedData.cs
+++ b/crypto/src/openpgp/PgpEncryptedData.cs
@@ -176,7 +176,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			byte[] streamDigest = new byte[digest.Length];
 			Array.Copy(lookAhead, 2, streamDigest, 0, streamDigest.Length);
 
-			return Arrays.ConstantTimeAreEqual(digest, streamDigest);
+			return Arrays.FixedTimeEquals(digest, streamDigest);
         }
     }
 }
diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs
index bf7e68363..9cb81a412 100644
--- a/crypto/src/pkcs/Pkcs12Store.cs
+++ b/crypto/src/pkcs/Pkcs12Store.cs
@@ -202,7 +202,7 @@ namespace Org.BouncyCastle.Pkcs
                 byte[] mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, false, data);
                 byte[] dig = dInfo.GetDigest();
 
-                if (!Arrays.ConstantTimeAreEqual(mac, dig))
+                if (!Arrays.FixedTimeEquals(mac, dig))
                 {
                     if (password.Length > 0)
                         throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
@@ -210,7 +210,7 @@ namespace Org.BouncyCastle.Pkcs
                     // Try with incorrect zero length password
                     mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, true, data);
 
-                    if (!Arrays.ConstantTimeAreEqual(mac, dig))
+                    if (!Arrays.FixedTimeEquals(mac, dig))
                         throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
 
                     wrongPkcs12Zero = true;
diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs
index e30115a95..132bd73b3 100644
--- a/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs
+++ b/crypto/src/pqc/crypto/crystals/kyber/KyberEngine.cs
@@ -148,7 +148,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber
 
             m_indCpa.Encrypt(cmp, Arrays.CopyOf(buf, SymBytes), pk, Arrays.CopyOfRange(kr, SymBytes, kr.Length));
 
-            bool fail = !Arrays.ConstantTimeAreEqual(cipherText, cmp);
+            bool fail = !Arrays.FixedTimeEquals(cipherText, cmp);
             
             Symmetric.Hash_h(kr, cipherText, SymBytes);
 
diff --git a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
index f8d0970af..e8c5d07e5 100644
--- a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
@@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
 
         internal bool MatchesT1(byte[] sig)
         {
-            return Arrays.ConstantTimeAreEqual(T1, sig);
+            return Arrays.FixedTimeEquals(T1, sig);
         }
 
         public byte[] GetI()
diff --git a/crypto/src/security/JksStore.cs b/crypto/src/security/JksStore.cs
index 9f4aced96..c5ef92a70 100644
--- a/crypto/src/security/JksStore.cs
+++ b/crypto/src/security/JksStore.cs
@@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Security
             // integrity check
             byte[] checksum = GetKeyChecksum(digest, password, pkcs8Key);
 
-            if (!Arrays.ConstantTimeAreEqual(20, encryptedData, pkcs8Len + 20, checksum, 0))
+            if (!Arrays.FixedTimeEquals(20, encryptedData, pkcs8Len + 20, checksum, 0))
                 throw new IOException("cannot recover key");
 
             return PrivateKeyFactory.CreateKey(pkcs8Key);
@@ -393,7 +393,7 @@ namespace Org.BouncyCastle.Security
             {
                 byte[] checksum = CalculateChecksum(password, rawStore, 0, checksumPos);
 
-                if (!Arrays.ConstantTimeAreEqual(20, checksum, 0, rawStore, checksumPos))
+                if (!Arrays.FixedTimeEquals(20, checksum, 0, rawStore, checksumPos))
                 {
                     Array.Clear(rawStore, 0, rawStore.Length);
                     throw new IOException("password incorrect or store tampered with");
diff --git a/crypto/src/tls/DtlsClientProtocol.cs b/crypto/src/tls/DtlsClientProtocol.cs
index 0a4a711ae..92478dc46 100644
--- a/crypto/src/tls/DtlsClientProtocol.cs
+++ b/crypto/src/tls/DtlsClientProtocol.cs
@@ -805,7 +805,7 @@ namespace Org.BouncyCastle.Tls
                      */
                     securityParameters.m_secureRenegotiation = true;
 
-                    if (!Arrays.ConstantTimeAreEqual(renegExtData,
+                    if (!Arrays.FixedTimeEquals(renegExtData,
                         TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                     {
                         throw new TlsFatalAlert(AlertDescription.handshake_failure);
diff --git a/crypto/src/tls/DtlsProtocol.cs b/crypto/src/tls/DtlsProtocol.cs
index 3d72bca9f..745535148 100644
--- a/crypto/src/tls/DtlsProtocol.cs
+++ b/crypto/src/tls/DtlsProtocol.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Tls
 
             TlsProtocol.AssertEmpty(buf);
 
-            if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
+            if (!Arrays.FixedTimeEquals(expected_verify_data, verify_data))
                 throw new TlsFatalAlert(AlertDescription.handshake_failure);
         }
 
diff --git a/crypto/src/tls/DtlsServerProtocol.cs b/crypto/src/tls/DtlsServerProtocol.cs
index 5edd5595e..43d4e5539 100644
--- a/crypto/src/tls/DtlsServerProtocol.cs
+++ b/crypto/src/tls/DtlsServerProtocol.cs
@@ -769,7 +769,7 @@ namespace Org.BouncyCastle.Tls
                      */
                     securityParameters.m_secureRenegotiation = true;
 
-                    if (!Arrays.ConstantTimeAreEqual(renegExtData,
+                    if (!Arrays.FixedTimeEquals(renegExtData,
                         TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                     {
                         throw new TlsFatalAlert(AlertDescription.handshake_failure);
diff --git a/crypto/src/tls/DtlsVerifier.cs b/crypto/src/tls/DtlsVerifier.cs
index edadeae70..e691685e6 100644
--- a/crypto/src/tls/DtlsVerifier.cs
+++ b/crypto/src/tls/DtlsVerifier.cs
@@ -57,14 +57,14 @@ namespace Org.BouncyCastle.Tls
                         //}
                         //case 1:
                         //{
-                        //    if (Arrays.ConstantTimeAreEqual(expectedCookie, request.ClientHello.Cookie))
+                        //    if (Arrays.FixedTimeEquals(expectedCookie, request.ClientHello.Cookie))
                         //        return request;
 
                         //    break;
                         //}
                         //}
 
-                        if (Arrays.ConstantTimeAreEqual(expectedCookie, request.ClientHello.Cookie))
+                        if (Arrays.FixedTimeEquals(expectedCookie, request.ClientHello.Cookie))
                             return request;
 
                         DtlsReliableHandshake.SendHelloVerifyRequest(sender, request.RecordSeq, expectedCookie);
diff --git a/crypto/src/tls/PskIdentity.cs b/crypto/src/tls/PskIdentity.cs
index 1887d0af4..2d4a0b0c7 100644
--- a/crypto/src/tls/PskIdentity.cs
+++ b/crypto/src/tls/PskIdentity.cs
@@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Tls
                 return false;
 
             return this.m_obfuscatedTicketAge == that.m_obfuscatedTicketAge
-                && Arrays.ConstantTimeAreEqual(this.m_identity, that.m_identity);
+                && Arrays.FixedTimeEquals(this.m_identity, that.m_identity);
         }
 
         public override int GetHashCode()
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index b7295bcc5..ec1cd28d5 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -1211,7 +1211,7 @@ namespace Org.BouncyCastle.Tls
                      */
                     securityParameters.m_secureRenegotiation = true;
 
-                    if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
+                    if (!Arrays.FixedTimeEquals(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                         throw new TlsFatalAlert(AlertDescription.handshake_failure);
                 }
             }
diff --git a/crypto/src/tls/TlsProtocol.cs b/crypto/src/tls/TlsProtocol.cs
index 437a51447..16bc1385e 100644
--- a/crypto/src/tls/TlsProtocol.cs
+++ b/crypto/src/tls/TlsProtocol.cs
@@ -1517,7 +1517,7 @@ namespace Org.BouncyCastle.Tls
             /*
              * Compare both checksums.
              */
-            if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
+            if (!Arrays.FixedTimeEquals(expected_verify_data, verify_data))
             {
                 /*
                  * Wrong checksum in the finished message.
@@ -1557,7 +1557,7 @@ namespace Org.BouncyCastle.Tls
             /*
              * Compare both checksums.
              */
-            if (!Arrays.ConstantTimeAreEqual(expected_verify_data, verify_data))
+            if (!Arrays.FixedTimeEquals(expected_verify_data, verify_data))
             {
                 /*
                  * Wrong checksum in the finished message.
diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs
index bf4b9119a..72c1b2ea5 100644
--- a/crypto/src/tls/TlsServerProtocol.cs
+++ b/crypto/src/tls/TlsServerProtocol.cs
@@ -512,7 +512,7 @@ namespace Org.BouncyCastle.Tls
                      */
                     securityParameters.m_secureRenegotiation = true;
 
-                    if (!Arrays.ConstantTimeAreEqual(clientRenegExtData,
+                    if (!Arrays.FixedTimeEquals(clientRenegExtData,
                         CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                     {
                         throw new TlsFatalAlert(AlertDescription.handshake_failure);
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index e1a8ead58..424fca133 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -5630,7 +5630,7 @@ namespace Org.BouncyCastle.Tls
                             byte[] calculatedBinder = CalculatePskBinder(crypto, isExternalPsk, pskCryptoHashAlgorithm,
                                 earlySecret, transcriptHash);
 
-                            if (Arrays.ConstantTimeAreEqual(calculatedBinder, binder))
+                            if (Arrays.FixedTimeEquals(calculatedBinder, binder))
                                 return new OfferedPsks.SelectedConfig(index, psk, pskKeyExchangeModes, earlySecret);
                         }
                     }
diff --git a/crypto/src/tsp/TSPUtil.cs b/crypto/src/tsp/TSPUtil.cs
index 1ba289ae6..6f1d07b0a 100644
--- a/crypto/src/tsp/TSPUtil.cs
+++ b/crypto/src/tsp/TSPUtil.cs
@@ -99,7 +99,7 @@ namespace Org.BouncyCastle.Tsp
 								GetDigestAlgName(tstInfo.MessageImprintAlgOid),
 							    signerInfo.GetSignature());
 
-							if (!Arrays.ConstantTimeAreEqual(expectedDigest, tstInfo.GetMessageImprintDigest()))
+							if (!Arrays.FixedTimeEquals(expectedDigest, tstInfo.GetMessageImprintDigest()))
 								throw new TspValidationException("Incorrect digest in message imprint");
 
 							timestamps.Add(timeStampToken);
diff --git a/crypto/src/tsp/TimeStampResponse.cs b/crypto/src/tsp/TimeStampResponse.cs
index 069521111..702194911 100644
--- a/crypto/src/tsp/TimeStampResponse.cs
+++ b/crypto/src/tsp/TimeStampResponse.cs
@@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Tsp
 					throw new TspValidationException("time stamp token found in failed request.");
 				}
 
-				if (!Arrays.ConstantTimeAreEqual(request.GetMessageImprintDigest(), tstInfo.GetMessageImprintDigest()))
+				if (!Arrays.FixedTimeEquals(request.GetMessageImprintDigest(), tstInfo.GetMessageImprintDigest()))
 				{
 					throw new TspValidationException("response for different message imprint digest.");
 				}
diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs
index 93b372720..f2f86da67 100644
--- a/crypto/src/tsp/TimeStampToken.cs
+++ b/crypto/src/tsp/TimeStampToken.cs
@@ -161,7 +161,7 @@ namespace Org.BouncyCastle.Tsp
 				byte[] hash = DigestUtilities.CalculateDigest(
 					certID.GetHashAlgorithmName(), cert.GetEncoded());
 
-				if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash))
+				if (!Arrays.FixedTimeEquals(certID.GetCertHash(), hash))
 					throw new TspValidationException("certificate hash does not match certID hash.");
 
 				if (certID.IssuerSerial != null)
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
 
diff --git a/crypto/test/src/tls/test/MockSrpTlsServer.cs b/crypto/test/src/tls/test/MockSrpTlsServer.cs
index 287b32219..1354214c8 100644
--- a/crypto/test/src/tls/test/MockSrpTlsServer.cs
+++ b/crypto/test/src/tls/test/MockSrpTlsServer.cs
@@ -146,7 +146,7 @@ namespace Org.BouncyCastle.Tls.Tests
 
             public TlsSrpLoginParameters GetLoginParameters(byte[] identity)
             {
-                if (Arrays.ConstantTimeAreEqual(TEST_IDENTITY, identity))
+                if (Arrays.FixedTimeEquals(TEST_IDENTITY, identity))
                 {
                     Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator();
                     verifierGenerator.Init(TEST_GROUP.N, TEST_GROUP.G, new Sha1Digest());