summary refs log tree commit diff
path: root/crypto/src/tls/TlsUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/tls/TlsUtilities.cs')
-rw-r--r--crypto/src/tls/TlsUtilities.cs269
1 files changed, 116 insertions, 153 deletions
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs

index 05d38c59c..72ff92271 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs
@@ -1068,16 +1068,22 @@ namespace Org.BouncyCastle.Tls public static IList GetDefaultSupportedSignatureAlgorithms(TlsContext context) { + return GetSupportedSignatureAlgorithms(context, DefaultSupportedSigAlgs); + } + + public static IList GetSupportedSignatureAlgorithms(TlsContext context, IList candidates) + { TlsCrypto crypto = context.Crypto; IList result = Platform.CreateArrayList(DefaultSupportedSigAlgs.Count); - foreach (SignatureAndHashAlgorithm sigAndHashAlg in DefaultSupportedSigAlgs) + foreach (SignatureAndHashAlgorithm sigAndHashAlg in candidates) { AddIfSupported(result, crypto, sigAndHashAlg); } return result; } + [Obsolete("Will be removed")] public static SignatureAndHashAlgorithm GetSignatureAndHashAlgorithm(TlsContext context, TlsCredentialedSigner signerCredentials) { @@ -1085,14 +1091,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; } @@ -1347,6 +1358,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)) { @@ -1358,7 +1377,7 @@ namespace Org.BouncyCastle.Tls if (signatureAlgorithm.Signature == SignatureAlgorithm.anonymous || !ContainsSignatureAlgorithm(supportedSignatureAlgorithms, signatureAlgorithm)) { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + throw new TlsFatalAlert(alertDescription); } } @@ -2088,7 +2107,7 @@ namespace Org.BouncyCastle.Tls TlsHash h = algorithm == null ? new CombinedHash(crypto) - : CreateHash(crypto, algorithm.Hash); + : CreateHash(crypto, algorithm); SecurityParameters sp = context.SecurityParameters; // NOTE: The implicit copy here is intended (and important) @@ -2124,48 +2143,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 GenerateCertificateVerify13 instead + // 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.GetOutputStream()); - 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, @@ -2195,16 +2204,13 @@ namespace Org.BouncyCastle.Tls if (null != streamSigner) { - Stream output = streamSigner.GetOutputStream(); + Stream output = streamSigner.Stream; output.Write(header, 0, header.Length); output.Write(prfHash, 0, prfHash.Length); 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(); @@ -2224,22 +2230,17 @@ namespace Org.BouncyCastle.Tls { signatureAlgorithm = verifyingCert.GetLegacySignatureAlgorithm(); - short clientCertType = GetLegacyClientCertType(signatureAlgorithm); - if (clientCertType < 0 || !Arrays.Contains(certificateRequest.CertificateTypes, clientCertType)) - throw new TlsFatalAlert(AlertDescription.unsupported_certificate); + CheckClientCertificateType(certificateRequest, GetLegacyClientCertType(signatureAlgorithm), + AlertDescription.unsupported_certificate); } else { - signatureAlgorithm = sigAndHashAlg.Signature; + VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, sigAndHashAlg); - // TODO Is it possible (maybe only pre-1.2 to check this immediately when the Certificate arrives? - if (!IsValidSignatureAlgorithmForCertificateVerify(signatureAlgorithm, - certificateRequest.CertificateTypes)) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } + signatureAlgorithm = sigAndHashAlg.Signature; - VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, sigAndHashAlg); + CheckClientCertificateType(certificateRequest, + SignatureAlgorithm.GetClientCertificateType(signatureAlgorithm), AlertDescription.illegal_parameter); } // Verify the CertificateVerify message contains a correct signature. @@ -2251,7 +2252,7 @@ namespace Org.BouncyCastle.Tls if (streamVerifier != null) { - handshakeHash.CopyBufferTo(streamVerifier.GetOutputStream()); + handshakeHash.CopyBufferTo(streamVerifier.Stream); verified = streamVerifier.IsVerified(); } else @@ -2259,10 +2260,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 { @@ -2287,62 +2285,54 @@ namespace Org.BouncyCastle.Tls } } + /// <exception cref="IOException"/> internal static void Verify13CertificateVerifyClient(TlsServerContext serverContext, - CertificateRequest certificateRequest, DigitallySigned certificateVerify, TlsHandshakeHash handshakeHash) + TlsHandshakeHash handshakeHash, CertificateVerify certificateVerify) { SecurityParameters securityParameters = serverContext.SecurityParameters; - Certificate clientCertificate = securityParameters.PeerCertificate; - TlsCertificate verifyingCert = clientCertificate.GetCertificateAt(0); - - SignatureAndHashAlgorithm sigAndHashAlg = certificateVerify.Algorithm; - VerifySupportedSignatureAlgorithm(securityParameters.ServerSigAlgs, sigAndHashAlg); - - int signatureScheme = SignatureScheme.From(sigAndHashAlg); - - // Verify the CertificateVerify message contains a correct signature. - bool verified; - try - { - TlsVerifier verifier = verifyingCert.CreateVerifier(signatureScheme); - verified = Verify13CertificateVerify(serverContext.Crypto, certificateVerify, verifier, - "TLS 1.3, client CertificateVerify", handshakeHash); - } - catch (TlsFatalAlert e) - { - throw e; - } - catch (Exception e) - { - throw new TlsFatalAlert(AlertDescription.decrypt_error, e); - } + IList supportedAlgorithms = securityParameters.ServerSigAlgs; + TlsCertificate certificate = securityParameters.PeerCertificate.GetCertificateAt(0); - if (!verified) - { - throw new TlsFatalAlert(AlertDescription.decrypt_error); - } + Verify13CertificateVerify(supportedAlgorithms, "TLS 1.3, client CertificateVerify", handshakeHash, + certificate, certificateVerify); } + /// <exception cref="IOException"/> internal static void Verify13CertificateVerifyServer(TlsClientContext clientContext, - DigitallySigned certificateVerify, TlsHandshakeHash handshakeHash) + TlsHandshakeHash handshakeHash, CertificateVerify certificateVerify) { SecurityParameters securityParameters = clientContext.SecurityParameters; - Certificate serverCertificate = securityParameters.PeerCertificate; - TlsCertificate verifyingCert = serverCertificate.GetCertificateAt(0); - SignatureAndHashAlgorithm sigAndHashAlg = certificateVerify.Algorithm; - VerifySupportedSignatureAlgorithm(securityParameters.ClientSigAlgs, sigAndHashAlg); + IList supportedAlgorithms = securityParameters.ClientSigAlgs; + TlsCertificate certificate = securityParameters.PeerCertificate.GetCertificateAt(0); - int signatureScheme = SignatureScheme.From(sigAndHashAlg); + Verify13CertificateVerify(supportedAlgorithms, "TLS 1.3, server CertificateVerify", handshakeHash, + certificate, certificateVerify); + } + /// <exception cref="IOException"/> + private static void Verify13CertificateVerify(IList supportedAlgorithms, string contextString, + TlsHandshakeHash handshakeHash, TlsCertificate certificate, CertificateVerify certificateVerify) + { // Verify the CertificateVerify message contains a correct signature. bool verified; try { - TlsVerifier verifier = verifyingCert.CreateVerifier(signatureScheme); + int signatureScheme = certificateVerify.Algorithm; + + SignatureAndHashAlgorithm algorithm = SignatureScheme.GetSignatureAndHashAlgorithm(signatureScheme); + VerifySupportedSignatureAlgorithm(supportedAlgorithms, algorithm); + + Tls13Verifier verifier = certificate.CreateVerifier(signatureScheme); + + byte[] header = GetCertificateVerifyHeader(contextString); + byte[] prfHash = GetCurrentPrfHash(handshakeHash); - verified = Verify13CertificateVerify(clientContext.Crypto, certificateVerify, verifier, - "TLS 1.3, server CertificateVerify", handshakeHash); + Stream output = verifier.Stream; + output.Write(header, 0, header.Length); + output.Write(prfHash, 0, prfHash.Length); + verified = verifier.VerifySignature(certificateVerify.Signature); } catch (TlsFatalAlert e) { @@ -2359,32 +2349,6 @@ namespace Org.BouncyCastle.Tls } } - private static bool Verify13CertificateVerify(TlsCrypto crypto, DigitallySigned certificateVerify, - TlsVerifier verifier, string contextString, TlsHandshakeHash handshakeHash) - { - TlsStreamVerifier streamVerifier = verifier.GetStreamVerifier(certificateVerify); - - byte[] header = GetCertificateVerifyHeader(contextString); - byte[] prfHash = GetCurrentPrfHash(handshakeHash); - - if (null != streamVerifier) - { - Stream output = streamVerifier.GetOutputStream(); - output.Write(header, 0, header.Length); - output.Write(prfHash, 0, prfHash.Length); - return streamVerifier.IsVerified(); - } - - int signatureScheme = SignatureScheme.From(certificateVerify.Algorithm); - int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); - - TlsHash tlsHash = crypto.CreateHash(cryptoHashAlgorithm); - tlsHash.Update(header, 0, header.Length); - tlsHash.Update(prfHash, 0, prfHash.Length); - byte[] hash = tlsHash.CalculateHash(); - return verifier.VerifyRawSignature(certificateVerify, hash); - } - private static byte[] GetCertificateVerifyHeader(string contextString) { int count = contextString.Length; @@ -2409,13 +2373,13 @@ namespace Org.BouncyCastle.Tls /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm algorithm = GetSignatureAndHashAlgorithm(context, credentials); + SignatureAndHashAlgorithm algorithm = GetSignatureAndHashAlgorithm(context.ServerVersion, credentials); TlsStreamSigner streamSigner = credentials.GetStreamSigner(); byte[] signature; if (streamSigner != null) { - SendSignatureInput(context, extraSignatureInput, digestBuffer, streamSigner.GetOutputStream()); + SendSignatureInput(context, extraSignatureInput, digestBuffer, streamSigner.Stream); signature = streamSigner.GetSignature(); } else @@ -2461,7 +2425,7 @@ namespace Org.BouncyCastle.Tls bool verified; if (streamVerifier != null) { - SendSignatureInput(context, null, digestBuffer, streamVerifier.GetOutputStream()); + SendSignatureInput(context, null, digestBuffer, streamVerifier.Stream); verified = streamVerifier.IsVerified(); } else @@ -2476,28 +2440,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(); } } } @@ -3896,14 +3860,6 @@ namespace Org.BouncyCastle.Tls && NamedGroup.CanBeNegotiated(keyShareGroup, negotiatedVersion); } - internal static bool IsValidSignatureAlgorithmForCertificateVerify(short signatureAlgorithm, - short[] clientCertificateTypes) - { - short clientCertificateType = SignatureAlgorithm.GetClientCertificateType(signatureAlgorithm); - - return clientCertificateType >= 0 && Arrays.Contains(clientCertificateTypes, clientCertificateType); - } - internal static bool IsValidSignatureAlgorithmForServerKeyExchange(short signatureAlgorithm, int keyExchangeAlgorithm) { @@ -4238,21 +4194,14 @@ namespace Org.BouncyCastle.Tls return handshakeHash.ForkPrfHash().CalculateHash(); } - internal static void SealHandshakeHash(TlsContext context, TlsHandshakeHash handshakeHash, bool forceBuffering) + private static TlsHash CreateHash(TlsCrypto crypto, short hashAlgorithm) { - if (forceBuffering || !context.Crypto.HasAllRawSignatureAlgorithms()) - { - handshakeHash.ForceBuffering(); - } - - handshakeHash.SealHashAlgorithms(); + return crypto.CreateHash(TlsCryptoUtilities.GetHash(hashAlgorithm)); } - private static TlsHash CreateHash(TlsCrypto crypto, short hashAlgorithm) + private static TlsHash CreateHash(TlsCrypto crypto, SignatureAndHashAlgorithm signatureAndHashAlgorithm) { - int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(hashAlgorithm); - - return crypto.CreateHash(cryptoHashAlgorithm); + return crypto.CreateHash(SignatureScheme.GetCryptoHashAlgorithm(signatureAndHashAlgorithm)); } /// <exception cref="IOException"/> @@ -4793,6 +4742,17 @@ namespace Org.BouncyCastle.Tls return (TlsCredentialedSigner)credentials; } + /// <exception cref="IOException"/> + private static void CheckClientCertificateType(CertificateRequest certificateRequest, + short clientCertificateType, short alertDescription) + { + if (clientCertificateType < 0 + || !Arrays.Contains(certificateRequest.CertificateTypes, clientCertificateType)) + { + throw new TlsFatalAlert(alertDescription); + } + } + private static void CheckDowngradeMarker(byte[] randomBlock, byte[] downgradeMarker) { int len = downgradeMarker.Length; @@ -4839,8 +4799,11 @@ namespace Org.BouncyCastle.Tls MemoryStream buf) { SecurityParameters securityParameters = clientContext.SecurityParameters; - if (null != securityParameters.PeerCertificate) + if (KeyExchangeAlgorithm.IsAnonymous(securityParameters.KeyExchangeAlgorithm) + || null != securityParameters.PeerCertificate) + { throw new TlsFatalAlert(AlertDescription.unexpected_message); + } MemoryStream endPointHash = new MemoryStream();