diff --git a/crypto/src/tls/SecurityParameters.cs b/crypto/src/tls/SecurityParameters.cs
index 0681401eb..7891549b6 100644
--- a/crypto/src/tls/SecurityParameters.cs
+++ b/crypto/src/tls/SecurityParameters.cs
@@ -8,6 +8,7 @@ namespace Org.BouncyCastle.Tls
public sealed class SecurityParameters
{
internal int m_entity = -1;
+ internal bool m_resumedSession = false;
internal bool m_secureRenegotiation = false;
internal int m_cipherSuite = Tls.CipherSuite.TLS_NULL_WITH_NULL_NULL;
internal short m_maxFragmentLength = -1;
@@ -174,6 +175,11 @@ namespace Org.BouncyCastle.Tls
get { return m_extendedPadding; }
}
+ public bool IsResumedSession
+ {
+ get { return m_resumedSession; }
+ }
+
public bool IsSecureRenegotiation
{
get { return m_secureRenegotiation; }
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index d750c5e2c..fc3894710 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Tls
/// <exception cref="IOException"/>
protected virtual void Handle13HandshakeMessage(short type, HandshakeMessageInput buf)
{
- if (!IsTlsV13ConnectionState() || m_resumedSession)
+ if (!IsTlsV13ConnectionState())
throw new TlsFatalAlert(AlertDescription.internal_error);
switch (type)
@@ -335,6 +335,9 @@ namespace Org.BouncyCastle.Tls
if (m_connectionState > CS_CLIENT_HELLO
&& TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
{
+ if (securityParameters.IsResumedSession)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
Handle13HandshakeMessage(type, buf);
return;
}
@@ -342,7 +345,7 @@ namespace Org.BouncyCastle.Tls
if (!IsLegacyConnectionState())
throw new TlsFatalAlert(AlertDescription.internal_error);
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
if (type != HandshakeType.finished || m_connectionState != CS_SERVER_HELLO)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
@@ -871,7 +874,7 @@ namespace Org.BouncyCastle.Tls
securityParameters.m_negotiatedVersion = server_version;
TlsUtilities.NegotiatedVersionTlsClient(m_tlsClientContext, m_tlsClient);
- this.m_resumedSession = false;
+ securityParameters.m_resumedSession = false;
securityParameters.m_sessionID = TlsUtilities.EmptyBytes;
m_tlsClient.NotifySessionID(TlsUtilities.EmptyBytes);
@@ -926,7 +929,7 @@ namespace Org.BouncyCastle.Tls
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
- this.m_resumedSession = false;
+ securityParameters.m_resumedSession = false;
securityParameters.m_sessionID = TlsUtilities.EmptyBytes;
m_tlsClient.NotifySessionID(TlsUtilities.EmptyBytes);
@@ -1108,7 +1111,7 @@ namespace Org.BouncyCastle.Tls
byte[] selectedSessionID = serverHello.SessionID;
securityParameters.m_sessionID = selectedSessionID;
m_tlsClient.NotifySessionID(selectedSessionID);
- this.m_resumedSession = selectedSessionID.Length > 0 && m_tlsSession != null
+ securityParameters.m_resumedSession = selectedSessionID.Length > 0 && m_tlsSession != null
&& Arrays.AreEqual(selectedSessionID, m_tlsSession.SessionID);
}
@@ -1166,7 +1169,7 @@ namespace Org.BouncyCastle.Tls
* extensions appearing in the client hello, and send a server hello containing no
* extensions[.]
*/
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
// TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats
// TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats
@@ -1227,11 +1230,12 @@ namespace Org.BouncyCastle.Tls
{
bool acceptedExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(
m_serverExtensions);
+ bool resumedSession = securityParameters.IsResumedSession;
if (acceptedExtendedMasterSecret)
{
if (server_version.IsSsl
- || (!m_resumedSession && !m_tlsClient.ShouldUseExtendedMasterSecret()))
+ || (!resumedSession && !m_tlsClient.ShouldUseExtendedMasterSecret()))
{
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
@@ -1239,7 +1243,7 @@ namespace Org.BouncyCastle.Tls
else
{
if (m_tlsClient.RequiresExtendedMasterSecret()
- || (m_resumedSession && !m_tlsClient.AllowLegacyResumption()))
+ || (resumedSession && !m_tlsClient.AllowLegacyResumption()))
{
throw new TlsFatalAlert(AlertDescription.handshake_failure);
}
@@ -1259,7 +1263,7 @@ namespace Org.BouncyCastle.Tls
var sessionClientExtensions = m_clientExtensions;
var sessionServerExtensions = m_serverExtensions;
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
if (securityParameters.CipherSuite != m_sessionParameters.CipherSuite
|| !server_version.Equals(m_sessionParameters.NegotiatedVersion))
@@ -1298,7 +1302,7 @@ namespace Org.BouncyCastle.Tls
* TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
* a session resumption handshake.
*/
- if (!m_resumedSession)
+ if (!securityParameters.IsResumedSession)
{
// TODO[tls13] See RFC 8446 4.4.2.1
if (TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions,
@@ -1324,7 +1328,7 @@ namespace Org.BouncyCastle.Tls
ApplyMaxFragmentLengthExtension(securityParameters.MaxFragmentLength);
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
securityParameters.m_masterSecret = m_sessionMasterSecret;
m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsClientContext));
@@ -1397,7 +1401,7 @@ namespace Org.BouncyCastle.Tls
var sessionClientExtensions = m_clientExtensions;
var sessionServerExtensions = m_serverExtensions;
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
if (securityParameters.CipherSuite != m_sessionParameters.CipherSuite
|| !negotiatedVersion.Equals(m_sessionParameters.NegotiatedVersion))
diff --git a/crypto/src/tls/TlsProtocol.cs b/crypto/src/tls/TlsProtocol.cs
index 67ee5773b..dbbb6e0f5 100644
--- a/crypto/src/tls/TlsProtocol.cs
+++ b/crypto/src/tls/TlsProtocol.cs
@@ -150,7 +150,6 @@ namespace Org.BouncyCastle.Tls
protected IDictionary<int, byte[]> m_serverExtensions = null;
protected short m_connectionState = CS_START;
- protected bool m_resumedSession = false;
protected bool m_selectedPsk13 = false;
protected bool m_receivedChangeCipherSpec = false;
protected bool m_expectSessionTicket = false;
@@ -361,7 +360,6 @@ namespace Org.BouncyCastle.Tls
this.m_handshakeHash = new DeferredHash(context);
this.m_connectionState = CS_START;
- this.m_resumedSession = false;
this.m_selectedPsk13 = false;
context.HandshakeBeginning(peer);
@@ -392,7 +390,6 @@ namespace Org.BouncyCastle.Tls
this.m_clientExtensions = null;
this.m_serverExtensions = null;
- this.m_resumedSession = false;
this.m_selectedPsk13 = false;
this.m_receivedChangeCipherSpec = false;
this.m_expectSessionTicket = false;
@@ -1320,9 +1317,8 @@ namespace Org.BouncyCastle.Tls
return false;
/*
- * NOTE: For session resumption without extended_master_secret, renegotiation MUST be
- * disabled (see RFC 7627 5.4). We currently do not implement renegotiation and it is
- * unlikely we ever would since it was removed in TLS 1.3.
+ * NOTE: For session resumption without extended_master_secret, renegotiation MUST be disabled
+ * (see RFC 7627 5.4).
*/
}
@@ -1385,7 +1381,7 @@ namespace Org.BouncyCastle.Tls
securityParameters.m_peerVerifyData = expected_verify_data;
- if (!m_resumedSession || securityParameters.IsExtendedMasterSecret)
+ if (!securityParameters.IsResumedSession || securityParameters.IsExtendedMasterSecret)
{
if (null == securityParameters.LocalVerifyData)
{
@@ -1553,7 +1549,7 @@ namespace Org.BouncyCastle.Tls
securityParameters.m_localVerifyData = verify_data;
- if (!m_resumedSession || securityParameters.IsExtendedMasterSecret)
+ if (!securityParameters.IsResumedSession || securityParameters.IsExtendedMasterSecret)
{
if (null == securityParameters.PeerVerifyData)
{
@@ -1660,9 +1656,9 @@ namespace Org.BouncyCastle.Tls
short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
if (maxFragmentLength >= 0)
{
- if (!MaxFragmentLength.IsValid(maxFragmentLength)
- || (!m_resumedSession &&
- maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)))
+ if (!MaxFragmentLength.IsValid(maxFragmentLength) ||
+ (clientExtensions != null &&
+ maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)))
{
throw new TlsFatalAlert(alertDescription);
}
diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs
index a222b998d..3acbe90df 100644
--- a/crypto/src/tls/TlsServerProtocol.cs
+++ b/crypto/src/tls/TlsServerProtocol.cs
@@ -226,6 +226,7 @@ namespace Org.BouncyCastle.Tls
*/
{
// TODO[tls13] Resumption/PSK
+ securityParameters.m_resumedSession = false;
this.m_tlsSession = TlsUtilities.ImportSession(TlsUtilities.EmptyBytes, null);
this.m_sessionParameters = null;
@@ -314,8 +315,9 @@ namespace Org.BouncyCastle.Tls
if (serverEncryptedExtensions.Count > 0)
{
- securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(clientHelloExtensions,
- serverEncryptedExtensions, AlertDescription.internal_error);
+ securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(
+ securityParameters.IsResumedSession ? null : clientHelloExtensions, serverEncryptedExtensions,
+ AlertDescription.internal_error);
}
securityParameters.m_encryptThenMac = false;
@@ -546,9 +548,10 @@ namespace Org.BouncyCastle.Tls
m_tlsServer.ProcessClientExtensions(m_clientExtensions);
}
- this.m_resumedSession = EstablishSession(m_tlsServer.GetSessionToResume(clientHello.SessionID));
+ bool resumedSession = EstablishSession(m_tlsServer.GetSessionToResume(clientHello.SessionID));
+ securityParameters.m_resumedSession = resumedSession;
- if (!m_resumedSession)
+ if (!resumedSession)
{
byte[] newSessionID = m_tlsServer.GetNewSessionID();
if (null == newSessionID)
@@ -568,7 +571,7 @@ namespace Org.BouncyCastle.Tls
TlsUtilities.NegotiatedVersionTlsServer(m_tlsServerContext);
{
- int cipherSuite = m_resumedSession
+ int cipherSuite = resumedSession
? m_sessionParameters.CipherSuite
: m_tlsServer.GetSelectedCipherSuite();
@@ -584,7 +587,7 @@ namespace Org.BouncyCastle.Tls
m_tlsServerContext.SetRsaPreMasterSecretVersion(clientLegacyVersion);
{
- var sessionServerExtensions = m_resumedSession
+ var sessionServerExtensions = resumedSession
? m_sessionParameters.ReadServerExtensions()
: m_tlsServer.GetServerExtensions();
@@ -628,7 +631,7 @@ namespace Org.BouncyCastle.Tls
* RFC 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended
* master secret [..]. (and see 5.2, 5.3)
*/
- if (m_resumedSession)
+ if (resumedSession)
{
if (!m_sessionParameters.IsExtendedMasterSecret)
{
@@ -669,13 +672,13 @@ namespace Org.BouncyCastle.Tls
securityParameters.m_encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(
m_serverExtensions);
- securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(m_clientExtensions,
- m_serverExtensions, AlertDescription.internal_error);
+ securityParameters.m_maxFragmentLength = ProcessMaxFragmentLengthExtension(
+ resumedSession ? null : m_clientExtensions, m_serverExtensions, AlertDescription.internal_error);
securityParameters.m_truncatedHmac = TlsExtensionsUtilities.HasTruncatedHmacExtension(
m_serverExtensions);
- if (!m_resumedSession)
+ if (!resumedSession)
{
if (TlsUtilities.HasExpectedEmptyExtensionData(m_serverExtensions, ExtensionType.status_request_v2,
AlertDescription.internal_error))
@@ -720,16 +723,12 @@ namespace Org.BouncyCastle.Tls
if (!IsTlsV13ConnectionState())
throw new TlsFatalAlert(AlertDescription.internal_error);
- if (m_resumedSession)
- {
- /*
- * TODO[tls13] Abbreviated handshakes (PSK resumption)
- *
- * NOTE: No CertificateRequest, Certificate, CertificateVerify messages, but client
- * might now send EndOfEarlyData after receiving server Finished message.
- */
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ /*
+ * TODO[tls13] Abbreviated handshakes (PSK resumption)
+ *
+ * NOTE: No CertificateRequest, Certificate, CertificateVerify messages, but client
+ * might now send EndOfEarlyData after receiving server Finished message.
+ */
switch (type)
{
@@ -857,6 +856,9 @@ namespace Org.BouncyCastle.Tls
if (m_connectionState > CS_CLIENT_HELLO
&& TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
{
+ if (securityParameters.IsResumedSession)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
Handle13HandshakeMessage(type, buf);
return;
}
@@ -864,7 +866,7 @@ namespace Org.BouncyCastle.Tls
if (!IsLegacyConnectionState())
throw new TlsFatalAlert(AlertDescription.internal_error);
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
if (type != HandshakeType.finished || m_connectionState != CS_SERVER_FINISHED)
throw new TlsFatalAlert(AlertDescription.unexpected_message);
@@ -933,7 +935,7 @@ namespace Org.BouncyCastle.Tls
SendServerHelloMessage(serverHello);
this.m_connectionState = CS_SERVER_HELLO;
- if (m_resumedSession)
+ if (securityParameters.IsResumedSession)
{
securityParameters.m_masterSecret = m_sessionMasterSecret;
m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsServerContext));
|