diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-05-05 17:09:14 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-05-05 17:09:14 +0700 |
commit | 66bea84d9d009eace8144628954a962601673f69 (patch) | |
tree | 1ed888c7d164f4229375e91289d75e436dc7f674 | |
parent | Change method to property (diff) | |
download | BouncyCastle.NET-ed25519-66bea84d9d009eace8144628954a962601673f69.tar.xz |
Rework TLS 1.3 verifiers
-rw-r--r-- | crypto/BouncyCastle.Android.csproj | 7 | ||||
-rw-r--r-- | crypto/BouncyCastle.csproj | 7 | ||||
-rw-r--r-- | crypto/BouncyCastle.iOS.csproj | 7 | ||||
-rw-r--r-- | crypto/crypto.csproj | 35 | ||||
-rw-r--r-- | crypto/src/tls/CertificateVerify.cs | 57 | ||||
-rw-r--r-- | crypto/src/tls/TlsClientProtocol.cs | 5 | ||||
-rw-r--r-- | crypto/src/tls/TlsServerProtocol.cs | 6 | ||||
-rw-r--r-- | crypto/src/tls/TlsUtilities.cs | 94 | ||||
-rw-r--r-- | crypto/src/tls/crypto/Tls13Verifier.cs | 14 | ||||
-rw-r--r-- | crypto/src/tls/crypto/TlsCertificate.cs | 2 | ||||
-rw-r--r-- | crypto/src/tls/crypto/TlsCryptoUtilities.cs | 29 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/LegacyTls13Verifier.cs | 60 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTls13Verifier.cs | 32 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsCertificate.cs | 106 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsECDsa13Verifier.cs | 40 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsEd25519Verifier.cs | 28 | ||||
-rw-r--r-- | crypto/src/tls/crypto/impl/bc/BcTlsEd448Verifier.cs | 28 | ||||
-rw-r--r-- | crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs | 21 |
18 files changed, 350 insertions, 228 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 3d84af346..9f584cd3b 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -1611,6 +1611,7 @@ <Compile Include="src\tls\CertificateStatusType.cs" /> <Compile Include="src\tls\CertificateType.cs" /> <Compile Include="src\tls\CertificateUrl.cs" /> + <Compile Include="src\tls\CertificateVerify.cs" /> <Compile Include="src\tls\ChangeCipherSpec.cs" /> <Compile Include="src\tls\ChannelBinding.cs" /> <Compile Include="src\tls\CipherSuite.cs" /> @@ -1633,6 +1634,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedDecryptor.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcSsl3Hmac.cs" /> + <Compile Include="src\tls\crypto\impl\bc\BcTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsAeadCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsBlockCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsCertificate.cs" /> @@ -1646,13 +1648,10 @@ <Compile Include="src\tls\crypto\impl\bc\BcTlsECDH.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDomain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaVerifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHash.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHmac.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsNonceGenerator.cs" /> @@ -1674,6 +1673,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcX25519Domain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448Domain.cs" /> + <Compile Include="src\tls\crypto\impl\LegacyTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\RsaUtilities.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipher.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipherImpl.cs" /> @@ -1685,6 +1685,7 @@ <Compile Include="src\tls\crypto\impl\TlsSuiteMac.cs" /> <Compile Include="src\tls\crypto\Srp6Group.cs" /> <Compile Include="src\tls\crypto\Srp6StandardGroups.cs" /> + <Compile Include="src\tls\crypto\Tls13Verifier.cs" /> <Compile Include="src\tls\crypto\TlsAgreement.cs" /> <Compile Include="src\tls\crypto\TlsCertificate.cs" /> <Compile Include="src\tls\crypto\TlsCertificateRole.cs" /> diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 84d7bf6fc..82ea19337 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -1605,6 +1605,7 @@ <Compile Include="src\tls\CertificateStatusType.cs" /> <Compile Include="src\tls\CertificateType.cs" /> <Compile Include="src\tls\CertificateUrl.cs" /> + <Compile Include="src\tls\CertificateVerify.cs" /> <Compile Include="src\tls\ChangeCipherSpec.cs" /> <Compile Include="src\tls\ChannelBinding.cs" /> <Compile Include="src\tls\CipherSuite.cs" /> @@ -1627,6 +1628,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedDecryptor.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcSsl3Hmac.cs" /> + <Compile Include="src\tls\crypto\impl\bc\BcTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsAeadCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsBlockCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsCertificate.cs" /> @@ -1640,13 +1642,10 @@ <Compile Include="src\tls\crypto\impl\bc\BcTlsECDH.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDomain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaVerifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHash.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHmac.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsNonceGenerator.cs" /> @@ -1668,6 +1667,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcX25519Domain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448Domain.cs" /> + <Compile Include="src\tls\crypto\impl\LegacyTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\RsaUtilities.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipher.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipherImpl.cs" /> @@ -1679,6 +1679,7 @@ <Compile Include="src\tls\crypto\impl\TlsSuiteMac.cs" /> <Compile Include="src\tls\crypto\Srp6Group.cs" /> <Compile Include="src\tls\crypto\Srp6StandardGroups.cs" /> + <Compile Include="src\tls\crypto\Tls13Verifier.cs" /> <Compile Include="src\tls\crypto\TlsAgreement.cs" /> <Compile Include="src\tls\crypto\TlsCertificate.cs" /> <Compile Include="src\tls\crypto\TlsCertificateRole.cs" /> diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index d76444e71..31ac62f93 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -1606,6 +1606,7 @@ <Compile Include="src\tls\CertificateStatusType.cs" /> <Compile Include="src\tls\CertificateType.cs" /> <Compile Include="src\tls\CertificateUrl.cs" /> + <Compile Include="src\tls\CertificateVerify.cs" /> <Compile Include="src\tls\ChangeCipherSpec.cs" /> <Compile Include="src\tls\ChannelBinding.cs" /> <Compile Include="src\tls\CipherSuite.cs" /> @@ -1628,6 +1629,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedDecryptor.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcDefaultTlsCredentialedSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcSsl3Hmac.cs" /> + <Compile Include="src\tls\crypto\impl\bc\BcTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsAeadCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsBlockCipherImpl.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsCertificate.cs" /> @@ -1641,13 +1643,10 @@ <Compile Include="src\tls\crypto\impl\bc\BcTlsECDH.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDomain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsa13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaSigner.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsECDsaVerifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd25519Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Signer.cs" /> - <Compile Include="src\tls\crypto\impl\bc\BcTlsEd448Verifier.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHash.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsHmac.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcTlsNonceGenerator.cs" /> @@ -1669,6 +1668,7 @@ <Compile Include="src\tls\crypto\impl\bc\BcX25519Domain.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448.cs" /> <Compile Include="src\tls\crypto\impl\bc\BcX448Domain.cs" /> + <Compile Include="src\tls\crypto\impl\LegacyTls13Verifier.cs" /> <Compile Include="src\tls\crypto\impl\RsaUtilities.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipher.cs" /> <Compile Include="src\tls\crypto\impl\TlsAeadCipherImpl.cs" /> @@ -1680,6 +1680,7 @@ <Compile Include="src\tls\crypto\impl\TlsSuiteMac.cs" /> <Compile Include="src\tls\crypto\Srp6Group.cs" /> <Compile Include="src\tls\crypto\Srp6StandardGroups.cs" /> + <Compile Include="src\tls\crypto\Tls13Verifier.cs" /> <Compile Include="src\tls\crypto\TlsAgreement.cs" /> <Compile Include="src\tls\crypto\TlsCertificate.cs" /> <Compile Include="src\tls\crypto\TlsCertificateRole.cs" /> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 092331032..1529174f1 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -7914,6 +7914,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\tls\CertificateVerify.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\tls\ChangeCipherSpec.cs" SubType = "Code" BuildAction = "Compile" @@ -8024,6 +8029,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\tls\crypto\impl\bc\BcTls13Verifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\tls\crypto\impl\bc\BcTlsAeadCipherImpl.cs" SubType = "Code" BuildAction = "Compile" @@ -8089,11 +8099,6 @@ BuildAction = "Compile" /> <File - RelPath = "src\tls\crypto\impl\bc\BcTlsECDsa13Verifier.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\tls\crypto\impl\bc\BcTlsECDsaSigner.cs" SubType = "Code" BuildAction = "Compile" @@ -8109,21 +8114,11 @@ BuildAction = "Compile" /> <File - RelPath = "src\tls\crypto\impl\bc\BcTlsEd25519Verifier.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\tls\crypto\impl\bc\BcTlsEd448Signer.cs" SubType = "Code" BuildAction = "Compile" /> <File - RelPath = "src\tls\crypto\impl\bc\BcTlsEd448Verifier.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\tls\crypto\impl\bc\BcTlsHash.cs" SubType = "Code" BuildAction = "Compile" @@ -8229,6 +8224,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\tls\crypto\impl\LegacyTls13Verifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\tls\crypto\impl\RsaUtilities.cs" SubType = "Code" BuildAction = "Compile" @@ -8284,6 +8284,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\tls\crypto\Tls13Verifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\tls\crypto\TlsAgreement.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/tls/CertificateVerify.cs b/crypto/src/tls/CertificateVerify.cs new file mode 100644 index 000000000..7c9f02735 --- /dev/null +++ b/crypto/src/tls/CertificateVerify.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Tls +{ + public sealed class CertificateVerify + { + private readonly int m_algorithm; + private readonly byte[] m_signature; + + public CertificateVerify(int algorithm, byte[] signature) + { + if (!TlsUtilities.IsValidUint16(algorithm)) + throw new ArgumentException("algorithm"); + if (signature == null) + throw new ArgumentNullException("signature"); + + this.m_algorithm = algorithm; + this.m_signature = signature; + } + + /// <returns>a <see cref="SignatureScheme"/> value.</returns> + public int Algorithm + { + get { return m_algorithm; } + } + + public byte[] Signature + { + get { return m_signature; } + } + + /// <summary>Encode this <see cref="CertificateVerify"/> to a <see cref="Stream"/>.</summary> + /// <param name="output">the <see cref="Stream"/> to encode to.</param> + /// <exception cref="IOException"/> + public void Encode(Stream output) + { + TlsUtilities.WriteUint16(m_algorithm, output); + TlsUtilities.WriteOpaque16(m_signature, output); + } + + /// <summary>Parse a <see cref="CertificateVerify"/> from a <see cref="Stream"/>.</summary> + /// <param name="context">the <see cref="TlsContext"/> of the current connection.</param> + /// <param name="input">the <see cref="Stream"/> to parse from.</param> + /// <returns>a <see cref="CertificateVerify"/> object.</returns> + /// <exception cref="IOException"/> + public static CertificateVerify Parse(TlsContext context, Stream input) + { + if (!TlsUtilities.IsTlsV13(context)) + throw new InvalidOperationException(); + + int algorithm = TlsUtilities.ReadUint16(input); + byte[] signature = TlsUtilities.ReadOpaque16(input); + return new CertificateVerify(algorithm, signature); + } + } +} diff --git a/crypto/src/tls/TlsClientProtocol.cs b/crypto/src/tls/TlsClientProtocol.cs index cb59289ae..89e7c4ba9 100644 --- a/crypto/src/tls/TlsClientProtocol.cs +++ b/crypto/src/tls/TlsClientProtocol.cs @@ -1467,12 +1467,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"/> diff --git a/crypto/src/tls/TlsServerProtocol.cs b/crypto/src/tls/TlsServerProtocol.cs index 0ab8a7a98..523fc0030 100644 --- a/crypto/src/tls/TlsServerProtocol.cs +++ b/crypto/src/tls/TlsServerProtocol.cs @@ -1281,13 +1281,11 @@ namespace Org.BouncyCastle.Tls if (null == clientCertificate || clientCertificate.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_tlsServerContext, buf); + CertificateVerify certificateVerify = CertificateVerify.Parse(m_tlsServerContext, buf); AssertEmpty(buf); - TlsUtilities.Verify13CertificateVerifyClient(m_tlsServerContext, m_certificateRequest, certificateVerify, - m_handshakeHash); + TlsUtilities.Verify13CertificateVerifyClient(m_tlsServerContext, m_handshakeHash, certificateVerify); } /// <exception cref="IOException"/> diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs index 13155d26e..0bee76c0a 100644 --- a/crypto/src/tls/TlsUtilities.cs +++ b/crypto/src/tls/TlsUtilities.cs @@ -2282,62 +2282,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); + IList supportedAlgorithms = securityParameters.ServerSigAlgs; + TlsCertificate certificate = securityParameters.PeerCertificate.GetCertificateAt(0); - 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); - } - - 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) { @@ -2354,32 +2346,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.Stream; - 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; diff --git a/crypto/src/tls/crypto/Tls13Verifier.cs b/crypto/src/tls/crypto/Tls13Verifier.cs new file mode 100644 index 000000000..143ea7394 --- /dev/null +++ b/crypto/src/tls/crypto/Tls13Verifier.cs @@ -0,0 +1,14 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Tls.Crypto +{ + public interface Tls13Verifier + { + /// <exception cref="IOException"/> + Stream Stream { get; } + + /// <exception cref="IOException"/> + bool VerifySignature(byte[] signature); + } +} diff --git a/crypto/src/tls/crypto/TlsCertificate.cs b/crypto/src/tls/crypto/TlsCertificate.cs index fe507a662..6b3e3220a 100644 --- a/crypto/src/tls/crypto/TlsCertificate.cs +++ b/crypto/src/tls/crypto/TlsCertificate.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Tls.Crypto /// <param name="signatureScheme"><see cref="SignatureScheme"/></param> /// <exception cref="IOException"/> - TlsVerifier CreateVerifier(int signatureScheme); + Tls13Verifier CreateVerifier(int signatureScheme); /// <exception cref="IOException"/> byte[] GetEncoded(); diff --git a/crypto/src/tls/crypto/TlsCryptoUtilities.cs b/crypto/src/tls/crypto/TlsCryptoUtilities.cs index 757eda1be..4ce48f738 100644 --- a/crypto/src/tls/crypto/TlsCryptoUtilities.cs +++ b/crypto/src/tls/crypto/TlsCryptoUtilities.cs @@ -1,6 +1,11 @@ using System; using System.IO; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; + namespace Org.BouncyCastle.Tls.Crypto { public abstract class TlsCryptoUtilities @@ -108,6 +113,30 @@ namespace Org.BouncyCastle.Tls.Crypto } } + public static DerObjectIdentifier GetOidForHash(int cryptoHashAlgorithm) + { + switch (cryptoHashAlgorithm) + { + case CryptoHashAlgorithm.md5: + return PkcsObjectIdentifiers.MD5; + case CryptoHashAlgorithm.sha1: + return X509ObjectIdentifiers.IdSha1; + case CryptoHashAlgorithm.sha224: + return NistObjectIdentifiers.IdSha224; + case CryptoHashAlgorithm.sha256: + return NistObjectIdentifiers.IdSha256; + case CryptoHashAlgorithm.sha384: + return NistObjectIdentifiers.IdSha384; + case CryptoHashAlgorithm.sha512: + return NistObjectIdentifiers.IdSha512; + // TODO[RFC 8998] + //case CryptoHashAlgorithm.sm3: + // return GMObjectIdentifiers.sm3; + default: + throw new ArgumentException(); + } + } + public static int GetSignature(short signatureAlgorithm) { switch (signatureAlgorithm) diff --git a/crypto/src/tls/crypto/impl/LegacyTls13Verifier.cs b/crypto/src/tls/crypto/impl/LegacyTls13Verifier.cs new file mode 100644 index 000000000..294a14da4 --- /dev/null +++ b/crypto/src/tls/crypto/impl/LegacyTls13Verifier.cs @@ -0,0 +1,60 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Tls.Crypto.Impl +{ + public sealed class LegacyTls13Verifier + : TlsVerifier + { + private readonly int m_signatureScheme; + private readonly Tls13Verifier m_tls13Verifier; + + public LegacyTls13Verifier(int signatureScheme, Tls13Verifier tls13Verifier) + { + if (!TlsUtilities.IsValidUint16(signatureScheme)) + throw new ArgumentException("signatureScheme"); + if (tls13Verifier == null) + throw new ArgumentNullException("tls13Verifier"); + + this.m_signatureScheme = signatureScheme; + this.m_tls13Verifier = tls13Verifier; + } + + public TlsStreamVerifier GetStreamVerifier(DigitallySigned digitallySigned) + { + SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm; + if (algorithm == null || SignatureScheme.From(algorithm) != m_signatureScheme) + throw new InvalidOperationException("Invalid algorithm: " + algorithm); + + return new TlsStreamVerifierImpl(m_tls13Verifier, digitallySigned.Signature); + } + + public bool VerifyRawSignature(DigitallySigned digitallySigned, byte[] hash) + { + throw new NotSupportedException(); + } + + private class TlsStreamVerifierImpl + : TlsStreamVerifier + { + private readonly Tls13Verifier m_tls13Verifier; + private readonly byte[] m_signature; + + internal TlsStreamVerifierImpl(Tls13Verifier tls13Verifier, byte[] signature) + { + this.m_tls13Verifier = tls13Verifier; + this.m_signature = signature; + } + + public Stream Stream + { + get { return m_tls13Verifier.Stream; } + } + + public bool IsVerified() + { + return m_tls13Verifier.VerifySignature(m_signature); + } + } + } +} diff --git a/crypto/src/tls/crypto/impl/bc/BcTls13Verifier.cs b/crypto/src/tls/crypto/impl/bc/BcTls13Verifier.cs new file mode 100644 index 000000000..ba4d0ccf8 --- /dev/null +++ b/crypto/src/tls/crypto/impl/bc/BcTls13Verifier.cs @@ -0,0 +1,32 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; + +namespace Org.BouncyCastle.Tls.Crypto.Impl.BC +{ + internal sealed class BcTls13Verifier + : Tls13Verifier + { + private readonly SignerSink m_output; + + internal BcTls13Verifier(ISigner verifier) + { + if (verifier == null) + throw new ArgumentNullException("verifier"); + + this.m_output = new SignerSink(verifier); + } + + public Stream Stream + { + get { return m_output; } + } + + public bool VerifySignature(byte[] signature) + { + return m_output.Signer.VerifySignature(signature); + } + } +} diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsCertificate.cs b/crypto/src/tls/crypto/impl/bc/BcTlsCertificate.cs index 469785dc2..7e946ce23 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsCertificate.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsCertificate.cs @@ -4,7 +4,9 @@ using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -87,38 +89,56 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC { switch (signatureAlgorithm) { - case SignatureAlgorithm.rsa_pss_rsae_sha256: - case SignatureAlgorithm.rsa_pss_rsae_sha384: - case SignatureAlgorithm.rsa_pss_rsae_sha512: case SignatureAlgorithm.ed25519: case SignatureAlgorithm.ed448: - case SignatureAlgorithm.rsa_pss_pss_sha256: - case SignatureAlgorithm.rsa_pss_pss_sha384: - case SignatureAlgorithm.rsa_pss_pss_sha512: - return CreateVerifier(SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm)); + { + int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm); + Tls13Verifier tls13Verifier = CreateVerifier(signatureScheme); + return new LegacyTls13Verifier(signatureScheme, tls13Verifier); + } } ValidateKeyUsage(KeyUsage.DigitalSignature); switch (signatureAlgorithm) { - case SignatureAlgorithm.rsa: - ValidateRsa_Pkcs1(); - return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa()); - case SignatureAlgorithm.dsa: return new BcTlsDsaVerifier(m_crypto, GetPubKeyDss()); case SignatureAlgorithm.ecdsa: return new BcTlsECDsaVerifier(m_crypto, GetPubKeyEC()); + case SignatureAlgorithm.rsa: + { + ValidateRsa_Pkcs1(); + return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa()); + } + + case SignatureAlgorithm.rsa_pss_pss_sha256: + case SignatureAlgorithm.rsa_pss_pss_sha384: + case SignatureAlgorithm.rsa_pss_pss_sha512: + { + ValidateRsa_Pss_Pss(signatureAlgorithm); + int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm); + return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); + } + + case SignatureAlgorithm.rsa_pss_rsae_sha256: + case SignatureAlgorithm.rsa_pss_rsae_sha384: + case SignatureAlgorithm.rsa_pss_rsae_sha512: + { + ValidateRsa_Pss_Rsae(); + int signatureScheme = SignatureScheme.From(HashAlgorithm.Intrinsic, signatureAlgorithm); + return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); + } + default: throw new TlsFatalAlert(AlertDescription.certificate_unknown); } } /// <exception cref="IOException"/> - public virtual TlsVerifier CreateVerifier(int signatureScheme) + public virtual Tls13Verifier CreateVerifier(int signatureScheme) { ValidateKeyUsage(KeyUsage.DigitalSignature); @@ -131,13 +151,31 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case SignatureScheme.ecdsa_secp384r1_sha384: case SignatureScheme.ecdsa_secp521r1_sha512: case SignatureScheme.ecdsa_sha1: - return new BcTlsECDsa13Verifier(m_crypto, GetPubKeyEC(), signatureScheme); + { + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); + IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); + + ISigner verifier = new DsaDigestSigner(new ECDsaSigner(), digest); + verifier.Init(false, GetPubKeyEC()); + + return new BcTls13Verifier(verifier); + } case SignatureScheme.ed25519: - return new BcTlsEd25519Verifier(m_crypto, GetPubKeyEd25519()); + { + Ed25519Signer verifier = new Ed25519Signer(); + verifier.Init(false, GetPubKeyEd25519()); + + return new BcTls13Verifier(verifier); + } case SignatureScheme.ed448: - return new BcTlsEd448Verifier(m_crypto, GetPubKeyEd448()); + { + Ed448Signer verifier = new Ed448Signer(TlsUtilities.EmptyBytes); + verifier.Init(false, GetPubKeyEd448()); + + return new BcTls13Verifier(verifier); + } case SignatureScheme.rsa_pkcs1_sha1: case SignatureScheme.rsa_pkcs1_sha256: @@ -145,7 +183,15 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case SignatureScheme.rsa_pkcs1_sha512: { ValidateRsa_Pkcs1(); - return new BcTlsRsaVerifier(m_crypto, GetPubKeyRsa()); + + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); + IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); + + RsaDigestSigner verifier = new RsaDigestSigner(digest, + TlsCryptoUtilities.GetOidForHash(cryptoHashAlgorithm)); + verifier.Init(false, GetPubKeyRsa()); + + return new BcTls13Verifier(verifier); } case SignatureScheme.rsa_pss_pss_sha256: @@ -153,7 +199,14 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case SignatureScheme.rsa_pss_pss_sha512: { ValidateRsa_Pss_Pss(SignatureScheme.GetSignatureAlgorithm(signatureScheme)); - return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); + + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); + IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); + + PssSigner verifier = new PssSigner(new RsaEngine(), digest, digest.GetDigestSize()); + verifier.Init(false, GetPubKeyRsa()); + + return new BcTls13Verifier(verifier); } case SignatureScheme.rsa_pss_rsae_sha256: @@ -161,12 +214,27 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC case SignatureScheme.rsa_pss_rsae_sha512: { ValidateRsa_Pss_Rsae(); - return new BcTlsRsaPssVerifier(m_crypto, GetPubKeyRsa(), signatureScheme); + + int cryptoHashAlgorithm = SignatureScheme.GetCryptoHashAlgorithm(signatureScheme); + IDigest digest = m_crypto.CreateDigest(cryptoHashAlgorithm); + + PssSigner verifier = new PssSigner(new RsaEngine(), digest, digest.GetDigestSize()); + verifier.Init(false, GetPubKeyRsa()); + + return new BcTls13Verifier(verifier); } // TODO[RFC 8998] //case SignatureScheme.sm2sig_sm3: - // return new BcTlsSM2Verifier(m_crypto, GetPubKeyEC(), Strings.ToByteArray("TLSv1.3+GM+Cipher+Suite")); + //{ + // ParametersWithID parametersWithID = new ParametersWithID(GetPubKeyEC(), + // Strings.ToByteArray("TLSv1.3+GM+Cipher+Suite")); + + // SM2Signer verifier = new SM2Signer(); + // verifier.Init(false, parametersWithID); + + // return new BcTls13Verifier(verifier); + //} default: throw new TlsFatalAlert(AlertDescription.certificate_unknown); diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsECDsa13Verifier.cs b/crypto/src/tls/crypto/impl/bc/BcTlsECDsa13Verifier.cs deleted file mode 100644 index 159b17c0b..000000000 --- a/crypto/src/tls/crypto/impl/bc/BcTlsECDsa13Verifier.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Crypto.Signers; - -namespace Org.BouncyCastle.Tls.Crypto.Impl.BC -{ - /// <summary>Implementation class for verification of ECDSA signatures in TLS 1.3+ using the BC light-weight API. - /// </summary> - public class BcTlsECDsa13Verifier - : BcTlsVerifier - { - private readonly int m_signatureScheme; - - public BcTlsECDsa13Verifier(BcTlsCrypto crypto, ECPublicKeyParameters publicKey, int signatureScheme) - : base(crypto, publicKey) - { - if (!SignatureScheme.IsECDsa(signatureScheme)) - throw new ArgumentException("signatureScheme"); - - this.m_signatureScheme = signatureScheme; - } - - public override bool VerifyRawSignature(DigitallySigned digitallySigned, byte[] hash) - { - SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm; - if (algorithm == null || SignatureScheme.From(algorithm) != m_signatureScheme) - throw new InvalidOperationException("Invalid algorithm: " + algorithm); - - IDsa dsa = new ECDsaSigner(); - - ISigner signer = new DsaDigestSigner(dsa, new NullDigest()); - signer.Init(false, m_publicKey); - signer.BlockUpdate(hash, 0, hash.Length); - return signer.VerifySignature(digitallySigned.Signature); - } - } -} diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsEd25519Verifier.cs b/crypto/src/tls/crypto/impl/bc/BcTlsEd25519Verifier.cs deleted file mode 100644 index a787bb92a..000000000 --- a/crypto/src/tls/crypto/impl/bc/BcTlsEd25519Verifier.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Crypto.Signers; - -namespace Org.BouncyCastle.Tls.Crypto.Impl.BC -{ - public class BcTlsEd25519Verifier - : BcTlsVerifier - { - public BcTlsEd25519Verifier(BcTlsCrypto crypto, Ed25519PublicKeyParameters publicKey) - : base(crypto, publicKey) - { - } - - public override TlsStreamVerifier GetStreamVerifier(DigitallySigned digitallySigned) - { - SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm; - if (algorithm == null || SignatureScheme.From(algorithm) != SignatureScheme.ed25519) - throw new InvalidOperationException("Invalid algorithm: " + algorithm); - - Ed25519Signer verifier = new Ed25519Signer(); - verifier.Init(false, m_publicKey); - - return new BcTlsStreamVerifier(verifier, digitallySigned.Signature); - } - } -} diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsEd448Verifier.cs b/crypto/src/tls/crypto/impl/bc/BcTlsEd448Verifier.cs deleted file mode 100644 index 7940d0757..000000000 --- a/crypto/src/tls/crypto/impl/bc/BcTlsEd448Verifier.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Crypto.Signers; - -namespace Org.BouncyCastle.Tls.Crypto.Impl.BC -{ - public class BcTlsEd448Verifier - : BcTlsVerifier - { - public BcTlsEd448Verifier(BcTlsCrypto crypto, Ed448PublicKeyParameters publicKey) - : base(crypto, publicKey) - { - } - - public override TlsStreamVerifier GetStreamVerifier(DigitallySigned digitallySigned) - { - SignatureAndHashAlgorithm algorithm = digitallySigned.Algorithm; - if (algorithm == null || SignatureScheme.From(algorithm) != SignatureScheme.ed448) - throw new InvalidOperationException("Invalid algorithm: " + algorithm); - - Ed448Signer verifier = new Ed448Signer(TlsUtilities.EmptyBytes); - verifier.Init(false, m_publicKey); - - return new BcTlsStreamVerifier(verifier, digitallySigned.Signature); - } - } -} diff --git a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs index 494175261..9e2679fbb 100644 --- a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs +++ b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs @@ -752,25 +752,12 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests signature = credentialedSigner.GenerateRawSignature(hash); } - DigitallySigned digitallySigned = new DigitallySigned( - SignatureScheme.GetSignatureAndHashAlgorithm(signatureScheme), signature); - TlsCertificate tlsCertificate = credentialedSigner.Certificate.GetCertificateAt(0); - TlsVerifier tlsVerifier = tlsCertificate.CreateVerifier(signatureScheme); + Tls13Verifier tls13Verifier = tlsCertificate.CreateVerifier(signatureScheme); - bool verified; - TlsStreamVerifier tlsStreamVerifier = tlsVerifier.GetStreamVerifier(digitallySigned); - if (null != tlsStreamVerifier) - { - Stream output = tlsStreamVerifier.Stream; - output.Write(message, 0, message.Length); - verified = tlsStreamVerifier.IsVerified(); - } - else - { - byte[] hash = ImplPrehash(signatureScheme, message); - verified = tlsVerifier.VerifyRawSignature(digitallySigned, hash); - } + Stream output13 = tls13Verifier.Stream; + output13.Write(message, 0, message.Length); + bool verified = tls13Verifier.VerifySignature(signature); Assert.IsTrue(verified); } |