diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-07-28 16:00:23 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-07-28 16:00:23 +0700 |
commit | 2b15619e62a09da46a0b2c0f5279c86394a14eb5 (patch) | |
tree | 4163c0412c125e05bc664cda37263e997c499d14 | |
parent | Fix test class name (diff) | |
download | BouncyCastle.NET-ed25519-2b15619e62a09da46a0b2c0f5279c86394a14eb5.tar.xz |
Client message flow for PSK handshake
-rw-r--r-- | crypto/src/tls/TlsClientProtocol.cs | 56 | ||||
-rw-r--r-- | crypto/src/tls/TlsProtocol.cs | 4 | ||||
-rw-r--r-- | crypto/src/tls/TlsUtilities.cs | 12 |
3 files changed, 45 insertions, 27 deletions
diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs index 021e8da1b..4616580f0 100644 --- a/crypto/src/tls/TlsClientProtocol.cs +++ b/crypto/src/tls/TlsClientProtocol.cs @@ -118,20 +118,9 @@ namespace Org.BouncyCastle.Tls /// <exception cref="IOException"/> protected virtual void Handle13HandshakeMessage(short type, HandshakeMessageInput buf) { - if (!IsTlsV13ConnectionState()) + if (!IsTlsV13ConnectionState() || m_resumedSession) throw new TlsFatalAlert(AlertDescription.internal_error); - if (m_resumedSession) - { - /* - * TODO[tls13] Resumption/PSK - * - * NOTE: No CertificateRequest, Certificate, CertificateVerify messages, but client - * might now send EndOfEarlyData after receiving server Finished message. - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - switch (type) { case HandshakeType.certificate: @@ -146,9 +135,6 @@ namespace Org.BouncyCastle.Tls Skip13CertificateRequest(); } - /* - * TODO[tls13] For PSK-only key exchange, there's no Certificate message. - */ Receive13ServerCertificate(buf); this.m_connectionState = CS_SERVER_CERTIFICATE; break; @@ -235,6 +221,12 @@ namespace Org.BouncyCastle.Tls // See RFC 8446 D.4. m_recordStream.SetIgnoreChangeCipherSpec(false); + /* + * TODO[tls13] After receiving the server's Finished message, if the server has accepted early + * data, an EndOfEarlyData message will be sent to indicate the key change. This message will + * be encrypted with the 0-RTT traffic keys. + */ + if (null != m_certificateRequest) { TlsCredentialedSigner clientCredentials = TlsUtilities.Establish13ClientCredentials( @@ -968,6 +960,8 @@ namespace Org.BouncyCastle.Tls throw new TlsFatalAlert(AlertDescription.illegal_parameter); pskEarlySecret = m_clientBinders.m_earlySecrets[selected_identity]; + + this.m_selectedPsk13 = true; } m_tlsClient.NotifySelectedPsk(selectedPsk); @@ -1028,7 +1022,10 @@ namespace Org.BouncyCastle.Tls { m_recordStream.SetIgnoreChangeCipherSpec(true); - // TODO[tls13] If offering early data, the record is placed immediately after the first ClientHello. + /* + * TODO[tls13] If offering early_data, the record is placed immediately after the first + * ClientHello. + */ /* * TODO[tls13] Ideally wait until just after Server Finished received, but then we'd need to defer * the enabling of the pending write cipher @@ -1338,23 +1335,22 @@ namespace Org.BouncyCastle.Tls /// <exception cref="IOException"/> protected virtual void Receive13CertificateRequest(MemoryStream buf, bool postHandshakeAuth) { + // TODO[tls13] Support for post_handshake_auth + if (postHandshakeAuth) + throw new TlsFatalAlert(AlertDescription.internal_error); + /* * RFC 8446 4.3.2. A server which is authenticating with a certificate MAY optionally * request a certificate from the client. */ - /* - * TODO[tls13] Currently all handshakes are certificate-authenticated. When PSK-only becomes an option, - * then check here that a certificate message is expected (else fatal unexpected_message alert). - */ + if (m_selectedPsk13) + throw new TlsFatalAlert(AlertDescription.unexpected_message); CertificateRequest certificateRequest = CertificateRequest.Parse(m_tlsClientContext, buf); AssertEmpty(buf); - if (postHandshakeAuth) - throw new TlsFatalAlert(AlertDescription.internal_error); - if (!certificateRequest.HasCertificateRequestContext(TlsUtilities.EmptyBytes)) throw new TlsFatalAlert(AlertDescription.illegal_parameter); @@ -1459,6 +1455,9 @@ namespace Org.BouncyCastle.Tls /// <exception cref="IOException"/> protected virtual void Receive13ServerCertificate(MemoryStream buf) { + if (m_selectedPsk13) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + this.m_authentication = TlsUtilities.Receive13ServerCertificate(m_tlsClientContext, m_tlsClient, buf); // NOTE: In TLS 1.3 we don't have to wait for a possible CertificateStatus message. @@ -1584,7 +1583,10 @@ namespace Org.BouncyCastle.Tls { m_recordStream.SetIgnoreChangeCipherSpec(true); - // TODO[tls13] If offering early data, the record is placed immediately after the first ClientHello. + /* + * TODO[tls13] If offering early_data, the record is placed immediately after the first + * ClientHello. + */ SendChangeCipherSpecMessage(); } @@ -1791,10 +1793,10 @@ namespace Org.BouncyCastle.Tls /// <exception cref="IOException"/> protected virtual void Skip13ServerCertificate() { - this.m_authentication = null; + if (!m_selectedPsk13) + throw new TlsFatalAlert(AlertDescription.unexpected_message); - // TODO[tls13] May be skipped for PSK handshakes? - throw new TlsFatalAlert(AlertDescription.unexpected_message); + this.m_authentication = TlsUtilities.Skip13ServerCertificate(m_tlsClientContext); } } } diff --git a/crypto/src/tls/TlsProtocol.cs b/crypto/src/tls/TlsProtocol.cs index f05c09a1b..8d0e3fc0d 100644 --- a/crypto/src/tls/TlsProtocol.cs +++ b/crypto/src/tls/TlsProtocol.cs @@ -150,6 +150,7 @@ namespace Org.BouncyCastle.Tls 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; @@ -359,6 +360,8 @@ 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); @@ -389,6 +392,7 @@ namespace Org.BouncyCastle.Tls this.m_serverExtensions = null; this.m_resumedSession = false; + this.m_selectedPsk13 = false; this.m_receivedChangeCipherSpec = false; this.m_expectSessionTicket = false; } diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs index 9dea576f5..8df787b6f 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs @@ -4821,6 +4821,18 @@ namespace Org.BouncyCastle.Tls return authentication; } + internal static TlsAuthentication Skip13ServerCertificate(TlsClientContext clientContext) + { + SecurityParameters securityParameters = clientContext.SecurityParameters; + if (null != securityParameters.PeerCertificate) + throw new TlsFatalAlert(AlertDescription.internal_error); + + securityParameters.m_peerCertificate = null; + securityParameters.m_tlsServerEndPoint = null; + + return null; + } + public static bool ContainsNonAscii(byte[] bs) { for (int i = 0; i < bs.Length; ++i) |