diff options
Diffstat (limited to 'crypto/src/tls/TlsClientProtocol.cs')
-rw-r--r-- | crypto/src/tls/TlsClientProtocol.cs | 203 |
1 files changed, 121 insertions, 82 deletions
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs index 8e31fa6c8..53cd37123 100644 --- a/crypto/src/tls/TlsClientProtocol.cs +++ b/crypto/src/tls/TlsClientProtocol.cs @@ -1112,6 +1112,16 @@ namespace Org.BouncyCastle.Tls m_tlsClient.NotifySessionID(selectedSessionID); securityParameters.m_resumedSession = selectedSessionID.Length > 0 && m_tlsSession != null && Arrays.AreEqual(selectedSessionID, m_tlsSession.SessionID); + + if (securityParameters.IsResumedSession) + { + if (serverHello.CipherSuite != m_sessionParameters.CipherSuite || + !securityParameters.NegotiatedVersion.Equals(m_sessionParameters.NegotiatedVersion)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter, + "ServerHello parameters do not match resumed session"); + } + } } /* @@ -1124,7 +1134,8 @@ namespace Org.BouncyCastle.Tls if (!TlsUtilities.IsValidCipherSuiteSelection(offeredCipherSuites, cipherSuite) || !TlsUtilities.IsValidVersionForCipherSuite(cipherSuite, securityParameters.NegotiatedVersion)) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + throw new TlsFatalAlert(AlertDescription.illegal_parameter, + "ServerHello selected invalid cipher suite"); } TlsUtilities.NegotiatedCipherSuite(securityParameters, cipherSuite); @@ -1139,9 +1150,9 @@ namespace Org.BouncyCastle.Tls * Hello is always allowed. */ this.m_serverExtensions = serverHelloExtensions; - if (m_serverExtensions != null) + if (serverHelloExtensions != null) { - foreach (int extType in m_serverExtensions.Keys) + foreach (int extType in serverHelloExtensions.Keys) { /* * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a @@ -1178,7 +1189,7 @@ namespace Org.BouncyCastle.Tls } } - byte[] renegExtData = TlsUtilities.GetExtensionData(m_serverExtensions, ExtensionType.renegotiation_info); + byte[] renegExtData = TlsUtilities.GetExtensionData(serverHelloExtensions, ExtensionType.renegotiation_info); // NOT renegotiating { @@ -1218,37 +1229,41 @@ namespace Org.BouncyCastle.Tls // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming m_tlsClient.NotifySecureRenegotiation(securityParameters.IsSecureRenegotiation); - /* - * RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended - * master secret [..]. (and see 5.2, 5.3) - * - * RFC 8446 Appendix D. Because TLS 1.3 always hashes in the transcript up to the server - * Finished, implementations which support both TLS 1.3 and earlier versions SHOULD indicate - * the use of the Extended Master Secret extension in their APIs whenever TLS 1.3 is used. - */ + // extended_master_secret { - bool acceptedExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension( - m_serverExtensions); - bool resumedSession = securityParameters.IsResumedSession; + bool negotiatedEms = false; - if (acceptedExtendedMasterSecret) + if (TlsExtensionsUtilities.HasExtendedMasterSecretExtension(m_clientExtensions)) { - if (server_version.IsSsl - || (!resumedSession && !m_tlsClient.ShouldUseExtendedMasterSecret())) + negotiatedEms = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverHelloExtensions); + + if (TlsUtilities.IsExtendedMasterSecretOptional(server_version)) { - throw new TlsFatalAlert(AlertDescription.handshake_failure); + if (!negotiatedEms && + m_tlsClient.RequiresExtendedMasterSecret()) + { + throw new TlsFatalAlert(AlertDescription.handshake_failure, + "Extended Master Secret extension is required"); + } } - } - else - { - if (m_tlsClient.RequiresExtendedMasterSecret() - || (resumedSession && !m_tlsClient.AllowLegacyResumption())) + else { - throw new TlsFatalAlert(AlertDescription.handshake_failure); + if (negotiatedEms) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter, + "Server sent an unexpected extended_master_secret extension negotiating " + server_version); + } } } - securityParameters.m_extendedMasterSecret = acceptedExtendedMasterSecret; + securityParameters.m_extendedMasterSecret = negotiatedEms; + } + + if (securityParameters.IsResumedSession && + securityParameters.IsExtendedMasterSecret != m_sessionParameters.IsExtendedMasterSecret) + { + throw new TlsFatalAlert(AlertDescription.handshake_failure, + "Server resumed session with mismatched extended_master_secret negotiation"); } /* @@ -1257,19 +1272,14 @@ namespace Org.BouncyCastle.Tls * messages are considered. */ securityParameters.m_applicationProtocol = TlsExtensionsUtilities.GetAlpnExtensionServer( - m_serverExtensions); + serverHelloExtensions); securityParameters.m_applicationProtocolSet = true; var sessionClientExtensions = m_clientExtensions; - var sessionServerExtensions = m_serverExtensions; + var sessionServerExtensions = serverHelloExtensions; + if (securityParameters.IsResumedSession) { - if (securityParameters.CipherSuite != m_sessionParameters.CipherSuite - || !server_version.Equals(m_sessionParameters.NegotiatedVersion)) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - sessionClientExtensions = null; sessionServerExtensions = m_sessionParameters.ReadServerExtensions(); } @@ -1291,16 +1301,12 @@ namespace Org.BouncyCastle.Tls securityParameters.m_encryptThenMac = serverSentEncryptThenMAC; } - securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions, - sessionServerExtensions, AlertDescription.illegal_parameter); + securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension( sessionServerExtensions); - /* - * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in - * a session resumption handshake. - */ if (!securityParameters.IsResumedSession) { // TODO[tls13] See RFC 8446 4.4.2.1 @@ -1315,6 +1321,11 @@ namespace Org.BouncyCastle.Tls securityParameters.m_statusRequestVersion = 1; } + securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); + securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); + this.m_expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket, AlertDescription.illegal_parameter); } @@ -1363,10 +1374,6 @@ namespace Org.BouncyCastle.Tls this.m_certificateRequest = certificateRequest; - m_tlsClientContext.SecurityParameters.m_clientCertificateType = - TlsExtensionsUtilities.GetClientCertificateTypeExtensionServer(m_serverExtensions, - CertificateType.X509); - TlsUtilities.EstablishServerSigAlgs(m_tlsClientContext.SecurityParameters, certificateRequest); } @@ -1404,31 +1411,34 @@ namespace Org.BouncyCastle.Tls var sessionClientExtensions = m_clientExtensions; var sessionServerExtensions = m_serverExtensions; + if (securityParameters.IsResumedSession) { - if (securityParameters.CipherSuite != m_sessionParameters.CipherSuite - || !negotiatedVersion.Equals(m_sessionParameters.NegotiatedVersion)) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - sessionClientExtensions = null; sessionServerExtensions = m_sessionParameters.ReadServerExtensions(); } - securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions, - sessionServerExtensions, AlertDescription.illegal_parameter); + securityParameters.m_maxFragmentLength = TlsUtilities.ProcessMaxFragmentLengthExtension( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); securityParameters.m_encryptThenMac = false; securityParameters.m_truncatedHmac = false; - /* - * TODO[tls13] RFC 8446 4.4.2.1. OCSP Status and SCT Extensions. - * - * OCSP information is carried in an extension for a CertificateEntry. - */ - securityParameters.m_statusRequestVersion = - m_clientExtensions.ContainsKey(ExtensionType.status_request) ? 1 : 0; + if (!securityParameters.IsResumedSession) + { + /* + * TODO[tls13] RFC 8446 4.4.2.1. OCSP Status and SCT Extensions. + * + * OCSP information is carried in an extension for a CertificateEntry. + */ + securityParameters.m_statusRequestVersion = m_clientExtensions.ContainsKey(ExtensionType.status_request) + ? 1 : 0; + + securityParameters.m_clientCertificateType = TlsUtilities.ProcessClientCertificateTypeExtension13( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); + securityParameters.m_serverCertificateType = TlsUtilities.ProcessServerCertificateTypeExtension13( + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); + } this.m_expectSessionTicket = false; @@ -1514,10 +1524,6 @@ namespace Org.BouncyCastle.Tls AssertEmpty(buf); m_certificateRequest = TlsUtilities.ValidateCertificateRequest(certificateRequest, m_keyExchange); - - m_tlsClientContext.SecurityParameters.m_clientCertificateType = - TlsExtensionsUtilities.GetClientCertificateTypeExtensionServer(m_serverExtensions, - CertificateType.X509); } /// <exception cref="IOException"/> @@ -1659,20 +1665,21 @@ namespace Org.BouncyCastle.Tls securityParameters.m_clientRandom = CreateRandomBlock(useGmtUnixTime, m_tlsClientContext); } - EstablishSession(offeringTlsV12Minus ? m_tlsClient.GetSessionToResume() : null); - m_tlsClient.NotifySessionToResume(m_tlsSession); - - /* - * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a - * Session ID in the TLS ClientHello. - */ - byte[] legacy_session_id = TlsUtilities.GetSessionID(m_tlsSession); + TlsSession sessionToResume = offeringTlsV12Minus ? m_tlsClient.GetSessionToResume() : null; bool fallback = m_tlsClient.IsFallback(); int[] offeredCipherSuites = m_tlsClient.GetCipherSuites(); - if (legacy_session_id.Length > 0 && m_sessionParameters != null) + this.m_clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(m_tlsClient.GetClientExtensions()); + + bool shouldUseEms = m_tlsClient.ShouldUseExtendedMasterSecret(); + + EstablishSession(sessionToResume); + + byte[] legacy_session_id = TlsUtilities.GetSessionID(m_tlsSession); + + if (legacy_session_id.Length > 0) { if (!Arrays.Contains(offeredCipherSuites, m_sessionParameters.CipherSuite)) { @@ -1680,8 +1687,42 @@ namespace Org.BouncyCastle.Tls } } - this.m_clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised( - m_tlsClient.GetClientExtensions()); + ProtocolVersion sessionVersion = null; + if (legacy_session_id.Length > 0) + { + sessionVersion = m_sessionParameters.NegotiatedVersion; + + if (!ProtocolVersion.Contains(supportedVersions, sessionVersion)) + { + legacy_session_id = TlsUtilities.EmptyBytes; + } + } + + if (legacy_session_id.Length > 0 && TlsUtilities.IsExtendedMasterSecretOptional(sessionVersion)) + { + if (shouldUseEms) + { + if (!m_sessionParameters.IsExtendedMasterSecret && + !m_tlsClient.AllowLegacyResumption()) + { + legacy_session_id = TlsUtilities.EmptyBytes; + } + } + else + { + if (m_sessionParameters.IsExtendedMasterSecret) + { + legacy_session_id = TlsUtilities.EmptyBytes; + } + } + } + + if (legacy_session_id.Length < 1) + { + CancelSession(); + } + + m_tlsClient.NotifySessionToResume(m_tlsSession); ProtocolVersion legacy_version = latestVersion; if (offeringTlsV13Plus) @@ -1691,10 +1732,10 @@ namespace Org.BouncyCastle.Tls TlsExtensionsUtilities.AddSupportedVersionsExtensionClient(m_clientExtensions, supportedVersions); /* - * RFC 8446 4.2.1. In compatibility mode [..], this field MUST be non-empty, so a client + * RFC 8446 4.1.2. In compatibility mode [..], this field MUST be non-empty, so a client * not offering a pre-TLS 1.3 session MUST generate a new 32-byte value. */ - if (legacy_session_id.Length < 1) + if (legacy_session_id.Length < 1 && TlsUtilities.ShouldUseCompatibilityMode(m_tlsClient)) { legacy_session_id = m_tlsClientContext.NonceGenerator.GenerateNonce(32); } @@ -1720,15 +1761,13 @@ namespace Org.BouncyCastle.Tls this.m_clientAgreements = TlsUtilities.AddKeyShareToClientHello(m_tlsClientContext, m_tlsClient, m_clientExtensions); - if (TlsUtilities.IsExtendedMasterSecretOptionalTls(supportedVersions) - && (m_tlsClient.ShouldUseExtendedMasterSecret() || - (null != m_sessionParameters && m_sessionParameters.IsExtendedMasterSecret))) + if (shouldUseEms && TlsUtilities.IsExtendedMasterSecretOptional(supportedVersions)) { - TlsExtensionsUtilities.AddExtendedMasterSecretExtension(m_clientExtensions); + TlsExtensionsUtilities.AddExtendedMasterSecretExtension(this.m_clientExtensions); } - else if (!offeringTlsV13Plus && m_tlsClient.RequiresExtendedMasterSecret()) + else { - throw new TlsFatalAlert(AlertDescription.internal_error); + this.m_clientExtensions.Remove(ExtensionType.extended_master_secret); } // NOT renegotiating |