diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs
index cb59289ae..ba2b565ca 100644
--- a/crypto/src/tls/TlsClientProtocol.cs
+++ b/crypto/src/tls/TlsClientProtocol.cs
@@ -450,24 +450,27 @@ namespace Org.BouncyCastle.Tls
{
Process13HelloRetryRequest(serverHello);
m_handshakeHash.NotifyPrfDetermined();
+ m_handshakeHash.SealHashAlgorithms();
TlsUtilities.AdjustTranscriptForRetry(m_handshakeHash);
buf.UpdateHash(m_handshakeHash);
this.m_connectionState = CS_SERVER_HELLO_RETRY_REQUEST;
Send13ClientHelloRetry();
- m_handshakeHash.SealHashAlgorithms();
this.m_connectionState = CS_CLIENT_HELLO_RETRY;
}
else
{
ProcessServerHello(serverHello);
m_handshakeHash.NotifyPrfDetermined();
+ if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
+ {
+ m_handshakeHash.SealHashAlgorithms();
+ }
buf.UpdateHash(m_handshakeHash);
this.m_connectionState = CS_SERVER_HELLO;
if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
{
- m_handshakeHash.SealHashAlgorithms();
Process13ServerHelloCoda(serverHello, false);
}
}
@@ -526,61 +529,70 @@ namespace Org.BouncyCastle.Tls
this.m_connectionState = CS_SERVER_HELLO_DONE;
- IList clientSupplementalData = m_tlsClient.GetClientSupplementalData();
- if (clientSupplementalData != null)
+ TlsCredentials clientAuthCredentials = null;
+ TlsCredentialedSigner clientAuthSigner = null;
+ Certificate clientAuthCertificate = null;
+ SignatureAndHashAlgorithm clientAuthAlgorithm = null;
+ TlsStreamSigner clientAuthStreamSigner = null;
+
+ if (m_certificateRequest != null)
{
- SendSupplementalDataMessage(clientSupplementalData);
- this.m_connectionState = CS_CLIENT_SUPPLEMENTAL_DATA;
+ clientAuthCredentials = TlsUtilities.EstablishClientCredentials(m_authentication,
+ m_certificateRequest);
+ if (clientAuthCredentials != null)
+ {
+ clientAuthCertificate = clientAuthCredentials.Certificate;
+
+ if (clientAuthCredentials is TlsCredentialedSigner)
+ {
+ clientAuthSigner = (TlsCredentialedSigner)clientAuthCredentials;
+ clientAuthAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(
+ securityParameters.NegotiatedVersion, clientAuthSigner);
+ clientAuthStreamSigner = clientAuthSigner.GetStreamSigner();
+
+ if (ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion))
+ {
+ TlsUtilities.VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs,
+ clientAuthAlgorithm, AlertDescription.internal_error);
+
+ if (clientAuthStreamSigner == null)
+ {
+ TlsUtilities.TrackHashAlgorithmClient(m_handshakeHash, clientAuthAlgorithm);
+ }
+ }
+
+ if (clientAuthStreamSigner != null)
+ {
+ m_handshakeHash.ForceBuffering();
+ }
+ }
+ }
}
- TlsCredentialedSigner credentialedSigner = null;
- TlsStreamSigner streamSigner = null;
+ m_handshakeHash.SealHashAlgorithms();
- if (m_certificateRequest == null)
+ if (clientAuthCredentials == null)
{
m_keyExchange.SkipClientCredentials();
}
else
{
- Certificate clientCertificate = null;
-
- TlsCredentials clientCredentials = TlsUtilities.EstablishClientCredentials(m_authentication,
- m_certificateRequest);
- if (null == clientCredentials)
- {
- m_keyExchange.SkipClientCredentials();
-
- /*
- * RFC 5246 If no suitable certificate is available, the client MUST send a
- * certificate message containing no certificates.
- *
- * NOTE: In previous RFCs, this was SHOULD instead of MUST.
- */
- }
- else
- {
- m_keyExchange.ProcessClientCredentials(clientCredentials);
-
- clientCertificate = clientCredentials.Certificate;
-
- if (clientCredentials is TlsCredentialedSigner)
- {
- credentialedSigner = (TlsCredentialedSigner)clientCredentials;
- streamSigner = credentialedSigner.GetStreamSigner();
- }
- }
+ m_keyExchange.ProcessClientCredentials(clientAuthCredentials);
+ }
- SendCertificateMessage(clientCertificate, null);
- this.m_connectionState = CS_CLIENT_CERTIFICATE;
+ IList clientSupplementalData = m_tlsClient.GetClientSupplementalData();
+ if (clientSupplementalData != null)
+ {
+ SendSupplementalDataMessage(clientSupplementalData);
+ this.m_connectionState = CS_CLIENT_SUPPLEMENTAL_DATA;
}
- bool forceBuffering = streamSigner != null;
- TlsUtilities.SealHandshakeHash(m_tlsClientContext, m_handshakeHash, forceBuffering);
+ if (m_certificateRequest != null)
+ {
+ SendCertificateMessage(clientAuthCertificate, null);
+ this.m_connectionState = CS_CLIENT_CERTIFICATE;
+ }
- /*
- * Send the client key exchange message, depending on the key exchange we are using
- * in our CipherSuite.
- */
SendClientKeyExchange();
this.m_connectionState = CS_CLIENT_KEY_EXCHANGE;
@@ -601,10 +613,11 @@ namespace Org.BouncyCastle.Tls
m_recordStream.SetPendingCipher(TlsUtilities.InitCipher(m_tlsClientContext));
- if (credentialedSigner != null)
+ if (clientAuthSigner != null)
{
DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient(
- m_tlsClientContext, credentialedSigner, streamSigner, m_handshakeHash);
+ m_tlsClientContext, clientAuthSigner, clientAuthAlgorithm, clientAuthStreamSigner,
+ m_handshakeHash);
SendCertificateVerifyMessage(certificateVerify);
this.m_connectionState = CS_CLIENT_CERTIFICATE_VERIFY;
}
@@ -674,13 +687,6 @@ namespace Org.BouncyCastle.Tls
ReceiveCertificateRequest(buf);
TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest);
-
- /*
- * TODO Give the client a chance to immediately select the CertificateVerify hash
- * algorithm here to avoid tracking the other hash algorithms unnecessarily?
- */
- TlsUtilities.TrackHashAlgorithms(m_handshakeHash, securityParameters.ServerSigAlgs);
-
break;
}
default:
@@ -1467,12 +1473,11 @@ namespace Org.BouncyCastle.Tls
if (null == serverCertificate || serverCertificate.IsEmpty)
throw new TlsFatalAlert(AlertDescription.internal_error);
- // TODO[tls13] Actual structure is 'CertificateVerify' in RFC 8446, consider adding for clarity
- DigitallySigned certificateVerify = DigitallySigned.Parse(m_tlsClientContext, buf);
+ CertificateVerify certificateVerify = CertificateVerify.Parse(m_tlsClientContext, buf);
AssertEmpty(buf);
- TlsUtilities.Verify13CertificateVerifyServer(m_tlsClientContext, certificateVerify, m_handshakeHash);
+ TlsUtilities.Verify13CertificateVerifyServer(m_tlsClientContext, m_handshakeHash, certificateVerify);
}
/// <exception cref="IOException"/>
|