diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-11-23 21:08:34 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-11-23 21:08:34 +0700 |
commit | 29a112bef25c63c03da142e665f027f00bd496b0 (patch) | |
tree | f5e2d730f84fc9f720a1e20b6b381c2bdefbee71 | |
parent | Round 4 modifications to HQC + removed some redundancy (diff) | |
download | BouncyCastle.NET-ed25519-29a112bef25c63c03da142e665f027f00bd496b0.tar.xz |
Use FixedTimeEquals
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()); |