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
|