diff options
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/crypto/tls/AbstractTlsClient.cs | 10 | ||||
-rw-r--r-- | crypto/src/crypto/tls/AbstractTlsServer.cs | 12 | ||||
-rw-r--r-- | crypto/src/crypto/tls/AlertDescription.cs | 13 | ||||
-rw-r--r-- | crypto/src/crypto/tls/CipherSuite.cs | 17 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsClient.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsClientProtocol.cs | 19 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsServer.cs | 3 | ||||
-rw-r--r-- | crypto/src/crypto/tls/TlsServerProtocol.cs | 5 |
8 files changed, 77 insertions, 4 deletions
diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs index 9484afa7d..9944b0b18 100644 --- a/crypto/src/crypto/tls/AbstractTlsClient.cs +++ b/crypto/src/crypto/tls/AbstractTlsClient.cs @@ -67,6 +67,16 @@ namespace Org.BouncyCastle.Crypto.Tls get { return ProtocolVersion.TLSv12; } } + public virtual bool IsFallback + { + /* + * draft-bmoeller-tls-downgrade-scsv-02 4. [..] is meant for use by clients that repeat a + * connection attempt with a downgraded protocol in order to avoid interoperability problems + * with legacy servers. + */ + get { return false; } + } + public virtual IDictionary GetClientExtensions() { IDictionary clientExtensions = null; diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs index c2c6fd57c..6cd9a881e 100644 --- a/crypto/src/crypto/tls/AbstractTlsServer.cs +++ b/crypto/src/crypto/tls/AbstractTlsServer.cs @@ -110,6 +110,18 @@ namespace Org.BouncyCastle.Crypto.Tls this.mClientVersion = clientVersion; } + public virtual void NotifyFallback(bool isFallback) + { + /* + * draft-bmoeller-tls-downgrade-scsv-02 3. If TLS_FALLBACK_SCSV appears in + * ClientHello.cipher_suites and the highest protocol version supported by the server is + * higher than the version indicated in ClientHello.client_version, the server MUST respond + * with an inappropriate_fallback alert. + */ + if (isFallback && MaximumVersion.IsLaterVersionOf(mClientVersion)) + throw new TlsFatalAlert(AlertDescription.inappropriate_fallback); + } + public virtual void NotifyOfferedCipherSuites(int[] offeredCipherSuites) { this.mOfferedCipherSuites = offeredCipherSuites; diff --git a/crypto/src/crypto/tls/AlertDescription.cs b/crypto/src/crypto/tls/AlertDescription.cs index 5b6e88bf7..ab6924567 100644 --- a/crypto/src/crypto/tls/AlertDescription.cs +++ b/crypto/src/crypto/tls/AlertDescription.cs @@ -214,6 +214,17 @@ namespace Org.BouncyCastle.Crypto.Tls */ public const byte unknown_psk_identity = 115; + /* + * draft-bmoeller-tls-downgrade-scsv-02 + */ + + /** + * If TLS_FALLBACK_SCSV appears in ClientHello.cipher_suites and the highest protocol version + * supported by the server is higher than the version indicated in ClientHello.client_version, + * the server MUST respond with an inappropriate_fallback alert. + */ + public const byte inappropriate_fallback = 86; + public static string GetName(byte alertDescription) { switch (alertDescription) @@ -278,6 +289,8 @@ namespace Org.BouncyCastle.Crypto.Tls return "bad_certificate_hash_value"; case unknown_psk_identity: return "unknown_psk_identity"; + case inappropriate_fallback: + return "inappropriate_fallback"; default: return "UNKNOWN"; } diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs index f034ab802..540b5d18d 100644 --- a/crypto/src/crypto/tls/CipherSuite.cs +++ b/crypto/src/crypto/tls/CipherSuite.cs @@ -348,5 +348,22 @@ namespace Org.BouncyCastle.Crypto.Tls public const int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xE41D; public const int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE41E; public const int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xE41F; + + /* + * draft-bmoeller-tls-downgrade-scsv-02 + */ + public const int TLS_FALLBACK_SCSV = 0x5600; + + public static bool IsScsv(int cipherSuite) + { + switch (cipherSuite) + { + case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: + case TLS_FALLBACK_SCSV: + return true; + default: + return false; + } + } } } diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs index cd5dfad13..116f6a779 100644 --- a/crypto/src/crypto/tls/TlsClient.cs +++ b/crypto/src/crypto/tls/TlsClient.cs @@ -27,6 +27,8 @@ namespace Org.BouncyCastle.Crypto.Tls ProtocolVersion ClientVersion { get; } + bool IsFallback { get; } + /// <summary> /// Get the list of cipher suites that this client supports. /// </summary> diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 9fe50add8..ea8a1b2e4 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -607,7 +607,7 @@ namespace Org.BouncyCastle.Crypto.Tls int selectedCipherSuite = TlsUtilities.ReadUint16(buf); if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); @@ -815,6 +815,8 @@ namespace Org.BouncyCastle.Crypto.Tls } } + bool fallback = this.mTlsClient.IsFallback; + this.mOfferedCipherSuites = this.mTlsClient.GetCipherSuites(); this.mOfferedCompressionMethods = this.mTlsClient.GetCompressionMethods(); @@ -850,9 +852,9 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info); bool noRenegExt = (null == renegExtData); - bool noSCSV = !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV); + bool noRenegScsv = !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV); - if (noRenegExt && noSCSV) + if (noRenegExt && noRenegScsv) { // TODO Consider whether to default to a client extension instead // this.mClientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mClientExtensions); @@ -860,6 +862,17 @@ namespace Org.BouncyCastle.Crypto.Tls this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV); } + /* + * draft-bmoeller-tls-downgrade-scsv-02 4. If a client sends a + * ClientHello.client_version containing a lower value than the latest (highest-valued) + * version supported by the client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite + * value in ClientHello.cipher_suites. + */ + if (fallback && !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV)) + { + this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV); + } + TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, message); } diff --git a/crypto/src/crypto/tls/TlsServer.cs b/crypto/src/crypto/tls/TlsServer.cs index 93e62b9ac..e791f93a9 100644 --- a/crypto/src/crypto/tls/TlsServer.cs +++ b/crypto/src/crypto/tls/TlsServer.cs @@ -13,6 +13,9 @@ namespace Org.BouncyCastle.Crypto.Tls void NotifyClientVersion(ProtocolVersion clientVersion); /// <exception cref="IOException"></exception> + void NotifyFallback(bool isFallback); + + /// <exception cref="IOException"></exception> void NotifyOfferedCipherSuites(int[] offeredCipherSuites); /// <exception cref="IOException"></exception> diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index 165d6a147..b1fb830b6 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -453,6 +453,8 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ReceiveClientHelloMessage(MemoryStream buf) { ProtocolVersion client_version = TlsUtilities.ReadVersion(buf); + mRecordStream.SetWriteVersion(client_version); + if (client_version.IsDtls) throw new TlsFatalAlert(AlertDescription.illegal_parameter); @@ -499,6 +501,7 @@ namespace Org.BouncyCastle.Crypto.Tls ContextAdmin.SetClientVersion(client_version); mTlsServer.NotifyClientVersion(client_version); + mTlsServer.NotifyFallback(Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV)); mSecurityParameters.clientRandom = client_random; @@ -626,7 +629,7 @@ namespace Org.BouncyCastle.Crypto.Tls int selectedCipherSuite = mTlsServer.GetSelectedCipherSuite(); if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.internal_error); |