diff options
-rw-r--r-- | crypto/src/tls/DtlsClientProtocol.cs | 110 | ||||
-rw-r--r-- | crypto/src/tls/DtlsServerProtocol.cs | 29 | ||||
-rw-r--r-- | crypto/src/tls/SignatureScheme.cs | 5 | ||||
-rw-r--r-- | crypto/src/tls/TlsClientProtocol.cs | 115 | ||||
-rw-r--r-- | crypto/src/tls/TlsServerProtocol.cs | 31 | ||||
-rw-r--r-- | crypto/src/tls/TlsUtilities.cs | 116 | ||||
-rw-r--r-- | crypto/test/src/tls/test/DtlsTestSuite.cs | 64 | ||||
-rw-r--r-- | crypto/test/src/tls/test/TlsTestClientImpl.cs | 13 | ||||
-rw-r--r-- | crypto/test/src/tls/test/TlsTestClientProtocol.cs | 10 | ||||
-rw-r--r-- | crypto/test/src/tls/test/TlsTestServerImpl.cs | 4 | ||||
-rw-r--r-- | crypto/test/src/tls/test/TlsTestSuite.cs | 49 |
11 files changed, 300 insertions, 246 deletions
diff --git a/crypto/src/tls/DtlsClientProtocol.cs b/crypto/src/tls/DtlsClientProtocol.cs index 44f574e3a..dd273f3e7 100644 --- a/crypto/src/tls/DtlsClientProtocol.cs +++ b/crypto/src/tls/DtlsClientProtocol.cs @@ -137,6 +137,10 @@ namespace Org.BouncyCastle.Tls } handshake.HandshakeHash.NotifyPrfDetermined(); + if (!ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) + { + handshake.HandshakeHash.SealHashAlgorithms(); + } ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.MaxFragmentLength); @@ -237,12 +241,6 @@ namespace Org.BouncyCastle.Tls TlsUtilities.EstablishServerSigAlgs(securityParameters, state.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(handshake.HandshakeHash, securityParameters.ServerSigAlgs); - serverMessage = handshake.ReceiveMessage(); } else @@ -262,54 +260,71 @@ namespace Org.BouncyCastle.Tls throw new TlsFatalAlert(AlertDescription.unexpected_message); } - IList clientSupplementalData = state.client.GetClientSupplementalData(); - if (clientSupplementalData != null) - { - byte[] supplementalDataBody = GenerateSupplementalData(clientSupplementalData); - handshake.SendMessage(HandshakeType.supplemental_data, supplementalDataBody); - } + TlsCredentials clientAuthCredentials = null; + TlsCredentialedSigner clientAuthSigner = null; + Certificate clientAuthCertificate = null; + SignatureAndHashAlgorithm clientAuthAlgorithm = null; + TlsStreamSigner clientAuthStreamSigner = null; - if (null != state.certificateRequest) + if (state.certificateRequest != null) { - state.clientCredentials = TlsUtilities.EstablishClientCredentials(state.authentication, + clientAuthCredentials = TlsUtilities.EstablishClientCredentials(state.authentication, state.certificateRequest); + if (clientAuthCredentials != null) + { + clientAuthCertificate = clientAuthCredentials.Certificate; - /* - * 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. - */ + if (clientAuthCredentials is TlsCredentialedSigner) + { + clientAuthSigner = (TlsCredentialedSigner)clientAuthCredentials; + clientAuthAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + securityParameters.NegotiatedVersion, clientAuthSigner); + clientAuthStreamSigner = clientAuthSigner.GetStreamSigner(); - Certificate clientCertificate = null; - if (null != state.clientCredentials) - { - clientCertificate = state.clientCredentials.Certificate; - } + if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) + { + TlsUtilities.VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, + clientAuthAlgorithm, AlertDescription.internal_error); - SendCertificateMessage(state.clientContext, handshake, clientCertificate, null); - } + if (clientAuthStreamSigner == null) + { + TlsUtilities.TrackHashAlgorithmClient(handshake.HandshakeHash, clientAuthAlgorithm); + } + } - TlsCredentialedSigner credentialedSigner = null; - TlsStreamSigner streamSigner = null; + if (clientAuthStreamSigner != null) + { + handshake.HandshakeHash.ForceBuffering(); + } + } + } + } - if (null != state.clientCredentials) + if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) { - state.keyExchange.ProcessClientCredentials(state.clientCredentials); + handshake.HandshakeHash.SealHashAlgorithms(); + } - if (state.clientCredentials is TlsCredentialedSigner) - { - credentialedSigner = (TlsCredentialedSigner)state.clientCredentials; - streamSigner = credentialedSigner.GetStreamSigner(); - } + if (clientAuthCredentials == null) + { + state.keyExchange.SkipClientCredentials(); } else { - state.keyExchange.SkipClientCredentials(); + state.keyExchange.ProcessClientCredentials(clientAuthCredentials); } - bool forceBuffering = streamSigner != null; - TlsUtilities.SealHandshakeHash(state.clientContext, handshake.HandshakeHash, forceBuffering); + IList clientSupplementalData = state.client.GetClientSupplementalData(); + if (clientSupplementalData != null) + { + byte[] supplementalDataBody = GenerateSupplementalData(clientSupplementalData); + handshake.SendMessage(HandshakeType.supplemental_data, supplementalDataBody); + } + + if (null != state.certificateRequest) + { + SendCertificateMessage(state.clientContext, handshake, clientAuthCertificate, null); + } byte[] clientKeyExchangeBody = GenerateClientKeyExchange(state); handshake.SendMessage(HandshakeType.client_key_exchange, clientKeyExchangeBody); @@ -319,18 +334,16 @@ namespace Org.BouncyCastle.Tls TlsProtocol.EstablishMasterSecret(state.clientContext, state.keyExchange); recordLayer.InitPendingEpoch(TlsUtilities.InitCipher(state.clientContext)); + if (clientAuthSigner != null) { - if (credentialedSigner != null) - { - DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient( - state.clientContext, credentialedSigner, streamSigner, handshake.HandshakeHash); - byte[] certificateVerifyBody = GenerateCertificateVerify(state, certificateVerify); - handshake.SendMessage(HandshakeType.certificate_verify, certificateVerifyBody); - } - - handshake.PrepareToFinish(); + DigitallySigned certificateVerify = TlsUtilities.GenerateCertificateVerifyClient(state.clientContext, + clientAuthSigner, clientAuthAlgorithm, clientAuthStreamSigner, handshake.HandshakeHash); + byte[] certificateVerifyBody = GenerateCertificateVerify(state, certificateVerify); + handshake.SendMessage(HandshakeType.certificate_verify, certificateVerifyBody); } + handshake.PrepareToFinish(); + securityParameters.m_localVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext, handshake.HandshakeHash, false); handshake.SendMessage(HandshakeType.finished, securityParameters.LocalVerifyData); @@ -973,7 +986,6 @@ namespace Org.BouncyCastle.Tls internal TlsAuthentication authentication = null; internal CertificateStatus certificateStatus = null; internal CertificateRequest certificateRequest = null; - internal TlsCredentials clientCredentials = null; internal TlsHeartbeat heartbeat = null; internal short heartbeatPolicy = HeartbeatMode.peer_not_allowed_to_send; } diff --git a/crypto/src/tls/DtlsServerProtocol.cs b/crypto/src/tls/DtlsServerProtocol.cs index b49122423..2c6ddf31f 100644 --- a/crypto/src/tls/DtlsServerProtocol.cs +++ b/crypto/src/tls/DtlsServerProtocol.cs @@ -146,6 +146,10 @@ namespace Org.BouncyCastle.Tls } handshake.HandshakeHash.NotifyPrfDetermined(); + if (!ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) + { + handshake.HandshakeHash.SealHashAlgorithms(); + } IList serverSupplementalData = state.server.GetServerSupplementalData(); if (serverSupplementalData != null) @@ -225,17 +229,30 @@ namespace Org.BouncyCastle.Tls TlsUtilities.EstablishServerSigAlgs(securityParameters, state.certificateRequest); - TlsUtilities.TrackHashAlgorithms(handshake.HandshakeHash, securityParameters.ServerSigAlgs); + if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) + { + TlsUtilities.TrackHashAlgorithms(handshake.HandshakeHash, securityParameters.ServerSigAlgs); - byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest); - handshake.SendMessage(HandshakeType.certificate_request, certificateRequestBody); + if (!state.serverContext.Crypto.HasAllRawSignatureAlgorithms()) + { + handshake.HandshakeHash.ForceBuffering(); + } + } } } - handshake.SendMessage(HandshakeType.server_hello_done, TlsUtilities.EmptyBytes); + if (ProtocolVersion.DTLSv12.Equals(securityParameters.NegotiatedVersion)) + { + handshake.HandshakeHash.SealHashAlgorithms(); + } + + if (null != state.certificateRequest) + { + byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest); + handshake.SendMessage(HandshakeType.certificate_request, certificateRequestBody); + } - bool forceBuffering = false; - TlsUtilities.SealHandshakeHash(state.serverContext, handshake.HandshakeHash, forceBuffering); + handshake.SendMessage(HandshakeType.server_hello_done, TlsUtilities.EmptyBytes); clientMessage = handshake.ReceiveMessage(); diff --git a/crypto/src/tls/SignatureScheme.cs b/crypto/src/tls/SignatureScheme.cs index 03a8ce30f..ed8e3c21b 100644 --- a/crypto/src/tls/SignatureScheme.cs +++ b/crypto/src/tls/SignatureScheme.cs @@ -97,6 +97,11 @@ namespace Org.BouncyCastle.Tls } } + public static int GetCryptoHashAlgorithm(SignatureAndHashAlgorithm signatureAndHashAlgorithm) + { + return GetCryptoHashAlgorithm(From(signatureAndHashAlgorithm)); + } + public static string GetName(int signatureScheme) { switch (signatureScheme) diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs index 89e7c4ba9..930294eae 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 (!ProtocolVersion.TLSv12.Equals(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,73 @@ 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; + if (ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion)) + { + 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 +616,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 +690,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: diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs index 523fc0030..a21ae69cd 100644 --- a/crypto/src/tls/TlsServerProtocol.cs +++ b/crypto/src/tls/TlsServerProtocol.cs @@ -899,11 +899,13 @@ namespace Org.BouncyCastle.Tls ServerHello serverHello = GenerateServerHello(clientHello, buf); m_handshakeHash.NotifyPrfDetermined(); - - if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) + if (!ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion)) { m_handshakeHash.SealHashAlgorithms(); + } + if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) + { if (serverHello.IsHelloRetryRequest()) { TlsUtilities.AdjustTranscriptForRetry(m_handshakeHash); @@ -1026,19 +1028,32 @@ namespace Org.BouncyCastle.Tls TlsUtilities.EstablishServerSigAlgs(securityParameters, m_certificateRequest); - TlsUtilities.TrackHashAlgorithms(m_handshakeHash, securityParameters.ServerSigAlgs); + if (ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion)) + { + TlsUtilities.TrackHashAlgorithms(m_handshakeHash, securityParameters.ServerSigAlgs); - SendCertificateRequestMessage(m_certificateRequest); - this.m_connectionState = CS_SERVER_CERTIFICATE_REQUEST; + if (!m_tlsServerContext.Crypto.HasAllRawSignatureAlgorithms()) + { + m_handshakeHash.ForceBuffering(); + } + } } } + if (ProtocolVersion.TLSv12.Equals(securityParameters.NegotiatedVersion)) + { + m_handshakeHash.SealHashAlgorithms(); + } + + if (null != m_certificateRequest) + { + SendCertificateRequestMessage(m_certificateRequest); + this.m_connectionState = CS_SERVER_CERTIFICATE_REQUEST; + } + SendServerHelloDoneMessage(); this.m_connectionState = CS_SERVER_HELLO_DONE; - bool forceBuffering = false; - TlsUtilities.SealHandshakeHash(m_tlsServerContext, m_handshakeHash, forceBuffering); - break; } default: diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs index 9a6b76e66..076aaf535 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs @@ -1086,14 +1086,19 @@ namespace Org.BouncyCastle.Tls } internal static SignatureAndHashAlgorithm GetSignatureAndHashAlgorithm(ProtocolVersion negotiatedVersion, - TlsCredentialedSigner signerCredentials) + TlsCredentialedSigner credentialedSigner) { SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; - if (IsTlsV12(negotiatedVersion)) + if (IsSignatureAlgorithmsExtensionAllowed(negotiatedVersion)) { - signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; + signatureAndHashAlgorithm = credentialedSigner.SignatureAndHashAlgorithm; if (signatureAndHashAlgorithm == null) + { + /* + * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 + */ throw new TlsFatalAlert(AlertDescription.internal_error); + } } return signatureAndHashAlgorithm; } @@ -1348,6 +1353,14 @@ namespace Org.BouncyCastle.Tls public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm) { + VerifySupportedSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm, + AlertDescription.illegal_parameter); + } + + /// <exception cref="IOException"/> + internal static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, + SignatureAndHashAlgorithm signatureAlgorithm, short alertDescription) + { if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15)) { @@ -1359,7 +1372,7 @@ namespace Org.BouncyCastle.Tls if (signatureAlgorithm.Signature == SignatureAlgorithm.anonymous || !ContainsSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm)) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + throw new TlsFatalAlert(alertDescription); } } @@ -2125,48 +2138,38 @@ namespace Org.BouncyCastle.Tls } internal static DigitallySigned GenerateCertificateVerifyClient(TlsClientContext clientContext, - TlsCredentialedSigner credentialedSigner, TlsStreamSigner streamSigner, TlsHandshakeHash handshakeHash) + TlsCredentialedSigner clientAuthSigner, SignatureAndHashAlgorithm clientAuthAlgorithm, + TlsStreamSigner clientAuthStreamSigner, TlsHandshakeHash handshakeHash) { SecurityParameters securityParameters = clientContext.SecurityParameters; - ProtocolVersion negotiatedVersion = securityParameters.NegotiatedVersion; - - if (IsTlsV13(negotiatedVersion)) + if (IsTlsV13(securityParameters.NegotiatedVersion)) { // Should be using Generate13CertificateVerify instead throw new TlsFatalAlert(AlertDescription.internal_error); } - /* - * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 - */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm = GetSignatureAndHashAlgorithm(negotiatedVersion, - credentialedSigner); - byte[] signature; - if (streamSigner != null) + if (clientAuthStreamSigner != null) { - handshakeHash.CopyBufferTo(streamSigner.Stream); - signature = streamSigner.GetSignature(); + handshakeHash.CopyBufferTo(clientAuthStreamSigner.Stream); + signature = clientAuthStreamSigner.GetSignature(); } else { byte[] hash; - if (signatureAndHashAlgorithm == null) + if (clientAuthAlgorithm == null) { hash = securityParameters.SessionHash; } else { - int signatureScheme = SignatureScheme.From(signatureAndHashAlgorithm); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - hash = handshakeHash.GetFinalHash(cryptoHashAlgorithm); + hash = handshakeHash.GetFinalHash(SignatureScheme.GetCryptoHashAlgorithm(clientAuthAlgorithm)); } - signature = credentialedSigner.GenerateRawSignature(hash); + signature = clientAuthSigner.GenerateRawSignature(hash); } - return new DigitallySigned(signatureAndHashAlgorithm, signature); + return new DigitallySigned(clientAuthAlgorithm, signature); } internal static DigitallySigned Generate13CertificateVerify(TlsContext context, @@ -2202,10 +2205,7 @@ namespace Org.BouncyCastle.Tls return streamSigner.GetSignature(); } - int signatureScheme = SignatureScheme.From(signatureAndHashAlgorithm); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - TlsHash tlsHash = crypto.CreateHash(cryptoHashAlgorithm); + TlsHash tlsHash = CreateHash(crypto, signatureAndHashAlgorithm); tlsHash.Update(header, 0, header.Length); tlsHash.Update(prfHash, 0, prfHash.Length); byte[] hash = tlsHash.CalculateHash(); @@ -2255,10 +2255,7 @@ namespace Org.BouncyCastle.Tls byte[] hash; if (IsTlsV12(serverContext)) { - int signatureScheme = SignatureScheme.From(sigAndHashAlg); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - hash = handshakeHash.GetFinalHash(cryptoHashAlgorithm); + hash = handshakeHash.GetFinalHash(SignatureScheme.GetCryptoHashAlgorithm(sigAndHashAlg)); } else { @@ -2438,28 +2435,28 @@ namespace Org.BouncyCastle.Tls } } + internal static void TrackHashAlgorithmClient(TlsHandshakeHash handshakeHash, + SignatureAndHashAlgorithm signatureAndHashAlgorithm) + { + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureAndHashAlgorithm); + if (cryptoHashAlgorithm >= 0) + { + handshakeHash.TrackHashAlgorithm(cryptoHashAlgorithm); + } + } + internal static void TrackHashAlgorithms(TlsHandshakeHash handshakeHash, IList supportedSignatureAlgorithms) { - if (supportedSignatureAlgorithms != null) + foreach (SignatureAndHashAlgorithm signatureAndHashAlgorithm in supportedSignatureAlgorithms) { - foreach (SignatureAndHashAlgorithm signatureAndHashAlgorithm in supportedSignatureAlgorithms) + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureAndHashAlgorithm); + if (cryptoHashAlgorithm >= 0) { - /* - * TODO We could validate the signature algorithm part. Currently the impact is - * that we might be tracking extra hashes pointlessly (but there are only a - * limited number of recognized hash algorithms). - */ - int signatureScheme = SignatureScheme.From(signatureAndHashAlgorithm); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - if (cryptoHashAlgorithm >= 0) - { - handshakeHash.TrackHashAlgorithm(cryptoHashAlgorithm); - } - else if (HashAlgorithm.Intrinsic == signatureAndHashAlgorithm.Hash) - { - handshakeHash.ForceBuffering(); - } + handshakeHash.TrackHashAlgorithm(cryptoHashAlgorithm); + } + else if (HashAlgorithm.Intrinsic == signatureAndHashAlgorithm.Hash) + { + handshakeHash.ForceBuffering(); } } } @@ -4192,29 +4189,14 @@ namespace Org.BouncyCastle.Tls return handshakeHash.ForkPrfHash().CalculateHash(); } - internal static void SealHandshakeHash(TlsContext context, TlsHandshakeHash handshakeHash, bool forceBuffering) - { - if (forceBuffering || !context.Crypto.HasAllRawSignatureAlgorithms()) - { - handshakeHash.ForceBuffering(); - } - - handshakeHash.SealHashAlgorithms(); - } - private static TlsHash CreateHash(TlsCrypto crypto, short hashAlgorithm) { - int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(hashAlgorithm); - - return crypto.CreateHash(cryptoHashAlgorithm); + return crypto.CreateHash(TlsCryptoUtilities.GetHash(hashAlgorithm)); } private static TlsHash CreateHash(TlsCrypto crypto, SignatureAndHashAlgorithm signatureAndHashAlgorithm) { - int signatureScheme = SignatureScheme.From(signatureAndHashAlgorithm); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - return crypto.CreateHash(cryptoHashAlgorithm); + return crypto.CreateHash(SignatureScheme.GetCryptoHashAlgorithm(signatureAndHashAlgorithm)); } /// <exception cref="IOException"/> diff --git a/crypto/test/src/tls/test/DtlsTestSuite.cs b/crypto/test/src/tls/test/DtlsTestSuite.cs index 0af2be32c..27c1ca648 100644 --- a/crypto/test/src/tls/test/DtlsTestSuite.cs +++ b/crypto/test/src/tls/test/DtlsTestSuite.cs @@ -68,63 +68,59 @@ namespace Org.BouncyCastle.Tls.Tests + "_"; /* - * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit - * of the DTLS server after a fatal alert. As of writing, manual runs show the correct - * alerts being raised - */ - -#if false - /* - * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is - * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client. + * Server only declares support for SHA256/ECDSA, client selects SHA256/RSA, so we expect fatal alert + * from the client validation of the CertificateVerify algorithm. */ if (TlsUtilities.IsTlsV12(version)) { TlsTestConfig c = CreateDtlsTestConfig(version); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms(); + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.VectorOfOne( + new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa)); c.ExpectClientFatalAlert(AlertDescription.internal_error); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgClient"); } /* - * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is - * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server - * when it verifies the selected algorithm against the CertificateRequest supported - * algorithms. + * Server only declares support for rsa_pss_rsae_sha256, client selects rsa_pss_rsae_sha256 but claims + * ecdsa_secp256r1_sha256, so we expect fatal alert from the server validation of the + * CertificateVerify algorithm. */ if (TlsUtilities.IsTlsV12(version)) { TlsTestConfig c = CreateDtlsTestConfig(version); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.clientAuthSigAlg = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256); + c.clientAuthSigAlgClaimed = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256); + c.serverCertReqSigAlgs = TlsUtilities.VectorOfOne( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256)); c.serverCheckSigAlgOfClientCerts = false; c.ExpectServerFatalAlert(AlertDescription.illegal_parameter); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgServer1"); } /* - * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends - * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the - * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms, - * we expect fatal alert to come from the server when it finds the claimed algorithm - * doesn't match the client certificate. + * Server declares support for rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256, client selects + * rsa_pss_rsae_sha256 but claims ecdsa_secp256r1_sha256, so we expect fatal alert from the server + * validation of the client certificate. */ if (TlsUtilities.IsTlsV12(version)) { TlsTestConfig c = CreateDtlsTestConfig(version); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); - c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, - SignatureAlgorithm.ecdsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); - c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + c.clientAuthSigAlg = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256); + c.clientAuthSigAlgClaimed = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256); + c.serverCertReqSigAlgs = new ArrayList(2); + c.serverCertReqSigAlgs.Add( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256)); + c.serverCertReqSigAlgs.Add( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256)); + c.ExpectServerFatalAlert(AlertDescription.bad_certificate); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgServer2"); } { @@ -132,7 +128,7 @@ namespace Org.BouncyCastle.Tls.Tests c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; c.ExpectServerFatalAlert(AlertDescription.decrypt_error); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySignature"); } { @@ -161,8 +157,9 @@ namespace Org.BouncyCastle.Tls.Tests { TlsTestConfig c = CreateDtlsTestConfig(version); c.clientSendSignatureAlgorithms = false; + c.clientSendSignatureAlgorithmsCert = false; c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.rsa); - c.ExpectClientFatalAlert(AlertDescription.certificate_unknown); + c.ExpectClientFatalAlert(AlertDescription.bad_certificate); AddTestCase(testSuite, c, prefix + "BadServerCertSigAlg"); } @@ -196,7 +193,6 @@ namespace Org.BouncyCastle.Tls.Tests AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg2"); } -#endif { TlsTestConfig c = CreateDtlsTestConfig(version); @@ -218,7 +214,6 @@ namespace Org.BouncyCastle.Tls.Tests AddTestCase(testSuite, c, prefix + "GoodOptionalCertReqDeclined"); } -#if false /* * Server generates downgraded (RFC 8446) ServerHello. We expect fatal alert * (illegal_parameter) from the client. @@ -232,7 +227,6 @@ namespace Org.BouncyCastle.Tls.Tests AddTestCase(testSuite, c, prefix + "BadDowngrade"); } -#endif } private static void AddTestCase(IList testSuite, TlsTestConfig config, string name) diff --git a/crypto/test/src/tls/test/TlsTestClientImpl.cs b/crypto/test/src/tls/test/TlsTestClientImpl.cs index 04c8ad0af..cb70dbc80 100644 --- a/crypto/test/src/tls/test/TlsTestClientImpl.cs +++ b/crypto/test/src/tls/test/TlsTestClientImpl.cs @@ -310,14 +310,23 @@ namespace Org.BouncyCastle.Tls.Tests IList supportedSigAlgs = certificateRequest.SupportedSignatureAlgorithms; if (supportedSigAlgs != null && config.clientAuthSigAlg != null) { - supportedSigAlgs = new ArrayList(1); - supportedSigAlgs.Add(config.clientAuthSigAlg); + supportedSigAlgs = TlsUtilities.VectorOfOne(config.clientAuthSigAlg); } // TODO[tls13] Check also supportedSigAlgsCert against the chain signature(s) TlsCredentialedSigner signerCredentials = TlsTestUtilities.LoadSignerCredentials(m_context, supportedSigAlgs, SignatureAlgorithm.rsa, "x509-client-rsa.pem", "x509-client-key-rsa.pem"); + if (signerCredentials == null && supportedSigAlgs != null) + { + SignatureAndHashAlgorithm pss = SignatureScheme.GetSignatureAndHashAlgorithm( + SignatureScheme.rsa_pss_rsae_sha256); + if (TlsUtilities.ContainsSignatureAlgorithm(supportedSigAlgs, pss)) + { + signerCredentials = TlsTestUtilities.LoadSignerCredentials(m_context, + new string[]{ "x509-client-rsa.pem" }, "x509-client-key-rsa.pem", pss); + } + } if (config.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID) return signerCredentials; diff --git a/crypto/test/src/tls/test/TlsTestClientProtocol.cs b/crypto/test/src/tls/test/TlsTestClientProtocol.cs index f7e94680a..879996040 100644 --- a/crypto/test/src/tls/test/TlsTestClientProtocol.cs +++ b/crypto/test/src/tls/test/TlsTestClientProtocol.cs @@ -19,6 +19,16 @@ namespace Org.BouncyCastle.Tls.Tests this.m_config = config; } + protected override void Send13CertificateVerifyMessage(DigitallySigned certificateVerify) + { + if (m_config.clientAuthSigAlgClaimed != null) + { + certificateVerify = new DigitallySigned(m_config.clientAuthSigAlgClaimed, certificateVerify.Signature); + } + + base.Send13CertificateVerifyMessage(certificateVerify); + } + protected override void SendCertificateVerifyMessage(DigitallySigned certificateVerify) { if (certificateVerify.Algorithm != null && m_config.clientAuthSigAlgClaimed != null) diff --git a/crypto/test/src/tls/test/TlsTestServerImpl.cs b/crypto/test/src/tls/test/TlsTestServerImpl.cs index 77df632fe..273de3d31 100644 --- a/crypto/test/src/tls/test/TlsTestServerImpl.cs +++ b/crypto/test/src/tls/test/TlsTestServerImpl.cs @@ -258,9 +258,7 @@ namespace Org.BouncyCastle.Tls.Tests { if (TlsUtilities.IsTlsV12(m_context) && m_config.serverAuthSigAlg != null) { - IList signatureAlgorithms = new ArrayList(1); - signatureAlgorithms.Add(m_config.serverAuthSigAlg); - return signatureAlgorithms; + return TlsUtilities.VectorOfOne(m_config.serverAuthSigAlg); } return m_context.SecurityParameters.ClientSigAlgs; diff --git a/crypto/test/src/tls/test/TlsTestSuite.cs b/crypto/test/src/tls/test/TlsTestSuite.cs index adedd8249..86a543ef0 100644 --- a/crypto/test/src/tls/test/TlsTestSuite.cs +++ b/crypto/test/src/tls/test/TlsTestSuite.cs @@ -104,56 +104,59 @@ namespace Org.BouncyCastle.Tls.Tests } /* - * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is - * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client. + * Server only declares support for SHA256/ECDSA, client selects SHA256/RSA, so we expect fatal alert + * from the client validation of the CertificateVerify algorithm. */ if (isTlsV12Exactly) { TlsTestConfig c = CreateTlsTestConfig(version, clientCrypto, serverCrypto); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms(); - c.serverCheckSigAlgOfClientCerts = false; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.VectorOfOne( + new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa)); c.ExpectClientFatalAlert(AlertDescription.internal_error); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgClient"); } /* - * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is - * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server - * when it verifies the selected algorithm against the CertificateRequest supported - * algorithms. + * Server only declares support for rsa_pss_rsae_sha256, client selects rsa_pss_rsae_sha256 but claims + * ecdsa_secp256r1_sha256, so we expect fatal alert from the server validation of the + * CertificateVerify algorithm. */ if (isTlsV12) { TlsTestConfig c = CreateTlsTestConfig(version, clientCrypto, serverCrypto); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.clientAuthSigAlg = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256); + c.clientAuthSigAlgClaimed = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256); + c.serverCertReqSigAlgs = TlsUtilities.VectorOfOne( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256)); c.serverCheckSigAlgOfClientCerts = false; c.ExpectServerFatalAlert(AlertDescription.illegal_parameter); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgServer1"); } /* - * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends - * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the - * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms, - * we expect fatal alert to come from the server when it finds the claimed algorithm - * doesn't match the client certificate. + * Server declares support for rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256, client selects + * rsa_pss_rsae_sha256 but claims ecdsa_secp256r1_sha256, so we expect fatal alert from the server + * validation of the client certificate. */ if (isTlsV12) { TlsTestConfig c = CreateTlsTestConfig(version, clientCrypto, serverCrypto); c.clientAuth = C.CLIENT_AUTH_VALID; - c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); - c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa); - c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.clientAuthSigAlg = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256); + c.clientAuthSigAlgClaimed = SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256); + c.serverCertReqSigAlgs = new ArrayList(2); + c.serverCertReqSigAlgs.Add( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.rsa_pss_rsae_sha256)); + c.serverCertReqSigAlgs.Add( + SignatureScheme.GetSignatureAndHashAlgorithm(SignatureScheme.ecdsa_secp256r1_sha256)); c.ExpectServerFatalAlert(AlertDescription.bad_certificate); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySigAlgServer2"); } { @@ -161,7 +164,7 @@ namespace Org.BouncyCastle.Tls.Tests c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; c.ExpectServerFatalAlert(AlertDescription.decrypt_error); - AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature"); + AddTestCase(testSuite, c, prefix + "BadCertVerifySignature"); } { |