diff options
author | Jeffrey Stedfast <jeff@xamarin.com> | 2015-03-14 09:21:16 -0400 |
---|---|---|
committer | Jeffrey Stedfast <jeff@xamarin.com> | 2015-03-14 09:21:16 -0400 |
commit | 5f446e15a61331939d37d0a62c72384e19b8a806 (patch) | |
tree | 6685f0f70604121f59b258d62e3efa63256053a6 | |
parent | Merge branch 'master' into vs2010 (diff) | |
parent | Update TLS for draft-ietf-tls-session-hash-04 (diff) | |
download | BouncyCastle.NET-ed25519-5f446e15a61331939d37d0a62c72384e19b8a806.tar.xz |
Merge branch 'master' into vs2010
171 files changed, 6465 insertions, 2526 deletions
diff --git a/.gitattributes b/.gitattributes index 31e8a5ac4..edfb7e9ef 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,7 +13,8 @@ *.nunit text diff=xml *.pem text *.README text -*.sln text eol=crlf +*.sln text +*.tmpl text *.txt text *.xml text diff=xml @@ -23,6 +24,7 @@ *.crl binary *.crt binary *.data binary +*.dll binary *.dsa binary *.jpg binary *.jpeg binary diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index db03b75be..8a201b824 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -614,6 +614,7 @@ <Compile Include="src\crypto\BufferedCipherBase.cs" /> <Compile Include="src\crypto\BufferedIesCipher.cs" /> <Compile Include="src\crypto\BufferedStreamCipher.cs" /> + <Compile Include="src\crypto\Check.cs" /> <Compile Include="src\crypto\CipherKeyGenerator.cs" /> <Compile Include="src\crypto\CryptoException.cs" /> <Compile Include="src\crypto\DataLengthException.cs" /> @@ -635,6 +636,7 @@ <Compile Include="src\crypto\InvalidCipherTextException.cs" /> <Compile Include="src\crypto\KeyGenerationParameters.cs" /> <Compile Include="src\crypto\MaxBytesExceededException.cs" /> + <Compile Include="src\crypto\OutputLengthException.cs" /> <Compile Include="src\crypto\PbeParametersGenerator.cs" /> <Compile Include="src\crypto\StreamBlockCipher.cs" /> <Compile Include="src\crypto\agreement\DHAgreement.cs" /> @@ -650,6 +652,7 @@ <Compile Include="src\crypto\agreement\kdf\ECDHKekGenerator.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Client.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Server.cs" /> + <Compile Include="src\crypto\agreement\srp\SRP6StandardGroups.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Utilities.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6VerifierGenerator.cs" /> <Compile Include="src\crypto\digests\GOST3411Digest.cs" /> @@ -854,6 +857,7 @@ <Compile Include="src\crypto\parameters\RsaKeyParameters.cs" /> <Compile Include="src\crypto\parameters\RsaPrivateCrtKeyParameters.cs" /> <Compile Include="src\crypto\parameters\SkeinParameters.cs" /> + <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> @@ -876,6 +880,7 @@ <Compile Include="src\crypto\signers\PssSigner.cs" /> <Compile Include="src\crypto\signers\RandomDsaKCalculator.cs" /> <Compile Include="src\crypto\signers\RsaDigestSigner.cs" /> + <Compile Include="src\crypto\signers\X931Signer.cs" /> <Compile Include="src\crypto\tls\AbstractTlsAgreementCredentials.cs" /> <Compile Include="src\crypto\tls\AbstractTlsCipherFactory.cs" /> <Compile Include="src\crypto\tls\AbstractTlsClient.cs" /> @@ -889,6 +894,7 @@ <Compile Include="src\crypto\tls\AbstractTlsSignerCredentials.cs" /> <Compile Include="src\crypto\tls\AlertDescription.cs" /> <Compile Include="src\crypto\tls\AlertLevel.cs" /> + <Compile Include="src\crypto\tls\BasicTlsPskIdentity.cs" /> <Compile Include="src\crypto\tls\BulkCipherAlgorithm.cs" /> <Compile Include="src\crypto\tls\ByteQueue.cs" /> <Compile Include="src\crypto\tls\CertChainType.cs" /> @@ -915,6 +921,7 @@ <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" /> <Compile Include="src\crypto\tls\DefaultTlsServer.cs" /> <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\DefaultTlsSrpGroupVerifier.cs" /> <Compile Include="src\crypto\tls\DeferredHash.cs" /> <Compile Include="src\crypto\tls\DigestInputBuffer.cs" /> <Compile Include="src\crypto\tls\DigitallySigned.cs" /> @@ -951,17 +958,21 @@ <Compile Include="src\crypto\tls\PrfAlgorithm.cs" /> <Compile Include="src\crypto\tls\ProtocolVersion.cs" /> <Compile Include="src\crypto\tls\PskTlsClient.cs" /> + <Compile Include="src\crypto\tls\PskTlsServer.cs" /> <Compile Include="src\crypto\tls\RecordStream.cs" /> <Compile Include="src\crypto\tls\SecurityParameters.cs" /> <Compile Include="src\crypto\tls\ServerDHParams.cs" /> <Compile Include="src\crypto\tls\ServerName.cs" /> <Compile Include="src\crypto\tls\ServerNameList.cs" /> <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" /> + <Compile Include="src\crypto\tls\ServerSrpParams.cs" /> <Compile Include="src\crypto\tls\SessionParameters.cs" /> <Compile Include="src\crypto\tls\SignatureAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignatureAndHashAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignerInputBuffer.cs" /> + <Compile Include="src\crypto\tls\SimulatedTlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\SrpTlsClient.cs" /> + <Compile Include="src\crypto\tls\SrpTlsServer.cs" /> <Compile Include="src\crypto\tls\SrtpProtectionProfile.cs" /> <Compile Include="src\crypto\tls\Ssl3Mac.cs" /> <Compile Include="src\crypto\tls\SupplementalDataEntry.cs" /> @@ -1014,7 +1025,10 @@ <Compile Include="src\crypto\tls\TlsSessionImpl.cs" /> <Compile Include="src\crypto\tls\TlsSigner.cs" /> <Compile Include="src\crypto\tls\TlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\TlsSrpGroupVerifier.cs" /> + <Compile Include="src\crypto\tls\TlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\TlsSrpKeyExchange.cs" /> + <Compile Include="src\crypto\tls\TlsSrpLoginParameters.cs" /> <Compile Include="src\crypto\tls\TlsSrpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsSrtpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsStream.cs" /> diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 1a43de126..ee05e159a 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -608,6 +608,7 @@ <Compile Include="src\crypto\BufferedCipherBase.cs" /> <Compile Include="src\crypto\BufferedIesCipher.cs" /> <Compile Include="src\crypto\BufferedStreamCipher.cs" /> + <Compile Include="src\crypto\Check.cs" /> <Compile Include="src\crypto\CipherKeyGenerator.cs" /> <Compile Include="src\crypto\CryptoException.cs" /> <Compile Include="src\crypto\DataLengthException.cs" /> @@ -629,6 +630,7 @@ <Compile Include="src\crypto\InvalidCipherTextException.cs" /> <Compile Include="src\crypto\KeyGenerationParameters.cs" /> <Compile Include="src\crypto\MaxBytesExceededException.cs" /> + <Compile Include="src\crypto\OutputLengthException.cs" /> <Compile Include="src\crypto\PbeParametersGenerator.cs" /> <Compile Include="src\crypto\StreamBlockCipher.cs" /> <Compile Include="src\crypto\agreement\DHAgreement.cs" /> @@ -644,6 +646,7 @@ <Compile Include="src\crypto\agreement\kdf\ECDHKekGenerator.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Client.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Server.cs" /> + <Compile Include="src\crypto\agreement\srp\SRP6StandardGroups.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Utilities.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6VerifierGenerator.cs" /> <Compile Include="src\crypto\digests\GOST3411Digest.cs" /> @@ -848,6 +851,7 @@ <Compile Include="src\crypto\parameters\RsaKeyParameters.cs" /> <Compile Include="src\crypto\parameters\RsaPrivateCrtKeyParameters.cs" /> <Compile Include="src\crypto\parameters\SkeinParameters.cs" /> + <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> @@ -870,6 +874,7 @@ <Compile Include="src\crypto\signers\PssSigner.cs" /> <Compile Include="src\crypto\signers\RandomDsaKCalculator.cs" /> <Compile Include="src\crypto\signers\RsaDigestSigner.cs" /> + <Compile Include="src\crypto\signers\X931Signer.cs" /> <Compile Include="src\crypto\tls\AbstractTlsAgreementCredentials.cs" /> <Compile Include="src\crypto\tls\AbstractTlsCipherFactory.cs" /> <Compile Include="src\crypto\tls\AbstractTlsClient.cs" /> @@ -883,6 +888,7 @@ <Compile Include="src\crypto\tls\AbstractTlsSignerCredentials.cs" /> <Compile Include="src\crypto\tls\AlertDescription.cs" /> <Compile Include="src\crypto\tls\AlertLevel.cs" /> + <Compile Include="src\crypto\tls\BasicTlsPskIdentity.cs" /> <Compile Include="src\crypto\tls\BulkCipherAlgorithm.cs" /> <Compile Include="src\crypto\tls\ByteQueue.cs" /> <Compile Include="src\crypto\tls\CertChainType.cs" /> @@ -909,6 +915,7 @@ <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" /> <Compile Include="src\crypto\tls\DefaultTlsServer.cs" /> <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\DefaultTlsSrpGroupVerifier.cs" /> <Compile Include="src\crypto\tls\DeferredHash.cs" /> <Compile Include="src\crypto\tls\DigestInputBuffer.cs" /> <Compile Include="src\crypto\tls\DigitallySigned.cs" /> @@ -945,17 +952,21 @@ <Compile Include="src\crypto\tls\PrfAlgorithm.cs" /> <Compile Include="src\crypto\tls\ProtocolVersion.cs" /> <Compile Include="src\crypto\tls\PskTlsClient.cs" /> + <Compile Include="src\crypto\tls\PskTlsServer.cs" /> <Compile Include="src\crypto\tls\RecordStream.cs" /> <Compile Include="src\crypto\tls\SecurityParameters.cs" /> <Compile Include="src\crypto\tls\ServerDHParams.cs" /> <Compile Include="src\crypto\tls\ServerName.cs" /> <Compile Include="src\crypto\tls\ServerNameList.cs" /> <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" /> + <Compile Include="src\crypto\tls\ServerSrpParams.cs" /> <Compile Include="src\crypto\tls\SessionParameters.cs" /> <Compile Include="src\crypto\tls\SignatureAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignatureAndHashAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignerInputBuffer.cs" /> + <Compile Include="src\crypto\tls\SimulatedTlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\SrpTlsClient.cs" /> + <Compile Include="src\crypto\tls\SrpTlsServer.cs" /> <Compile Include="src\crypto\tls\SrtpProtectionProfile.cs" /> <Compile Include="src\crypto\tls\Ssl3Mac.cs" /> <Compile Include="src\crypto\tls\SupplementalDataEntry.cs" /> @@ -1008,7 +1019,10 @@ <Compile Include="src\crypto\tls\TlsSessionImpl.cs" /> <Compile Include="src\crypto\tls\TlsSigner.cs" /> <Compile Include="src\crypto\tls\TlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\TlsSrpGroupVerifier.cs" /> + <Compile Include="src\crypto\tls\TlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\TlsSrpKeyExchange.cs" /> + <Compile Include="src\crypto\tls\TlsSrpLoginParameters.cs" /> <Compile Include="src\crypto\tls\TlsSrpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsSrtpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsStream.cs" /> diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 45a7dfaab..7e6830fe6 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -609,6 +609,7 @@ <Compile Include="src\crypto\BufferedCipherBase.cs" /> <Compile Include="src\crypto\BufferedIesCipher.cs" /> <Compile Include="src\crypto\BufferedStreamCipher.cs" /> + <Compile Include="src\crypto\Check.cs" /> <Compile Include="src\crypto\CipherKeyGenerator.cs" /> <Compile Include="src\crypto\CryptoException.cs" /> <Compile Include="src\crypto\DataLengthException.cs" /> @@ -630,6 +631,7 @@ <Compile Include="src\crypto\InvalidCipherTextException.cs" /> <Compile Include="src\crypto\KeyGenerationParameters.cs" /> <Compile Include="src\crypto\MaxBytesExceededException.cs" /> + <Compile Include="src\crypto\OutputLengthException.cs" /> <Compile Include="src\crypto\PbeParametersGenerator.cs" /> <Compile Include="src\crypto\StreamBlockCipher.cs" /> <Compile Include="src\crypto\agreement\DHAgreement.cs" /> @@ -645,6 +647,7 @@ <Compile Include="src\crypto\agreement\kdf\ECDHKekGenerator.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Client.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Server.cs" /> + <Compile Include="src\crypto\agreement\srp\SRP6StandardGroups.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6Utilities.cs" /> <Compile Include="src\crypto\agreement\srp\SRP6VerifierGenerator.cs" /> <Compile Include="src\crypto\digests\GOST3411Digest.cs" /> @@ -849,6 +852,7 @@ <Compile Include="src\crypto\parameters\RsaKeyParameters.cs" /> <Compile Include="src\crypto\parameters\RsaPrivateCrtKeyParameters.cs" /> <Compile Include="src\crypto\parameters\SkeinParameters.cs" /> + <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> @@ -871,6 +875,7 @@ <Compile Include="src\crypto\signers\PssSigner.cs" /> <Compile Include="src\crypto\signers\RandomDsaKCalculator.cs" /> <Compile Include="src\crypto\signers\RsaDigestSigner.cs" /> + <Compile Include="src\crypto\signers\X931Signer.cs" /> <Compile Include="src\crypto\tls\AbstractTlsAgreementCredentials.cs" /> <Compile Include="src\crypto\tls\AbstractTlsCipherFactory.cs" /> <Compile Include="src\crypto\tls\AbstractTlsClient.cs" /> @@ -884,6 +889,7 @@ <Compile Include="src\crypto\tls\AbstractTlsSignerCredentials.cs" /> <Compile Include="src\crypto\tls\AlertDescription.cs" /> <Compile Include="src\crypto\tls\AlertLevel.cs" /> + <Compile Include="src\crypto\tls\BasicTlsPskIdentity.cs" /> <Compile Include="src\crypto\tls\BulkCipherAlgorithm.cs" /> <Compile Include="src\crypto\tls\ByteQueue.cs" /> <Compile Include="src\crypto\tls\CertChainType.cs" /> @@ -910,6 +916,7 @@ <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" /> <Compile Include="src\crypto\tls\DefaultTlsServer.cs" /> <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\DefaultTlsSrpGroupVerifier.cs" /> <Compile Include="src\crypto\tls\DeferredHash.cs" /> <Compile Include="src\crypto\tls\DigestInputBuffer.cs" /> <Compile Include="src\crypto\tls\DigitallySigned.cs" /> @@ -946,17 +953,21 @@ <Compile Include="src\crypto\tls\PrfAlgorithm.cs" /> <Compile Include="src\crypto\tls\ProtocolVersion.cs" /> <Compile Include="src\crypto\tls\PskTlsClient.cs" /> + <Compile Include="src\crypto\tls\PskTlsServer.cs" /> <Compile Include="src\crypto\tls\RecordStream.cs" /> <Compile Include="src\crypto\tls\SecurityParameters.cs" /> <Compile Include="src\crypto\tls\ServerDHParams.cs" /> <Compile Include="src\crypto\tls\ServerName.cs" /> <Compile Include="src\crypto\tls\ServerNameList.cs" /> <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" /> + <Compile Include="src\crypto\tls\ServerSrpParams.cs" /> <Compile Include="src\crypto\tls\SessionParameters.cs" /> <Compile Include="src\crypto\tls\SignatureAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignatureAndHashAlgorithm.cs" /> <Compile Include="src\crypto\tls\SignerInputBuffer.cs" /> + <Compile Include="src\crypto\tls\SimulatedTlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\SrpTlsClient.cs" /> + <Compile Include="src\crypto\tls\SrpTlsServer.cs" /> <Compile Include="src\crypto\tls\SrtpProtectionProfile.cs" /> <Compile Include="src\crypto\tls\Ssl3Mac.cs" /> <Compile Include="src\crypto\tls\SupplementalDataEntry.cs" /> @@ -1009,7 +1020,10 @@ <Compile Include="src\crypto\tls\TlsSessionImpl.cs" /> <Compile Include="src\crypto\tls\TlsSigner.cs" /> <Compile Include="src\crypto\tls\TlsSignerCredentials.cs" /> + <Compile Include="src\crypto\tls\TlsSrpGroupVerifier.cs" /> + <Compile Include="src\crypto\tls\TlsSrpIdentityManager.cs" /> <Compile Include="src\crypto\tls\TlsSrpKeyExchange.cs" /> + <Compile Include="src\crypto\tls\TlsSrpLoginParameters.cs" /> <Compile Include="src\crypto\tls\TlsSrpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsSrtpUtilities.cs" /> <Compile Include="src\crypto\tls\TlsStream.cs" /> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index fdd5c152b..35474aebb 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -2964,6 +2964,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\Check.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\CipherKeyGenerator.cs" SubType = "Code" BuildAction = "Compile" @@ -3069,6 +3074,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\OutputLengthException.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\PBEParametersGenerator.cs" SubType = "Code" BuildAction = "Compile" @@ -3144,6 +3154,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\agreement\srp\SRP6StandardGroups.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\agreement\srp\SRP6Utilities.cs" SubType = "Code" BuildAction = "Compile" @@ -4164,6 +4179,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\parameters\Srp6GroupParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\parameters\TweakableBlockCipherParameters.cs" SubType = "Code" BuildAction = "Compile" @@ -4274,6 +4294,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\signers\X931Signer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\AbstractTlsAgreementCredentials.cs" SubType = "Code" BuildAction = "Compile" @@ -4469,6 +4494,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\DefaultTlsSrpGroupVerifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\DefaultTlsSignerCredentials.cs" SubType = "Code" BuildAction = "Compile" @@ -4674,6 +4704,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\ServerSrpParams.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\ServerName.cs" SubType = "Code" BuildAction = "Compile" @@ -4709,11 +4744,21 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\SimulatedTlsSrpIdentityManager.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\SrpTlsClient.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\SrpTlsServer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\SrtpProtectionProfile.cs" SubType = "Code" BuildAction = "Compile" @@ -4974,6 +5019,21 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\tls\TlsSrpGroupVerifier.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\tls\TlsSrpIdentityManager.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\tls\TlsSrpLoginParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\tls\TlsSrpKeyExchange.cs" SubType = "Code" BuildAction = "Compile" @@ -9904,11 +9964,23 @@ BuildAction = "EmbeddedResource" /> <File + RelPath = "test\data\tls\x509-ca.pem" + BuildAction = "EmbeddedResource" + /> + <File RelPath = "test\data\tls\x509-ca-key.pem" BuildAction = "EmbeddedResource" /> <File - RelPath = "test\data\tls\x509-ca.pem" + RelPath = "test\data\tls\x509-client.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-client-dsa.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-client-ecdsa.pem" BuildAction = "EmbeddedResource" /> <File @@ -9916,11 +9988,11 @@ BuildAction = "EmbeddedResource" /> <File - RelPath = "test\data\tls\x509-client.pem" + RelPath = "test\data\tls\x509-client-key-dsa.pem" BuildAction = "EmbeddedResource" /> <File - RelPath = "test\data\tls\x509-server-key.pem" + RelPath = "test\data\tls\x509-client-key-ecdsa.pem" BuildAction = "EmbeddedResource" /> <File @@ -9928,6 +10000,26 @@ BuildAction = "EmbeddedResource" /> <File + RelPath = "test\data\tls\x509-server-dsa.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-server-ecdsa.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-server-key.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-server-key-dsa.pem" + BuildAction = "EmbeddedResource" + /> + <File + RelPath = "test\data\tls\x509-server-key-ecdsa.pem" + BuildAction = "EmbeddedResource" + /> + <File RelPath = "test\data\tls\keystores\client_store.dsa" BuildAction = "EmbeddedResource" /> @@ -10981,6 +11073,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\test\X931SignerTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\test\XSalsa20Test.cs" SubType = "Code" BuildAction = "Compile" @@ -10991,6 +11088,61 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\DtlsProtocolTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\DtlsTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\DtlsTestSuite.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\LoggingDatagramTransport.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockDatagramAssociation.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockDtlsClient.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockDtlsServer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockPskTlsClient.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockPskTlsServer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockSrpTlsClient.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\MockSrpTlsServer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\MockTlsClient.cs" SubType = "Code" BuildAction = "Compile" @@ -11001,21 +11153,81 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\NetworkStream.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\PipedStream.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\PskTlsClientTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\TlsClientTest.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\TlsProtocolTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsPskProtocolTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsSrpProtocolTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\TlsServerTest.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\TlsTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsTestClientImpl.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsTestConfig.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsTestServerImpl.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\tls\test\TlsTestSuite.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\tls\test\TlsTestUtilities.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\tls\test\UnreliableDatagramTransport.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\math\ec\test\AllTests.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/bcpg/S2k.cs b/crypto/src/bcpg/S2k.cs index de08c016c..f6d306890 100644 --- a/crypto/src/bcpg/S2k.cs +++ b/crypto/src/bcpg/S2k.cs @@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Bcpg public const int Salted = 1; public const int SaltedAndIterated = 3; public const int GnuDummyS2K = 101; + public const int GnuProtectionModeNoPrivateKey = 1; + public const int GnuProtectionModeDivertToCard = 2; internal int type; internal HashAlgorithmTag algorithm; diff --git a/crypto/src/crypto/BufferedAeadBlockCipher.cs b/crypto/src/crypto/BufferedAeadBlockCipher.cs index 04bcb88ed..7ba41090f 100644 --- a/crypto/src/crypto/BufferedAeadBlockCipher.cs +++ b/crypto/src/crypto/BufferedAeadBlockCipher.cs @@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/crypto/BufferedBlockCipher.cs b/crypto/src/crypto/BufferedBlockCipher.cs index 3a98798a2..c87d2daf9 100644 --- a/crypto/src/crypto/BufferedBlockCipher.cs +++ b/crypto/src/crypto/BufferedBlockCipher.cs @@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. @@ -223,13 +223,10 @@ namespace Org.BouncyCastle.Crypto if (outLength > 0) { - if ((outOff + outLength) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.OutputLength(output, outOff, outLength, "output buffer too short"); } - int resultLen = 0; + int resultLen = 0; int gapLen = buf.Length - bufOff; if (length > gapLen) { @@ -339,17 +336,10 @@ namespace Org.BouncyCastle.Crypto { if (bufOff != 0) { - if (!cipher.IsPartialBlockOkay) - { - throw new DataLengthException("data not block size aligned"); - } - - if (outOff + bufOff > output.Length) - { - throw new DataLengthException("output buffer too short for DoFinal()"); - } - - // NB: Can't copy directly, or we may write too much output + Check.DataLength(!cipher.IsPartialBlockOkay, "data not block size aligned"); + Check.OutputLength(output, outOff, bufOff, "output buffer too short for DoFinal()"); + + // NB: Can't copy directly, or we may write too much output cipher.ProcessBlock(buf, 0, buf, 0); Array.Copy(buf, 0, output, outOff, bufOff); } diff --git a/crypto/src/crypto/Check.cs b/crypto/src/crypto/Check.cs new file mode 100644 index 000000000..96a05c64b --- /dev/null +++ b/crypto/src/crypto/Check.cs @@ -0,0 +1,25 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + internal class Check + { + internal static void DataLength(bool condition, string msg) + { + if (condition) + throw new DataLengthException(msg); + } + + internal static void DataLength(byte[] buf, int off, int len, string msg) + { + if (off + len > buf.Length) + throw new DataLengthException(msg); + } + + internal static void OutputLength(byte[] buf, int off, int len, string msg) + { + if (off + len > buf.Length) + throw new OutputLengthException(msg); + } + } +} diff --git a/crypto/src/crypto/OutputLengthException.cs b/crypto/src/crypto/OutputLengthException.cs new file mode 100644 index 000000000..e1cf44925 --- /dev/null +++ b/crypto/src/crypto/OutputLengthException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class OutputLengthException + : DataLengthException + { + public OutputLengthException() + { + } + + public OutputLengthException( + string message) + : base(message) + { + } + + public OutputLengthException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6Client.cs b/crypto/src/crypto/agreement/srp/SRP6Client.cs index 309736564..f075d7ad1 100644 --- a/crypto/src/crypto/agreement/srp/SRP6Client.cs +++ b/crypto/src/crypto/agreement/srp/SRP6Client.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; @@ -24,7 +25,11 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp protected BigInteger u; protected BigInteger S; - protected IDigest digest; + protected BigInteger M1; + protected BigInteger M2; + protected BigInteger Key; + + protected IDigest digest; protected SecureRandom random; public Srp6Client() @@ -46,6 +51,11 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp this.random = random; } + public virtual void Init(Srp6GroupParameters group, IDigest digest, SecureRandom random) + { + Init(group.N, group.G, digest, random); + } + /** * Generates client's credentials given the client's salt, identity and password * @param salt The salt used in the client's verifier. @@ -89,5 +99,66 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N); return B.Subtract(tmp).Mod(N).ModPow(exp, N); } + + /** + * Computes the client evidence message M1 using the previously received values. + * To be called after calculating the secret S. + * @return M1: the client side generated evidence message + * @throws CryptoException + */ + public virtual BigInteger CalculateClientEvidenceMessage() + { + // Verify pre-requirements + if (this.pubA == null || this.B == null || this.S == null) + { + throw new CryptoException("Impossible to compute M1: " + + "some data are missing from the previous operations (A,B,S)"); + } + // compute the client evidence message 'M1' + this.M1 = Srp6Utilities.CalculateM1(digest, N, pubA, B, S); + return M1; + } + + /** Authenticates the server evidence message M2 received and saves it only if correct. + * @param M2: the server side generated evidence message + * @return A boolean indicating if the server message M2 was the expected one. + * @throws CryptoException + */ + public virtual bool VerifyServerEvidenceMessage(BigInteger serverM2) + { + // Verify pre-requirements + if (this.pubA == null || this.M1 == null || this.S == null) + { + throw new CryptoException("Impossible to compute and verify M2: " + + "some data are missing from the previous operations (A,M1,S)"); + } + + // Compute the own server evidence message 'M2' + BigInteger computedM2 = Srp6Utilities.CalculateM2(digest, N, pubA, M1, S); + if (computedM2.Equals(serverM2)) + { + this.M2 = serverM2; + return true; + } + return false; + } + + /** + * Computes the final session key as a result of the SRP successful mutual authentication + * To be called after verifying the server evidence message M2. + * @return Key: the mutually authenticated symmetric session key + * @throws CryptoException + */ + public virtual BigInteger CalculateSessionKey() + { + // Verify pre-requirements (here we enforce a previous calculation of M1 and M2) + if (this.S == null || this.M1 == null || this.M2 == null) + { + throw new CryptoException("Impossible to compute Key: " + + "some data are missing from the previous operations (S,M1,M2)"); + } + this.Key = Srp6Utilities.CalculateKey(digest, N, S); + return Key; + } } } diff --git a/crypto/src/crypto/agreement/srp/SRP6Server.cs b/crypto/src/crypto/agreement/srp/SRP6Server.cs index 35b96d488..fd0c9f1cb 100644 --- a/crypto/src/crypto/agreement/srp/SRP6Server.cs +++ b/crypto/src/crypto/agreement/srp/SRP6Server.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; @@ -26,6 +27,9 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp protected BigInteger u; protected BigInteger S; + protected BigInteger M1; + protected BigInteger M2; + protected BigInteger Key; public Srp6Server() { @@ -49,6 +53,11 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp this.digest = digest; } + public virtual void Init(Srp6GroupParameters group, BigInteger v, IDigest digest, SecureRandom random) + { + Init(group.N, group.G, v, digest, random); + } + /** * Generates the server's credentials that are to be sent to the client. * @return The server's public value to the client @@ -82,9 +91,73 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp return Srp6Utilities.GeneratePrivateValue(digest, N, g, random); } - private BigInteger CalculateS() + private BigInteger CalculateS() { return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N); } + + /** + * Authenticates the received client evidence message M1 and saves it only if correct. + * To be called after calculating the secret S. + * @param M1: the client side generated evidence message + * @return A boolean indicating if the client message M1 was the expected one. + * @throws CryptoException + */ + public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1) + { + // Verify pre-requirements + if (this.A == null || this.pubB == null || this.S == null) + { + throw new CryptoException("Impossible to compute and verify M1: " + + "some data are missing from the previous operations (A,B,S)"); + } + + // Compute the own client evidence message 'M1' + BigInteger computedM1 = Srp6Utilities.CalculateM1(digest, N, A, pubB, S); + if (computedM1.Equals(clientM1)) + { + this.M1 = clientM1; + return true; + } + return false; + } + + /** + * Computes the server evidence message M2 using the previously verified values. + * To be called after successfully verifying the client evidence message M1. + * @return M2: the server side generated evidence message + * @throws CryptoException + */ + public virtual BigInteger CalculateServerEvidenceMessage() + { + // Verify pre-requirements + if (this.A == null || this.M1 == null || this.S == null) + { + throw new CryptoException("Impossible to compute M2: " + + "some data are missing from the previous operations (A,M1,S)"); + } + + // Compute the server evidence message 'M2' + this.M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S); + return M2; + } + + /** + * Computes the final session key as a result of the SRP successful mutual authentication + * To be called after calculating the server evidence message M2. + * @return Key: the mutual authenticated symmetric session key + * @throws CryptoException + */ + public virtual BigInteger CalculateSessionKey() + { + // Verify pre-requirements + if (this.S == null || this.M1 == null || this.M2 == null) + { + throw new CryptoException("Impossible to compute Key: " + + "some data are missing from the previous operations (S,M1,M2)"); + } + this.Key = Srp6Utilities.CalculateKey(digest, N, S); + return Key; + } } } diff --git a/crypto/src/crypto/agreement/srp/SRP6StandardGroups.cs b/crypto/src/crypto/agreement/srp/SRP6StandardGroups.cs new file mode 100644 index 000000000..36f4aba11 --- /dev/null +++ b/crypto/src/crypto/agreement/srp/SRP6StandardGroups.cs @@ -0,0 +1,159 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + public class Srp6StandardGroups + { + private static BigInteger FromHex(string hex) + { + return new BigInteger(1, Hex.Decode(hex)); + } + + private static Srp6GroupParameters FromNG(string hexN, string hexG) + { + return new Srp6GroupParameters(FromHex(hexN), FromHex(hexG)); + } + + /* + * RFC 5054 + */ + private const string rfc5054_1024_N = "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" + + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" + + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" + + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" + "FD5138FE8376435B9FC61D2FC0EB06E3"; + private const string rfc5054_1024_g = "02"; + public static readonly Srp6GroupParameters rfc5054_1024 = FromNG(rfc5054_1024_N, rfc5054_1024_g); + + private const string rfc5054_1536_N = "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA961" + + "4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843" + + "80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B" + + "E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5" + + "6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A" + + "F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E" + + "8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB"; + private const string rfc5054_1536_g = "02"; + public static readonly Srp6GroupParameters rfc5054_1536 = FromNG(rfc5054_1536_N, rfc5054_1536_g); + + private const string rfc5054_2048_N = "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294" + + "3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D" + + "CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB" + + "D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74" + + "7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A" + + "436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D" + + "5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73" + + "03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6" + + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F" + "9E4AFF73"; + private const string rfc5054_2048_g = "02"; + public static readonly Srp6GroupParameters rfc5054_2048 = FromNG(rfc5054_2048_N, rfc5054_2048_g); + + private const string rfc5054_3072_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + "E0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"; + private const string rfc5054_3072_g = "05"; + public static readonly Srp6GroupParameters rfc5054_3072 = FromNG(rfc5054_3072_N, rfc5054_3072_g); + + private const string rfc5054_4096_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF"; + private const string rfc5054_4096_g = "05"; + public static readonly Srp6GroupParameters rfc5054_4096 = FromNG(rfc5054_4096_N, rfc5054_4096_g); + + private const string rfc5054_6144_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + "6DCC4024FFFFFFFFFFFFFFFF"; + private const string rfc5054_6144_g = "05"; + public static readonly Srp6GroupParameters rfc5054_6144 = FromNG(rfc5054_6144_N, rfc5054_6144_g); + + private const string rfc5054_8192_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + + "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA" + + "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C" + + "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886" + + "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6" + + "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5" + + "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268" + + "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6" + + "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF"; + private const string rfc5054_8192_g = "13"; + public static readonly Srp6GroupParameters rfc5054_8192 = FromNG(rfc5054_8192_N, rfc5054_8192_g); + } +} diff --git a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs index 4e790f572..ef6d8f24c 100644 --- a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs +++ b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs @@ -54,7 +54,75 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp return val; } - private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2) + /** + * Computes the client evidence message (M1) according to the standard routine: + * M1 = H( A | B | S ) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param A The public client value + * @param B The public server value + * @param S The secret calculated by both sides + * @return M1 The calculated client evidence message + */ + public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) + { + BigInteger M1 = HashPaddedTriplet(digest, N, A, B, S); + return M1; + } + + /** + * Computes the server evidence message (M2) according to the standard routine: + * M2 = H( A | M1 | S ) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param A The public client value + * @param M1 The client evidence message + * @param S The secret calculated by both sides + * @return M2 The calculated server evidence message + */ + public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S) + { + BigInteger M2 = HashPaddedTriplet(digest, N, A, M1, S); + return M2; + } + + /** + * Computes the final Key according to the standard routine: Key = H(S) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param S The secret calculated by both sides + * @return + */ + public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S) + { + int padLength = (N.BitLength + 7) / 8; + byte[] _S = GetPadded(S, padLength); + digest.BlockUpdate(_S, 0, _S.Length); + + byte[] output = new byte[digest.GetDigestSize()]; + digest.DoFinal(output, 0); + return new BigInteger(1, output); + } + + private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3) + { + int padLength = (N.BitLength + 7) / 8; + + byte[] n1_bytes = GetPadded(n1, padLength); + byte[] n2_bytes = GetPadded(n2, padLength); + byte[] n3_bytes = GetPadded(n3, padLength); + + digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length); + digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length); + digest.BlockUpdate(n3_bytes, 0, n3_bytes.Length); + + byte[] output = new byte[digest.GetDigestSize()]; + digest.DoFinal(output, 0); + + return new BigInteger(1, output); + } + + private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2) { int padLength = (N.BitLength + 7) / 8; diff --git a/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs b/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs index 264833b4d..956973598 100644 --- a/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs +++ b/crypto/src/crypto/agreement/srp/SRP6VerifierGenerator.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; namespace Org.BouncyCastle.Crypto.Agreement.Srp @@ -31,7 +32,12 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp this.digest = digest; } - /** + public virtual void Init(Srp6GroupParameters group, IDigest digest) + { + Init(group.N, group.G, digest); + } + + /** * Creates a new SRP verifier * @param salt The salt to use, generally should be large and random * @param identity The user's identifying information (eg. username) diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs index 0cdd868fa..9d7f76c05 100644 --- a/crypto/src/crypto/engines/AesEngine.cs +++ b/crypto/src/crypto/engines/AesEngine.cs @@ -363,7 +363,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -377,41 +377,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -429,7 +420,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs index 38d3a5841..a1b544568 100644 --- a/crypto/src/crypto/engines/AesFastEngine.cs +++ b/crypto/src/crypto/engines/AesFastEngine.cs @@ -695,7 +695,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -709,41 +709,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -761,7 +752,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/AesLightEngine.cs b/crypto/src/crypto/engines/AesLightEngine.cs index 54f2d2e88..a6b9e3bd4 100644 --- a/crypto/src/crypto/engines/AesLightEngine.cs +++ b/crypto/src/crypto/engines/AesLightEngine.cs @@ -258,7 +258,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -272,41 +272,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -324,7 +315,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/BlowfishEngine.cs b/crypto/src/crypto/engines/BlowfishEngine.cs index 8f80f712e..7b50e832f 100644 --- a/crypto/src/crypto/engines/BlowfishEngine.cs +++ b/crypto/src/crypto/engines/BlowfishEngine.cs @@ -296,7 +296,7 @@ namespace Org.BouncyCastle.Crypto.Engines //==================================== private static readonly int ROUNDS = 16; - private const int BLOCK_SIZE = 8; // bytes = 64 bits + private const int BLOCK_SIZE = 8; // bytes = 64 bits private static readonly int SBOX_SK = 256; private static readonly int P_SZ = ROUNDS+2; @@ -353,19 +353,10 @@ namespace Org.BouncyCastle.Crypto.Engines int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Blowfish not initialised"); - } - if ((inOff + BLOCK_SIZE) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + BLOCK_SIZE) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); if (encrypting) { diff --git a/crypto/src/crypto/engines/CamelliaEngine.cs b/crypto/src/crypto/engines/CamelliaEngine.cs index 8f4a442e9..71bd1b0dc 100644 --- a/crypto/src/crypto/engines/CamelliaEngine.cs +++ b/crypto/src/crypto/engines/CamelliaEngine.cs @@ -611,7 +611,7 @@ namespace Org.BouncyCastle.Crypto.Engines { } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -623,22 +623,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Camellia"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -646,12 +646,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Camellia engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (_keyIs128) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (_keyIs128) { return processBlock128(input, inOff, output, outOff); } @@ -661,7 +660,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { // nothing } diff --git a/crypto/src/crypto/engines/CamelliaLightEngine.cs b/crypto/src/crypto/engines/CamelliaLightEngine.cs index a301eb55e..a132227c5 100644 --- a/crypto/src/crypto/engines/CamelliaLightEngine.cs +++ b/crypto/src/crypto/engines/CamelliaLightEngine.cs @@ -524,22 +524,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Camellia"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -551,7 +551,7 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -559,12 +559,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Camellia engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (_keyis128) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (_keyis128) { return processBlock128(input, inOff, output, outOff); } @@ -574,7 +573,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { } } diff --git a/crypto/src/crypto/engines/Cast5Engine.cs b/crypto/src/crypto/engines/Cast5Engine.cs index 4c3f84a55..1af30a335 100644 --- a/crypto/src/crypto/engines/Cast5Engine.cs +++ b/crypto/src/crypto/engines/Cast5Engine.cs @@ -329,7 +329,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -360,12 +360,11 @@ namespace Org.BouncyCastle.Crypto.Engines int blockSize = GetBlockSize(); if (_workingKey == null) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + blockSize) > input.Length) - throw new DataLengthException("Input buffer too short"); - if ((outOff + blockSize) > output.Length) - throw new DataLengthException("Output buffer too short"); - if (_encrypting) + Check.DataLength(input, inOff, blockSize, "input buffer too short"); + Check.OutputLength(output, outOff, blockSize, "output buffer too short"); + + if (_encrypting) { return EncryptBlock(input, inOff, output, outOff); } diff --git a/crypto/src/crypto/engines/ChaChaEngine.cs b/crypto/src/crypto/engines/ChaChaEngine.cs index f4a7b8fe1..46b59ed2e 100644 --- a/crypto/src/crypto/engines/ChaChaEngine.cs +++ b/crypto/src/crypto/engines/ChaChaEngine.cs @@ -162,7 +162,6 @@ namespace Org.BouncyCastle.Crypto.Engines x09 += x14; x04 = R(x04 ^ x09, 12); x03 += x04; x14 = R(x14 ^ x03, 8); x09 += x14; x04 = R(x04 ^ x09, 7); - } x[ 0] = x00 + input[ 0]; @@ -182,8 +181,6 @@ namespace Org.BouncyCastle.Crypto.Engines x[14] = x14 + input[14]; x[15] = x15 + input[15]; } - } - } diff --git a/crypto/src/crypto/engines/DesEdeEngine.cs b/crypto/src/crypto/engines/DesEdeEngine.cs index eec4ec59d..bc40b56a8 100644 --- a/crypto/src/crypto/engines/DesEdeEngine.cs +++ b/crypto/src/crypto/engines/DesEdeEngine.cs @@ -70,10 +70,9 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey1 == null) throw new InvalidOperationException("DESede engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); + + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); byte[] temp = new byte[BLOCK_SIZE]; diff --git a/crypto/src/crypto/engines/DesEdeWrapEngine.cs b/crypto/src/crypto/engines/DesEdeWrapEngine.cs index fdc71687f..43100a9bd 100644 --- a/crypto/src/crypto/engines/DesEdeWrapEngine.cs +++ b/crypto/src/crypto/engines/DesEdeWrapEngine.cs @@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forWrapping * @param param */ - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return */ - public string AlgorithmName + public virtual string AlgorithmName { get { return "DESede"; } } @@ -116,7 +116,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param inLen * @return */ - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int length) @@ -185,7 +185,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @throws InvalidCipherTextException */ - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/DesEngine.cs b/crypto/src/crypto/engines/DesEngine.cs index 067cf45e3..a6d580bb6 100644 --- a/crypto/src/crypto/engines/DesEngine.cs +++ b/crypto/src/crypto/engines/DesEngine.cs @@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Engines get { return "DES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } @@ -59,12 +59,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("DES engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - DesFunc(workingKey, input, inOff, output, outOff); + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + DesFunc(workingKey, input, inOff, output, outOff); return BLOCK_SIZE; } diff --git a/crypto/src/crypto/engines/ElGamalEngine.cs b/crypto/src/crypto/engines/ElGamalEngine.cs index 3d256a087..197d7bc15 100644 --- a/crypto/src/crypto/engines/ElGamalEngine.cs +++ b/crypto/src/crypto/engines/ElGamalEngine.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Engines private bool forEncryption; private int bitSize; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ElGamal"; } } @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary ElGamal key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the ElGamal process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/GOST28147Engine.cs b/crypto/src/crypto/engines/GOST28147Engine.cs index 8eb6f36b5..e37ddaefd 100644 --- a/crypto/src/crypto/engines/GOST28147Engine.cs +++ b/crypto/src/crypto/engines/GOST28147Engine.cs @@ -150,7 +150,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param parameters the parameters required to set up the cipher. * @exception ArgumentException if the parameters argument is inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -187,48 +187,39 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Gost28147"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Gost28147 engine not initialised"); - } - if ((inOff + BlockSize) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + BlockSize) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(output, outOff, BlockSize, "output buffer too short"); - Gost28147Func(workingKey, input, inOff, output, outOff); + Gost28147Func(workingKey, input, inOff, output, outOff); return BlockSize; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs index a2d099f87..40c7a4e17 100644 --- a/crypto/src/crypto/engines/HC128Engine.cs +++ b/crypto/src/crypto/engines/HC128Engine.cs @@ -142,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Engines cnt = 0; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "HC-128"; } } @@ -156,7 +156,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @throws ArgumentException if the params argument is * inappropriate (ie. the key is not 128 bit long). */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -201,7 +201,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ret; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -210,24 +210,23 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < len; i++) + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); + + for (int i = 0; i < len; i++) { output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); } } - public void Reset() + public virtual void Reset() { idx = 0; Init(); } - public byte ReturnByte(byte input) + public virtual byte ReturnByte(byte input) { return (byte)(input ^ GetByte()); } diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs index da717dab7..6eb360711 100644 --- a/crypto/src/crypto/engines/HC256Engine.cs +++ b/crypto/src/crypto/engines/HC256Engine.cs @@ -126,7 +126,7 @@ namespace Org.BouncyCastle.Crypto.Engines cnt = 0; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "HC-256"; } } @@ -140,7 +140,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @throws ArgumentException if the params argument is * inappropriate (ie. the key is not 256 bit long). */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -185,7 +185,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ret; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -194,24 +194,23 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < len; i++) + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); + + for (int i = 0; i < len; i++) { output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); } } - public void Reset() + public virtual void Reset() { idx = 0; Init(); } - public byte ReturnByte(byte input) + public virtual byte ReturnByte(byte input) { return (byte)(input ^ GetByte()); } diff --git a/crypto/src/crypto/engines/ISAACEngine.cs b/crypto/src/crypto/engines/ISAACEngine.cs index 9c58678a0..f25577130 100644 --- a/crypto/src/crypto/engines/ISAACEngine.cs +++ b/crypto/src/crypto/engines/ISAACEngine.cs @@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { if (index == 0) @@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Engines return output; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -77,10 +77,9 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); + + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); for (int i = 0; i < len; i++) { @@ -94,12 +93,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "ISAAC"; } } - public void Reset() + public virtual void Reset() { setKey(workingKey); } diff --git a/crypto/src/crypto/engines/IdeaEngine.cs b/crypto/src/crypto/engines/IdeaEngine.cs index 46b5a787c..4909510ac 100644 --- a/crypto/src/crypto/engines/IdeaEngine.cs +++ b/crypto/src/crypto/engines/IdeaEngine.cs @@ -47,7 +47,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -58,43 +58,37 @@ namespace Org.BouncyCastle.Crypto.Engines ((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "IDEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("IDEA engine not initialised"); - } - if ((inOff + BLOCK_SIZE) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - if ((outOff + BLOCK_SIZE) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + IdeaFunc(workingKey, input, inOff, output, outOff); return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } private static readonly int MASK = 0xffff; diff --git a/crypto/src/crypto/engines/IesEngine.cs b/crypto/src/crypto/engines/IesEngine.cs index 70df3077c..a2004a9d6 100644 --- a/crypto/src/crypto/engines/IesEngine.cs +++ b/crypto/src/crypto/engines/IesEngine.cs @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param pubParam the recipient's/sender's public key parameters * @param param encoding and derivation parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters privParameters, ICipherParameters pubParameters, @@ -213,7 +213,7 @@ namespace Org.BouncyCastle.Crypto.Engines return buf; } - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] input, int inOff, int inLen) @@ -224,10 +224,16 @@ namespace Org.BouncyCastle.Crypto.Engines byte[] zBytes = BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z); - return forEncryption - ? EncryptBlock(input, inOff, inLen, zBytes) - : DecryptBlock(input, inOff, inLen, zBytes); + try + { + return forEncryption + ? EncryptBlock(input, inOff, inLen, zBytes) + : DecryptBlock(input, inOff, inLen, zBytes); + } + finally + { + Array.Clear(zBytes, 0, zBytes.Length); + } } } - } diff --git a/crypto/src/crypto/engines/NaccacheSternEngine.cs b/crypto/src/crypto/engines/NaccacheSternEngine.cs index 9ca092351..e547e0caf 100644 --- a/crypto/src/crypto/engines/NaccacheSternEngine.cs +++ b/crypto/src/crypto/engines/NaccacheSternEngine.cs @@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool, * org.bouncycastle.crypto.CipherParameters) */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public bool Debug + public virtual bool Debug { set { this.debug = value; } } @@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetInputBlockSize() */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetOutputBlockSize() */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @see org.bouncycastle.crypto.AsymmetricBlockCipher#ProcessBlock(byte[], * int, int) */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBytes, int inOff, int length) @@ -245,7 +245,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return The byte[] representation of the encrypted BigInteger (i.e. * crypted.toByteArray()) */ - public byte[] Encrypt( + public virtual byte[] Encrypt( BigInteger plain) { // Always return modulus size values 0-padded at the beginning @@ -273,7 +273,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return encrypt((block1 + block2) mod sigma) * @throws InvalidCipherTextException */ - public byte[] AddCryptedBlocks( + public virtual byte[] AddCryptedBlocks( byte[] block1, byte[] block2) { @@ -329,7 +329,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the data after it went through the NaccacheSternEngine. * @throws InvalidCipherTextException */ - public byte[] ProcessData( + public virtual byte[] ProcessData( byte[] data) { if (debug) diff --git a/crypto/src/crypto/engines/NoekeonEngine.cs b/crypto/src/crypto/engines/NoekeonEngine.cs index b73e696a9..dd78a4ea5 100644 --- a/crypto/src/crypto/engines/NoekeonEngine.cs +++ b/crypto/src/crypto/engines/NoekeonEngine.cs @@ -42,17 +42,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Noekeon"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return GenericSize; } @@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -88,17 +88,16 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + GenericSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + GenericSize) > output.Length) - throw new DataLengthException("output buffer too short"); - return _forEncryption + Check.DataLength(input, inOff, GenericSize, "input buffer too short"); + Check.OutputLength(output, outOff, GenericSize, "output buffer too short"); + + return _forEncryption ? encryptBlock(input, inOff, output, outOff) : decryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { // TODO This should do something in case the encryption is aborted } diff --git a/crypto/src/crypto/engines/NullEngine.cs b/crypto/src/crypto/engines/NullEngine.cs index 407b8ccc6..f883b7c29 100644 --- a/crypto/src/crypto/engines/NullEngine.cs +++ b/crypto/src/crypto/engines/NullEngine.cs @@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Crypto.Engines { } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -26,22 +26,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Null"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return true; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -49,12 +49,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Null engine not initialised"); - if ((inOff + BlockSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BlockSize) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < BlockSize; ++i) + Check.DataLength(input, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(output, outOff, BlockSize, "output buffer too short"); + + for (int i = 0; i < BlockSize; ++i) { output[outOff + i] = input[inOff + i]; } @@ -62,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BlockSize; } - public void Reset() + public virtual void Reset() { // nothing needs to be done } diff --git a/crypto/src/crypto/engines/RC2Engine.cs b/crypto/src/crypto/engines/RC2Engine.cs index aaf8c714c..b56953de5 100644 --- a/crypto/src/crypto/engines/RC2Engine.cs +++ b/crypto/src/crypto/engines/RC2Engine.cs @@ -114,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -139,26 +139,26 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC2"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -166,12 +166,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("RC2 engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -308,5 +307,4 @@ namespace Org.BouncyCastle.Crypto.Engines outBytes[outOff + 7] = (byte)(x76 >> 8); } } - } diff --git a/crypto/src/crypto/engines/RC2WrapEngine.cs b/crypto/src/crypto/engines/RC2WrapEngine.cs index 238c9f76a..5742aa8b7 100644 --- a/crypto/src/crypto/engines/RC2WrapEngine.cs +++ b/crypto/src/crypto/engines/RC2WrapEngine.cs @@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forWrapping * @param param */ - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -101,7 +101,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return */ - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC2"; } } @@ -114,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param inLen * @return */ - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int length) @@ -215,7 +215,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @throws InvalidCipherTextException */ - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/RC4Engine.cs b/crypto/src/crypto/engines/RC4Engine.cs index c65468d93..fd84b7d23 100644 --- a/crypto/src/crypto/engines/RC4Engine.cs +++ b/crypto/src/crypto/engines/RC4Engine.cs @@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -47,12 +47,12 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("invalid parameter passed to RC4 init - " + parameters.GetType().ToString()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC4"; } } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { x = (x + 1) & 0xff; @@ -67,23 +67,15 @@ namespace Org.BouncyCastle.Crypto.Engines return (byte)(input ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int length, byte[] output, - int outOff - ) + int outOff) { - if ((inOff + length) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + length) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, length, "input buffer too short"); + Check.OutputLength(output, outOff, length, "output buffer too short"); for (int i = 0; i < length ; i++) { @@ -101,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { SetKey(workingKey); } @@ -143,5 +135,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RC532Engine.cs b/crypto/src/crypto/engines/RC532Engine.cs index 1661707ef..169a60b98 100644 --- a/crypto/src/crypto/engines/RC532Engine.cs +++ b/crypto/src/crypto/engines/RC532Engine.cs @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC5-32"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 2 * 4; } @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -97,7 +97,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -108,7 +108,7 @@ namespace Org.BouncyCastle.Crypto.Engines : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -290,5 +290,4 @@ namespace Org.BouncyCastle.Crypto.Engines dst[dstOff + 3] = (byte)(word >> 24); } } - } diff --git a/crypto/src/crypto/engines/RC564Engine.cs b/crypto/src/crypto/engines/RC564Engine.cs index 5c69d40ff..ddcce0fa8 100644 --- a/crypto/src/crypto/engines/RC564Engine.cs +++ b/crypto/src/crypto/engines/RC564Engine.cs @@ -51,17 +51,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC5-64"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 2 * bytesPerWord; } @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Engines SetKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -102,7 +102,7 @@ namespace Org.BouncyCastle.Crypto.Engines : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -291,5 +291,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RC6Engine.cs b/crypto/src/crypto/engines/RC6Engine.cs index d72cc2f7b..196bd8394 100644 --- a/crypto/src/crypto/engines/RC6Engine.cs +++ b/crypto/src/crypto/engines/RC6Engine.cs @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC6"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 4 * bytesPerWord; } @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -84,7 +84,7 @@ namespace Org.BouncyCastle.Crypto.Engines SetKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -93,17 +93,16 @@ namespace Org.BouncyCastle.Crypto.Engines int blockSize = GetBlockSize(); if (_S == null) throw new InvalidOperationException("RC6 engine not initialised"); - if ((inOff + blockSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + blockSize) > output.Length) - throw new DataLengthException("output buffer too short"); - return (forEncryption) + Check.DataLength(input, inOff, blockSize, "input buffer too short"); + Check.OutputLength(output, outOff, blockSize, "output buffer too short"); + + return (forEncryption) ? EncryptBlock(input, inOff, output, outOff) : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -358,5 +357,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RFC3211WrapEngine.cs b/crypto/src/crypto/engines/RFC3211WrapEngine.cs index e520075f9..4e3af5227 100644 --- a/crypto/src/crypto/engines/RFC3211WrapEngine.cs +++ b/crypto/src/crypto/engines/RFC3211WrapEngine.cs @@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.engine = new CbcBlockCipher(engine); } - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters param) { @@ -48,12 +48,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return engine.GetUnderlyingCipher().AlgorithmName + "/RFC3211Wrap"; } } - public byte[] Wrap( + public virtual byte[] Wrap( byte[] inBytes, int inOff, int inLen) @@ -99,7 +99,7 @@ namespace Org.BouncyCastle.Crypto.Engines return cekBlock; } - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] inBytes, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RFC3394WrapEngine.cs b/crypto/src/crypto/engines/RFC3394WrapEngine.cs index 5615a63e5..4bb0e2114 100644 --- a/crypto/src/crypto/engines/RFC3394WrapEngine.cs +++ b/crypto/src/crypto/engines/RFC3394WrapEngine.cs @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.engine = engine; } - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -64,12 +64,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return engine.AlgorithmName; } } - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int inLen) @@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Crypto.Engines return block; } - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs index cdf69ddda..037abf7e9 100644 --- a/crypto/src/crypto/engines/RSABlindedEngine.cs +++ b/crypto/src/crypto/engines/RSABlindedEngine.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Engines private RsaKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters param) { @@ -55,7 +55,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -81,7 +81,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSABlindingEngine.cs b/crypto/src/crypto/engines/RSABlindingEngine.cs index 76b57a3f7..c636627bf 100644 --- a/crypto/src/crypto/engines/RSABlindingEngine.cs +++ b/crypto/src/crypto/engines/RSABlindingEngine.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines private bool forEncryption; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting (blinding), false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters param) { @@ -63,7 +63,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -89,7 +89,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @throws DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSACoreEngine.cs b/crypto/src/crypto/engines/RSACoreEngine.cs index 4e64d25d6..38326371f 100644 --- a/crypto/src/crypto/engines/RSACoreEngine.cs +++ b/crypto/src/crypto/engines/RSACoreEngine.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Crypto.Engines return (bitSize - 1) / 8; } - public BigInteger ConvertInput( + public virtual BigInteger ConvertInput( byte[] inBuf, int inOff, int inLen) @@ -90,7 +90,7 @@ namespace Org.BouncyCastle.Crypto.Engines return input; } - public byte[] ConvertOutput( + public virtual byte[] ConvertOutput( BigInteger result) { byte[] output = result.ToByteArrayUnsigned(); @@ -112,7 +112,7 @@ namespace Org.BouncyCastle.Crypto.Engines return output; } - public BigInteger ProcessBlock( + public virtual BigInteger ProcessBlock( BigInteger input) { if (key is RsaPrivateCrtKeyParameters) diff --git a/crypto/src/crypto/engines/RijndaelEngine.cs b/crypto/src/crypto/engines/RijndaelEngine.cs index df2e5baea..80f522353 100644 --- a/crypto/src/crypto/engines/RijndaelEngine.cs +++ b/crypto/src/crypto/engines/RijndaelEngine.cs @@ -571,7 +571,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -585,43 +585,34 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("invalid parameter passed to Rijndael init - " + parameters.GetType().ToString()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Rijndael"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BC / 2; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Rijndael engine not initialised"); - } - - if ((inOff + (BC / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - if ((outOff + (BC / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, (BC / 2), "input buffer too short"); + Check.OutputLength(output, outOff, (BC / 2), "output buffer too short"); - UnPackBlock(input, inOff); + UnPackBlock(input, inOff); if (forEncryption) { @@ -637,11 +628,11 @@ namespace Org.BouncyCastle.Crypto.Engines return BC / 2; } - public void Reset() + public virtual void Reset() { } - private void UnPackBlock( + private void UnPackBlock( byte[] bytes, int off) { @@ -743,5 +734,4 @@ namespace Org.BouncyCastle.Crypto.Engines KeyAddition(rk[0]); } } - } diff --git a/crypto/src/crypto/engines/RsaEngine.cs b/crypto/src/crypto/engines/RsaEngine.cs index 7e6dfb163..4399b4409 100644 --- a/crypto/src/crypto/engines/RsaEngine.cs +++ b/crypto/src/crypto/engines/RsaEngine.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Engines { private RsaCoreEngine core; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -38,7 +38,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -50,7 +50,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs index efea0f1fe..f615b8476 100644 --- a/crypto/src/crypto/engines/SEEDEngine.cs +++ b/crypto/src/crypto/engines/SEEDEngine.cs @@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Crypto.Engines private int[] wKey; private bool forEncryption; - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -176,22 +176,22 @@ namespace Org.BouncyCastle.Crypto.Engines wKey = createWorkingKey(((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "SEED"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBuf, int inOff, byte[] outBuf, @@ -199,12 +199,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (wKey == null) throw new InvalidOperationException("SEED engine not initialised"); - if (inOff + BlockSize > inBuf.Length) - throw new DataLengthException("input buffer too short"); - if (outOff + BlockSize > outBuf.Length) - throw new DataLengthException("output buffer too short"); - long l = bytesToLong(inBuf, inOff + 0); + Check.DataLength(inBuf, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(outBuf, outOff, BlockSize, "output buffer too short"); + + long l = bytesToLong(inBuf, inOff + 0); long r = bytesToLong(inBuf, inOff + 8); if (forEncryption) @@ -234,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BlockSize; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/Salsa20Engine.cs b/crypto/src/crypto/engines/Salsa20Engine.cs index 81884d603..9b27dc7b4 100644 --- a/crypto/src/crypto/engines/Salsa20Engine.cs +++ b/crypto/src/crypto/engines/Salsa20Engine.cs @@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.rounds = rounds; } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -108,7 +108,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { if (LimitExceeded()) @@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] inBytes, int inOff, int len, @@ -144,26 +144,15 @@ namespace Org.BouncyCastle.Crypto.Engines int outOff) { if (!initialised) - { throw new InvalidOperationException(AlgorithmName + " not initialised"); - } - if ((inOff + len) > inBytes.Length) - { - throw new DataLengthException("input buffer too short"); - } + Check.DataLength(inBytes, inOff, len, "input buffer too short"); + Check.OutputLength(outBytes, outOff, len, "output buffer too short"); - if ((outOff + len) > outBytes.Length) - { - throw new DataLengthException("output buffer too short"); - } - - if (LimitExceeded((uint)len)) - { + if (LimitExceeded((uint)len)) throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV"); - } - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { if (index == 0) { @@ -175,7 +164,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { index = 0; ResetLimitCounter(); diff --git a/crypto/src/crypto/engines/SerpentEngine.cs b/crypto/src/crypto/engines/SerpentEngine.cs index 92b25acc6..255c204ab 100644 --- a/crypto/src/crypto/engines/SerpentEngine.cs +++ b/crypto/src/crypto/engines/SerpentEngine.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Serpent"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } @@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception InvalidOperationException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -84,12 +84,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (wKey == null) throw new InvalidOperationException("Serpent not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -101,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } @@ -775,5 +774,4 @@ namespace Org.BouncyCastle.Crypto.Engines X0 = RotateRight(x0, 13); } } - } diff --git a/crypto/src/crypto/engines/SkipjackEngine.cs b/crypto/src/crypto/engines/SkipjackEngine.cs index 3d2a781e6..a45dc9b24 100644 --- a/crypto/src/crypto/engines/SkipjackEngine.cs +++ b/crypto/src/crypto/engines/SkipjackEngine.cs @@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -71,22 +71,22 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "SKIPJACK"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -94,12 +94,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (key1 == null) throw new InvalidOperationException("SKIPJACK engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -111,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } @@ -135,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ((g5 << 8) + g6); } - public int EncryptBlock( + public virtual int EncryptBlock( byte[] input, int inOff, byte[] outBytes, @@ -203,7 +202,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ((h6 << 8) + h5); } - public int DecryptBlock( + public virtual int DecryptBlock( byte[] input, int inOff, byte[] outBytes, @@ -251,5 +250,4 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } } - } diff --git a/crypto/src/crypto/engines/TEAEngine.cs b/crypto/src/crypto/engines/TEAEngine.cs index 582dd0f73..2e1a7002b 100644 --- a/crypto/src/crypto/engines/TEAEngine.cs +++ b/crypto/src/crypto/engines/TEAEngine.cs @@ -36,17 +36,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "TEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return block_size; } @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -77,7 +77,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBytes, int inOff, byte[] outBytes, @@ -86,18 +86,15 @@ namespace Org.BouncyCastle.Crypto.Engines if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + block_size) > inBytes.Length) - throw new DataLengthException("input buffer too short"); + Check.DataLength(inBytes, inOff, block_size, "input buffer too short"); + Check.OutputLength(outBytes, outOff, block_size, "output buffer too short"); - if ((outOff + block_size) > outBytes.Length) - throw new DataLengthException("output buffer too short"); - - return _forEncryption + return _forEncryption ? encryptBlock(inBytes, inOff, outBytes, outOff) : decryptBlock(inBytes, inOff, outBytes, outOff); } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/ThreefishEngine.cs b/crypto/src/crypto/engines/ThreefishEngine.cs index 954470345..33ff3a421 100644 --- a/crypto/src/crypto/engines/ThreefishEngine.cs +++ b/crypto/src/crypto/engines/ThreefishEngine.cs @@ -155,7 +155,7 @@ namespace Org.BouncyCastle.Crypto.Engines /// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param> /// <param name="parameters">an instance of <see cref="TweakableBlockCipherParameters"/> or <see cref="KeyParameter"/> (to /// use a 0 tweak)</param> - public void Init(bool forEncryption, ICipherParameters parameters) + public virtual void Init(bool forEncryption, ICipherParameters parameters) { byte[] keyBytes; byte[] tweakBytes; @@ -266,26 +266,26 @@ namespace Org.BouncyCastle.Crypto.Engines t[4] = t[1]; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Threefish-" + (blocksizeBytes * 8); } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return blocksizeBytes; } - public void Reset() + public virtual void Reset() { } - public int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff) + public virtual int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff) { if ((outOff + blocksizeBytes) > outBytes.Length) { diff --git a/crypto/src/crypto/engines/TwofishEngine.cs b/crypto/src/crypto/engines/TwofishEngine.cs index b983d9d31..04a579ced 100644 --- a/crypto/src/crypto/engines/TwofishEngine.cs +++ b/crypto/src/crypto/engines/TwofishEngine.cs @@ -293,12 +293,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("Twofish not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } diff --git a/crypto/src/crypto/engines/VMPCEngine.cs b/crypto/src/crypto/engines/VMPCEngine.cs index 1c2802a80..852901e36 100644 --- a/crypto/src/crypto/engines/VMPCEngine.cs +++ b/crypto/src/crypto/engines/VMPCEngine.cs @@ -92,15 +92,8 @@ namespace Org.BouncyCastle.Crypto.Engines byte[] output, int outOff) { - if ((inOff + len) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + len) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); for (int i = 0; i < len; i++) { diff --git a/crypto/src/crypto/engines/XSalsa20Engine.cs b/crypto/src/crypto/engines/XSalsa20Engine.cs index fc6630905..2898b46c8 100644 --- a/crypto/src/crypto/engines/XSalsa20Engine.cs +++ b/crypto/src/crypto/engines/XSalsa20Engine.cs @@ -13,7 +13,6 @@ namespace Org.BouncyCastle.Crypto.Engines public class XSalsa20Engine : Salsa20Engine { - public override string AlgorithmName { get { return "XSalsa20"; } @@ -65,7 +64,6 @@ namespace Org.BouncyCastle.Crypto.Engines // Counter reset ResetCounter(); } - } } diff --git a/crypto/src/crypto/engines/XTEAEngine.cs b/crypto/src/crypto/engines/XTEAEngine.cs index eb9291775..40d81fbe6 100644 --- a/crypto/src/crypto/engines/XTEAEngine.cs +++ b/crypto/src/crypto/engines/XTEAEngine.cs @@ -34,17 +34,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "XTEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return block_size; } @@ -57,7 +57,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBytes, int inOff, byte[] outBytes, @@ -84,18 +84,15 @@ namespace Org.BouncyCastle.Crypto.Engines if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + block_size) > inBytes.Length) - throw new DataLengthException("input buffer too short"); + Check.DataLength(inBytes, inOff, block_size, "input buffer too short"); + Check.OutputLength(outBytes, outOff, block_size, "output buffer too short"); - if ((outOff + block_size) > outBytes.Length) - throw new DataLengthException("output buffer too short"); - - return _forEncryption + return _forEncryption ? encryptBlock(inBytes, inOff, outBytes, outOff) : decryptBlock(inBytes, inOff, outBytes, outOff); } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs index e870f1c08..2613b902b 100644 --- a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs +++ b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs @@ -4,6 +4,7 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Generators { @@ -11,117 +12,127 @@ namespace Org.BouncyCastle.Crypto.Generators * an RSA key pair generator. */ public class RsaKeyPairGenerator - : IAsymmetricCipherKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator { - private static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); - private const int DefaultTests = 12; + private static readonly int[] SPECIAL_E_VALUES = new int[]{ 3, 5, 17, 257, 65537 }; + private static readonly int SPECIAL_E_HIGHEST = SPECIAL_E_VALUES[SPECIAL_E_VALUES.Length - 1]; + private static readonly int SPECIAL_E_BITS = BigInteger.ValueOf(SPECIAL_E_HIGHEST).BitLength; - private RsaKeyGenerationParameters param; + protected static readonly BigInteger One = BigInteger.One; + protected static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); + protected const int DefaultTests = 100; - public void Init( + protected RsaKeyGenerationParameters parameters; + + public virtual void Init( KeyGenerationParameters parameters) { if (parameters is RsaKeyGenerationParameters) { - this.param = (RsaKeyGenerationParameters)parameters; + this.parameters = (RsaKeyGenerationParameters)parameters; } else { - this.param = new RsaKeyGenerationParameters( + this.parameters = new RsaKeyGenerationParameters( DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests); } } - public AsymmetricCipherKeyPair GenerateKeyPair() + public virtual AsymmetricCipherKeyPair GenerateKeyPair() { - BigInteger p, q, n, d, e, pSub1, qSub1, phi; - - // - // p and q values should have a length of half the strength in bits - // - int strength = param.Strength; - int qBitlength = strength >> 1; - int pBitlength = strength - qBitlength; - int mindiffbits = strength / 3; - int minWeight = strength >> 2; - - e = param.PublicExponent; - - // TODO Consider generating safe primes for p, q (see DHParametersHelper.GenerateSafePrimes) - // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") - - p = ChooseRandomPrime(pBitlength, e); - - // - // Generate a modulus of the required length - // for (;;) { - q = ChooseRandomPrime(qBitlength, e); + // + // p and q values should have a length of half the strength in bits + // + int strength = parameters.Strength; + int pBitlength = (strength + 1) / 2; + int qBitlength = strength - pBitlength; + int mindiffbits = strength / 3; + int minWeight = strength >> 2; - // p and q should not be too close together (or equal!) - BigInteger diff = q.Subtract(p).Abs(); - if (diff.BitLength < mindiffbits) - continue; + BigInteger e = parameters.PublicExponent; + + // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) + // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") + + BigInteger p = ChooseRandomPrime(pBitlength, e); + BigInteger q, n; // - // calculate the modulus + // generate a modulus of the required length // - n = p.Multiply(q); - - if (n.BitLength != strength) + for (;;) { + q = ChooseRandomPrime(qBitlength, e); + + // p and q should not be too close together (or equal!) + BigInteger diff = q.Subtract(p).Abs(); + if (diff.BitLength < mindiffbits) + continue; + // - // if we get here our primes aren't big enough, make the largest - // of the two p and try again + // calculate the modulus // - p = p.Max(q); - continue; + n = p.Multiply(q); + + if (n.BitLength != strength) + { + // + // if we get here our primes aren't big enough, make the largest + // of the two p and try again + // + p = p.Max(q); + continue; + } + + /* + * Require a minimum weight of the NAF representation, since low-weight composites may + * be weak against a version of the number-field-sieve for factoring. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtilities.GetNafWeight(n) < minWeight) + { + p = ChooseRandomPrime(pBitlength, e); + continue; + } + + break; } - /* - * Require a minimum weight of the NAF representation, since low-weight composites may - * be weak against a version of the number-field-sieve for factoring. - * - * See "The number field sieve for integers of low weight", Oliver Schirokauer. - */ - if (WNafUtilities.GetNafWeight(n) < minWeight) + if (p.CompareTo(q) < 0) { - p = ChooseRandomPrime(pBitlength, e); - continue; + BigInteger tmp = p; + p = q; + q = tmp; } - break; - } - - if (p.CompareTo(q) < 0) - { - phi = p; - p = q; - q = phi; - } - - pSub1 = p.Subtract(BigInteger.One); - qSub1 = q.Subtract(BigInteger.One); - phi = pSub1.Multiply(qSub1); + BigInteger pSub1 = p.Subtract(One); + BigInteger qSub1 = q.Subtract(One); + //BigInteger phi = pSub1.Multiply(qSub1); + BigInteger gcd = pSub1.Gcd(qSub1); + BigInteger lcm = pSub1.Divide(gcd).Multiply(qSub1); - // - // calculate the private exponent - // - d = e.ModInverse(phi); + // + // calculate the private exponent + // + BigInteger d = e.ModInverse(lcm); - // - // calculate the CRT factors - // - BigInteger dP, dQ, qInv; + if (d.BitLength <= qBitlength) + continue; - dP = d.Remainder(pSub1); - dQ = d.Remainder(qSub1); - qInv = q.ModInverse(p); + // + // calculate the CRT factors + // + BigInteger dP = d.Remainder(pSub1); + BigInteger dQ = d.Remainder(qSub1); + BigInteger qInv = q.ModInverse(p); - return new AsymmetricCipherKeyPair( - new RsaKeyParameters(false, n, e), - new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + return new AsymmetricCipherKeyPair( + new RsaKeyParameters(false, n, e), + new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + } } /// <summary>Choose a random prime value for use with RSA</summary> @@ -130,17 +141,19 @@ namespace Org.BouncyCastle.Crypto.Generators /// <returns>a prime p, with (p-1) relatively prime to e</returns> protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e) { + bool eIsKnownOddPrime = (e.BitLength <= SPECIAL_E_BITS) && Arrays.Contains(SPECIAL_E_VALUES, e.IntValue); + for (;;) { - BigInteger p = new BigInteger(bitlength, 1, param.Random); + BigInteger p = new BigInteger(bitlength, 1, parameters.Random); - if (p.Mod(e).Equals(BigInteger.One)) + if (p.Mod(e).Equals(One)) continue; - if (!p.IsProbablePrime(param.Certainty)) + if (!p.IsProbablePrime(parameters.Certainty)) continue; - if (!e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One)) + if (!eIsKnownOddPrime && !e.Gcd(p.Subtract(One)).Equals(One)) continue; return p; diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs index 653d75cb9..e0b1e6b54 100644 --- a/crypto/src/crypto/modes/CcmBlockCipher.cs +++ b/crypto/src/crypto/modes/CcmBlockCipher.cs @@ -61,6 +61,7 @@ namespace Org.BouncyCastle.Crypto.Modes { this.forEncryption = forEncryption; + ICipherParameters cipherParameters; if (parameters is AeadParameters) { AeadParameters param = (AeadParameters) parameters; @@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Modes nonce = param.GetNonce(); initialAssociatedText = param.GetAssociatedText(); macSize = param.MacSize / 8; - keyParam = param.Key; + cipherParameters = param.Key; } else if (parameters is ParametersWithIV) { @@ -77,17 +78,25 @@ namespace Org.BouncyCastle.Crypto.Modes nonce = param.GetIV(); initialAssociatedText = null; macSize = macBlock.Length / 2; - keyParam = param.Parameters; + cipherParameters = param.Parameters; } else { throw new ArgumentException("invalid parameters passed to CCM"); } + // NOTE: Very basic support for key re-use, but no performance gain from it + if (cipherParameters != null) + { + keyParam = cipherParameters; + } + if (nonce == null || nonce.Length < 7 || nonce.Length > 13) { throw new ArgumentException("nonce must have length from 7 to 13 octets"); } + + Reset(); } public virtual string AlgorithmName @@ -128,6 +137,8 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] outBytes, int outOff) { + Check.DataLength(inBytes, inOff, inLen, "Input buffer too short"); + data.Write(inBytes, inOff, inLen); return 0; @@ -137,13 +148,11 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] outBytes, int outOff) { - byte[] enc = ProcessPacket(data.GetBuffer(), 0, (int)data.Position); - - Array.Copy(enc, 0, outBytes, outOff, enc.Length); + int len = ProcessPacket(data.GetBuffer(), 0, (int)data.Position, outBytes, outOff); Reset(); - return enc.Length; + return len; } public virtual void Reset() @@ -161,11 +170,7 @@ namespace Org.BouncyCastle.Crypto.Modes */ public virtual byte[] GetMac() { - byte[] mac = new byte[macSize]; - - Array.Copy(macBlock, 0, mac, 0, mac.Length); - - return mac; + return Arrays.CopyOfRange(macBlock, 0, macSize); } public virtual int GetUpdateOutputSize( @@ -174,7 +179,7 @@ namespace Org.BouncyCastle.Crypto.Modes return 0; } - public int GetOutputSize( + public virtual int GetOutputSize( int len) { int totalData = (int)data.Length + len; @@ -187,10 +192,51 @@ namespace Org.BouncyCastle.Crypto.Modes return totalData < macSize ? 0 : totalData - macSize; } - public byte[] ProcessPacket( - byte[] input, - int inOff, - int inLen) + /** + * Process a packet of data for either CCM decryption or encryption. + * + * @param in data for processing. + * @param inOff offset at which data starts in the input array. + * @param inLen length of the data in the input array. + * @return a byte array containing the processed input.. + * @throws IllegalStateException if the cipher is not appropriately set up. + * @throws InvalidCipherTextException if the input data is truncated or the mac check fails. + */ + public virtual byte[] ProcessPacket(byte[] input, int inOff, int inLen) + { + byte[] output; + + if (forEncryption) + { + output = new byte[inLen + macSize]; + } + else + { + if (inLen < macSize) + throw new InvalidCipherTextException("data too short"); + + output = new byte[inLen - macSize]; + } + + ProcessPacket(input, inOff, inLen, output, 0); + + return output; + } + + /** + * Process a packet of data for either CCM decryption or encryption. + * + * @param in data for processing. + * @param inOff offset at which data starts in the input array. + * @param inLen length of the data in the input array. + * @param output output array. + * @param outOff offset into output array to start putting processed bytes. + * @return the number of bytes added to output. + * @throws IllegalStateException if the cipher is not appropriately set up. + * @throws InvalidCipherTextException if the input data is truncated or the mac check fails. + * @throws DataLengthException if output buffer too short. + */ + public virtual int ProcessPacket(byte[] input, int inOff, int inLen, byte[] output, int outOff) { // TODO: handle null keyParam (e.g. via RepeatedKeySpec) // Need to keep the CTR and CBC Mac parts around and reset @@ -213,42 +259,45 @@ namespace Org.BouncyCastle.Crypto.Modes IBlockCipher ctrCipher = new SicBlockCipher(cipher); ctrCipher.Init(forEncryption, new ParametersWithIV(keyParam, iv)); - int index = inOff; - int outOff = 0; - byte[] output; + int outputLen; + int inIndex = inOff; + int outIndex = outOff; if (forEncryption) { - output = new byte[inLen + macSize]; + outputLen = inLen + macSize; + Check.OutputLength(output, outOff, outputLen, "Output buffer too short."); calculateMac(input, inOff, inLen, macBlock); ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); // S0 - while (index < inLen - BlockSize) // S1... + while (inIndex < (inOff + inLen - BlockSize)) // S1... { - ctrCipher.ProcessBlock(input, index, output, outOff); - outOff += BlockSize; - index += BlockSize; + ctrCipher.ProcessBlock(input, inIndex, output, outIndex); + outIndex += BlockSize; + inIndex += BlockSize; } byte[] block = new byte[BlockSize]; - Array.Copy(input, index, block, 0, inLen - index); + Array.Copy(input, inIndex, block, 0, inLen + inOff - inIndex); ctrCipher.ProcessBlock(block, 0, block, 0); - Array.Copy(block, 0, output, outOff, inLen - index); + Array.Copy(block, 0, output, outIndex, inLen + inOff - inIndex); - outOff += inLen - index; - - Array.Copy(macBlock, 0, output, outOff, output.Length - outOff); + Array.Copy(macBlock, 0, output, outOff + inLen, macSize); } else { - output = new byte[inLen - macSize]; + if (inLen < macSize) + throw new InvalidCipherTextException("data too short"); - Array.Copy(input, inOff + inLen - macSize, macBlock, 0, macSize); + outputLen = inLen - macSize; + Check.OutputLength(output, outOff, outputLen, "Output buffer too short."); + + Array.Copy(input, inOff + outputLen, macBlock, 0, macSize); ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); @@ -257,30 +306,30 @@ namespace Org.BouncyCastle.Crypto.Modes macBlock[i] = 0; } - while (outOff < output.Length - BlockSize) + while (inIndex < (inOff + outputLen - BlockSize)) { - ctrCipher.ProcessBlock(input, index, output, outOff); - outOff += BlockSize; - index += BlockSize; + ctrCipher.ProcessBlock(input, inIndex, output, outIndex); + outIndex += BlockSize; + inIndex += BlockSize; } byte[] block = new byte[BlockSize]; - Array.Copy(input, index, block, 0, output.Length - outOff); + Array.Copy(input, inIndex, block, 0, outputLen - (inIndex - inOff)); ctrCipher.ProcessBlock(block, 0, block, 0); - Array.Copy(block, 0, output, outOff, output.Length - outOff); + Array.Copy(block, 0, output, outIndex, outputLen - (inIndex - inOff)); byte[] calculatedMacBlock = new byte[BlockSize]; - calculateMac(output, 0, output.Length, calculatedMacBlock); + calculateMac(output, outOff, outputLen, calculatedMacBlock); if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock)) throw new InvalidCipherTextException("mac check in CCM failed"); } - return output; + return outputLen; } private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock) diff --git a/crypto/src/crypto/modes/CtsBlockCipher.cs b/crypto/src/crypto/modes/CtsBlockCipher.cs index a32b49675..ff37844ab 100644 --- a/crypto/src/crypto/modes/CtsBlockCipher.cs +++ b/crypto/src/crypto/modes/CtsBlockCipher.cs @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Modes } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs index 5ccc69b66..624f385b5 100644 --- a/crypto/src/crypto/modes/EAXBlockCipher.cs +++ b/crypto/src/crypto/modes/EAXBlockCipher.cs @@ -54,7 +54,6 @@ namespace Org.BouncyCastle.Crypto.Modes blockSize = cipher.GetBlockSize(); mac = new CMac(cipher); macBlock = new byte[blockSize]; - bufBlock = new byte[blockSize * 2]; associatedTextMac = new byte[mac.GetMacSize()]; nonceMac = new byte[mac.GetMacSize()]; this.cipher = new SicBlockCipher(cipher); @@ -65,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Modes get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; } } - public IBlockCipher GetUnderlyingCipher() + public virtual IBlockCipher GetUnderlyingCipher() { return cipher; } @@ -107,6 +106,8 @@ namespace Org.BouncyCastle.Crypto.Modes throw new ArgumentException("invalid parameters passed to EAX"); } + bufBlock = new byte[forEncryption ? blockSize : (blockSize + macSize)]; + byte[] tag = new byte[blockSize]; // Key reuse implemented in CBC mode of underlying CMac @@ -117,16 +118,10 @@ namespace Org.BouncyCastle.Crypto.Modes mac.BlockUpdate(nonce, 0, nonce.Length); mac.DoFinal(nonceMac, 0); - tag[blockSize - 1] = (byte)Tag.H; - mac.BlockUpdate(tag, 0, blockSize); - - if (initialAssociatedText != null) - { - ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); - } - - // Same BlockCipher underlies this and the mac, so reuse last key on cipher + // Same BlockCipher underlies this and the mac, so reuse last key on cipher cipher.Init(true, new ParametersWithIV(null, nonceMac)); + + Reset(); } private void InitCipher() @@ -191,16 +186,16 @@ namespace Org.BouncyCastle.Crypto.Modes { if (cipherInitialized) { - throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); } mac.Update(input); } - public void ProcessAadBytes(byte[] inBytes, int inOff, int len) + public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) { if (cipherInitialized) { - throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); } mac.BlockUpdate(inBytes, inOff, len); } @@ -247,10 +242,11 @@ namespace Org.BouncyCastle.Crypto.Modes if (forEncryption) { - cipher.ProcessBlock(bufBlock, 0, tmp, 0); - cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); + Check.OutputLength(outBytes, outOff, extra + macSize, "Output buffer too short"); + + cipher.ProcessBlock(bufBlock, 0, tmp, 0); - Array.Copy(tmp, 0, outBytes, outOff, extra); + Array.Copy(tmp, 0, outBytes, outOff, extra); mac.BlockUpdate(tmp, 0, extra); @@ -264,14 +260,18 @@ namespace Org.BouncyCastle.Crypto.Modes } else { - if (extra > macSize) + if (extra < macSize) + throw new InvalidCipherTextException("data too short"); + + Check.OutputLength(outBytes, outOff, extra - macSize, "Output buffer too short"); + + if (extra > macSize) { mac.BlockUpdate(bufBlock, 0, extra - macSize); cipher.ProcessBlock(bufBlock, 0, tmp, 0); - cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); - Array.Copy(tmp, 0, outBytes, outOff, extra - macSize); + Array.Copy(tmp, 0, outBytes, outOff, extra - macSize); } CalculateMac(); @@ -331,6 +331,11 @@ namespace Org.BouncyCastle.Crypto.Modes if (bufOff == bufBlock.Length) { + Check.OutputLength(outBytes, outOff, blockSize, "Output buffer is too short"); + + // TODO Could move the ProcessByte(s) calls to here +// InitCipher(); + int size; if (forEncryption) @@ -346,10 +351,14 @@ namespace Org.BouncyCastle.Crypto.Modes size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff); } - bufOff = blockSize; - Array.Copy(bufBlock, blockSize, bufBlock, 0, blockSize); + bufOff = 0; + if (!forEncryption) + { + Array.Copy(bufBlock, blockSize, bufBlock, 0, macSize); + bufOff = macSize; + } - return size; + return size; } return 0; diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs index 2e2ac2eca..8e6120eef 100644 --- a/crypto/src/crypto/modes/GCMBlockCipher.cs +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -284,6 +284,9 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] output, int outOff) { + if (input.Length < (inOff + len)) + throw new DataLengthException("Input buffer too short"); + int resultLen = 0; for (int i = 0; i < len; ++i) @@ -301,6 +304,7 @@ namespace Org.BouncyCastle.Crypto.Modes private void OutputBlock(byte[] output, int offset) { + Check.OutputLength(output, offset, BlockSize, "Output buffer too short"); if (totalLength == 0) { InitCipher(); @@ -325,12 +329,19 @@ namespace Org.BouncyCastle.Crypto.Modes } int extra = bufOff; - if (!forEncryption) + + if (forEncryption) + { + Check.OutputLength(output, outOff, extra + macSize, "Output buffer too short"); + } + else { if (extra < macSize) throw new InvalidCipherTextException("data too short"); extra -= macSize; + + Check.OutputLength(output, outOff, extra, "Output buffer too short"); } if (extra > 0) diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs index 54359dfe8..e7dc466e6 100644 --- a/crypto/src/crypto/modes/OCBBlockCipher.cs +++ b/crypto/src/crypto/modes/OCBBlockCipher.cs @@ -355,6 +355,7 @@ namespace Org.BouncyCastle.Crypto.Modes Xor(mainBlock, Pad); + Check.OutputLength(output, outOff, mainBlockPos, "Output buffer too short"); Array.Copy(mainBlock, 0, output, outOff, mainBlockPos); if (!forEncryption) @@ -382,6 +383,8 @@ namespace Org.BouncyCastle.Crypto.Modes if (forEncryption) { + Check.OutputLength(output, outOff, resultLen + macSize, "Output buffer too short"); + // Append tag to the message Array.Copy(macBlock, 0, output, outOff + resultLen, macSize); resultLen += macSize; @@ -431,6 +434,8 @@ namespace Org.BouncyCastle.Crypto.Modes protected virtual void ProcessMainBlock(byte[] output, int outOff) { + Check.DataLength(output, outOff, BLOCK_SIZE, "Output buffer too short"); + /* * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks */ diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs index 0f241035f..de41d88f4 100644 --- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -106,6 +106,29 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm x[3] = r13; } + internal static void Multiply(ulong[] x, ulong[] y) + { + ulong r00 = x[0], r01 = x[1], r10 = 0, r11 = 0; + + for (int i = 0; i < 2; ++i) + { + long bits = (long)y[i]; + for (int j = 0; j < 64; ++j) + { + ulong m1 = (ulong)(bits >> 63); bits <<= 1; + r10 ^= (r00 & m1); + r11 ^= (r01 & m1); + + ulong m2 = (r01 << 63) >> 8; + r01 = (r01 >> 1) | (r00 << 63); + r00 = (r00 >> 1) ^ (m2 & E1L); + } + } + + x[0] = r10; + x[1] = r11; + } + // P is the value with only bit i=1 set internal static void MultiplyP(uint[] x) { diff --git a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs index fb8a92ba3..5d2f8cf15 100644 --- a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs +++ b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Paddings } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. @@ -178,10 +178,7 @@ namespace Org.BouncyCastle.Crypto.Paddings if (outLength > 0) { - if ((outOff + outLength) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.OutputLength(output, outOff, outLength, "output buffer too short"); } int resultLen = 0; @@ -242,7 +239,7 @@ namespace Org.BouncyCastle.Crypto.Paddings { Reset(); - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } resultLen = cipher.ProcessBlock(buf, 0, output, outOff); diff --git a/crypto/src/crypto/parameters/Srp6GroupParameters.cs b/crypto/src/crypto/parameters/Srp6GroupParameters.cs new file mode 100644 index 000000000..6762dd31d --- /dev/null +++ b/crypto/src/crypto/parameters/Srp6GroupParameters.cs @@ -0,0 +1,27 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class Srp6GroupParameters + { + private readonly BigInteger n, g; + + public Srp6GroupParameters(BigInteger N, BigInteger g) + { + this.n = N; + this.g = g; + } + + public BigInteger G + { + get { return g; } + } + + public BigInteger N + { + get { return n; } + } + } +} diff --git a/crypto/src/crypto/signers/DsaDigestSigner.cs b/crypto/src/crypto/signers/DsaDigestSigner.cs index aee713450..086601481 100644 --- a/crypto/src/crypto/signers/DsaDigestSigner.cs +++ b/crypto/src/crypto/signers/DsaDigestSigner.cs @@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Crypto.Signers this.dsaSigner = signer; } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) @@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using * the key we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("DSADigestSigner not initialised for signature generation."); @@ -97,7 +97,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <returns>true if the internal state represents the signature described in the passed in array.</returns> - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <summary>Reset the internal state</summary> - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs index 6027aa9b9..28ab79c1c 100644 --- a/crypto/src/crypto/signers/ECGOST3410Signer.cs +++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs @@ -18,12 +18,12 @@ namespace Org.BouncyCastle.Crypto.Signers private ECKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ECGOST3410"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers * * @param message the message that will be verified later. */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { byte[] mRev = new byte[message.Length]; // conversion is little-endian @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Signers * the passed in message (for standard GOST3410 the message should be * a GOST3411 hash of the real message to be verified). */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/ECNRSigner.cs b/crypto/src/crypto/signers/ECNRSigner.cs index cae15bdbf..bb21a4994 100644 --- a/crypto/src/crypto/signers/ECNRSigner.cs +++ b/crypto/src/crypto/signers/ECNRSigner.cs @@ -19,12 +19,12 @@ namespace Org.BouncyCastle.Crypto.Signers private ECKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ECNR"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param digest the digest to be signed. * @exception DataLengthException if the digest is longer than the key allows */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { if (!this.forSigning) @@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param s the s value of the signature. * @exception DataLengthException if the digest is longer than the key allows */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/GOST3410DigestSigner.cs b/crypto/src/crypto/signers/GOST3410DigestSigner.cs index 58aefa368..bc32808df 100644 --- a/crypto/src/crypto/signers/GOST3410DigestSigner.cs +++ b/crypto/src/crypto/signers/GOST3410DigestSigner.cs @@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Crypto.Signers this.digest = digest; } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) @@ -86,7 +86,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using * the key we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation."); @@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <returns>true if the internal state represents the signature described in the passed in array.</returns> - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -137,7 +137,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <summary>Reset the internal state</summary> - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs index 375eeb5cc..f1832ae37 100644 --- a/crypto/src/crypto/signers/GOST3410Signer.cs +++ b/crypto/src/crypto/signers/GOST3410Signer.cs @@ -15,12 +15,12 @@ namespace Org.BouncyCastle.Crypto.Signers private Gost3410KeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "GOST3410"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers * * @param message the message that will be verified later. */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { byte[] mRev = new byte[message.Length]; // conversion is little-endian @@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Signers * the passed in message for standard Gost3410 the message should be a * Gost3411 hash of the real message to be verified. */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/GenericSigner.cs b/crypto/src/crypto/signers/GenericSigner.cs index 5035b454d..a5512176f 100644 --- a/crypto/src/crypto/signers/GenericSigner.cs +++ b/crypto/src/crypto/signers/GenericSigner.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.digest = digest; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; } } @@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param parameters * necessary parameters. */ - public void Init(bool forSigning, ICipherParameters parameters) + public virtual void Init(bool forSigning, ICipherParameters parameters) { this.forSigning = forSigning; @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update(byte input) + public virtual void Update(byte input) { digest.Update(input); } @@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate(byte[] input, int inOff, int length) + public virtual void BlockUpdate(byte[] input, int inOff, int length) { digest.BlockUpdate(input, inOff, length); } @@ -79,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using the key * we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("GenericSigner not initialised for signature generation."); @@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Crypto.Signers * return true if the internal state represents the signature described in * the passed in array. */ - public bool VerifySignature(byte[] signature) + public virtual bool VerifySignature(byte[] signature) { if (forSigning) throw new InvalidOperationException("GenericSigner not initialised for verification"); @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Signers } } - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs index d4f6c5522..1486656bd 100644 --- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs @@ -120,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + "ISO9796-2S2"; } } @@ -365,7 +365,7 @@ namespace Org.BouncyCastle.Crypto.Signers /// <summary> Generate a signature for the loaded message using the key we were /// initialised with. /// </summary> - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { int digSize = digest.GetDigestSize(); byte[] m2Hash = new byte[digSize]; diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs index cfb8942e6..4bb4d17a6 100644 --- a/crypto/src/crypto/signers/Iso9796d2Signer.cs +++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs @@ -105,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + "ISO9796-2S1"; } } @@ -252,7 +252,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <summary> update the internal digest with the byte b</summary> - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -266,7 +266,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// <summary> update the internal digest with the byte array in</summary> - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index 6900224f3..03890902b 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.trailer = trailer; } - public string AlgorithmName + public virtual string AlgorithmName { get { return mgfDigest.AlgorithmName + "withRSAandMGF1"; } } diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs index 9af4e7145..d9b19cf6b 100644 --- a/crypto/src/crypto/signers/RsaDigestSigner.cs +++ b/crypto/src/crypto/signers/RsaDigestSigner.cs @@ -64,8 +64,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.algId = algId; } - [Obsolete] - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "withRSA"; } } @@ -76,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param forSigning true if for signing, false otherwise * @param param necessary parameters. */ - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -106,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -115,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) @@ -127,7 +126,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using * the key we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("RsaDigestSigner not initialised for signature generation."); @@ -143,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Signers * return true if the internal state represents the signature described * in the passed in array. */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -197,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Signers } } - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs new file mode 100644 index 000000000..89f512b78 --- /dev/null +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * X9.31-1998 - signing using a hash. + * <p> + * The message digest hash, H, is encapsulated to form a byte string as follows + * </p> + * <pre> + * EB = 06 || PS || 0xBA || H || TRAILER + * </pre> + * where PS is a string of bytes all of value 0xBB of length such that |EB|=|n|, and TRAILER is the ISO/IEC 10118 part number†for the digest. The byte string, EB, is converted to an integer value, the message representative, f. + */ + public class X931Signer + : ISigner + { + public const int TRAILER_IMPLICIT = 0xBC; + public const int TRAILER_RIPEMD160 = 0x31CC; + public const int TRAILER_RIPEMD128 = 0x32CC; + public const int TRAILER_SHA1 = 0x33CC; + public const int TRAILER_SHA256 = 0x34CC; + public const int TRAILER_SHA512 = 0x35CC; + public const int TRAILER_SHA384 = 0x36CC; + public const int TRAILER_WHIRLPOOL = 0x37CC; + public const int TRAILER_SHA224 = 0x38CC; + + private static readonly IDictionary trailerMap = Platform.CreateHashtable(); + + static X931Signer() + { + trailerMap.Add("RIPEMD128", TRAILER_RIPEMD128); + trailerMap.Add("RIPEMD160", TRAILER_RIPEMD160); + + trailerMap.Add("SHA-1", TRAILER_SHA1); + trailerMap.Add("SHA-224", TRAILER_SHA224); + trailerMap.Add("SHA-256", TRAILER_SHA256); + trailerMap.Add("SHA-384", TRAILER_SHA384); + trailerMap.Add("SHA-512", TRAILER_SHA512); + + trailerMap.Add("Whirlpool", TRAILER_WHIRLPOOL); + } + + private IDigest digest; + private IAsymmetricBlockCipher cipher; + private RsaKeyParameters kParam; + + private int trailer; + private int keyBits; + private byte[] block; + + /** + * Generate a signer for the with either implicit or explicit trailers + * for ISO9796-2. + * + * @param cipher base cipher to use for signature creation/verification + * @param digest digest to use. + * @param implicit whether or not the trailer is implicit or gives the hash. + */ + public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit) + { + this.cipher = cipher; + this.digest = digest; + + if (isImplicit) + { + trailer = TRAILER_IMPLICIT; + } + else + { + string name = digest.AlgorithmName; + if (!trailerMap.Contains(name)) + throw new ArgumentException("no valid trailer", "digest"); + + trailer = (int)trailerMap[name]; + } + } + + public virtual string AlgorithmName + { + get { return digest.AlgorithmName + "with" + cipher.AlgorithmName + "/X9.31"; } + } + + /** + * Constructor for a signer with an explicit digest trailer. + * + * @param cipher cipher to use. + * @param digest digest to sign with. + */ + public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest) + : this(cipher, digest, false) + { + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + kParam = (RsaKeyParameters)parameters; + + cipher.Init(forSigning, kParam); + + keyBits = kParam.Modulus.BitLength; + + block = new byte[(keyBits + 7) / 8]; + + Reset(); + } + + /// <summary> clear possible sensitive data</summary> + private void ClearBlock(byte[] block) + { + Array.Clear(block, 0, block.Length); + } + + /** + * update the internal digest with the byte b + */ + public virtual void Update(byte b) + { + digest.Update(b); + } + + /** + * update the internal digest with the byte array in + */ + public virtual void BlockUpdate(byte[] input, int off, int len) + { + digest.BlockUpdate(input, off, len); + } + + /** + * reset the internal state + */ + public virtual void Reset() + { + digest.Reset(); + } + + /** + * generate a signature for the loaded message using the key we were + * initialised with. + */ + public virtual byte[] GenerateSignature() + { + CreateSignatureBlock(); + + BigInteger t = new BigInteger(1, cipher.ProcessBlock(block, 0, block.Length)); + ClearBlock(block); + + t = t.Min(kParam.Modulus.Subtract(t)); + + return BigIntegers.AsUnsignedByteArray((kParam.Modulus.BitLength + 7) / 8, t); + } + + private void CreateSignatureBlock() + { + int digSize = digest.GetDigestSize(); + + int delta; + + if (trailer == TRAILER_IMPLICIT) + { + delta = block.Length - digSize - 1; + digest.DoFinal(block, delta); + block[block.Length - 1] = (byte)TRAILER_IMPLICIT; + } + else + { + delta = block.Length - digSize - 2; + digest.DoFinal(block, delta); + block[block.Length - 2] = (byte)(trailer >> 8); + block[block.Length - 1] = (byte)trailer; + } + + block[0] = 0x6b; + for (int i = delta - 2; i != 0; i--) + { + block[i] = (byte)0xbb; + } + block[delta - 1] = (byte)0xba; + } + + /** + * return true if the signature represents a ISO9796-2 signature + * for the passed in message. + */ + public virtual bool VerifySignature(byte[] signature) + { + try + { + block = cipher.ProcessBlock(signature, 0, signature.Length); + } + catch (Exception) + { + return false; + } + + BigInteger t = new BigInteger(block); + BigInteger f; + + if ((t.IntValue & 15) == 12) + { + f = t; + } + else + { + t = kParam.Modulus.Subtract(t); + if ((t.IntValue & 15) == 12) + { + f = t; + } + else + { + return false; + } + } + + CreateSignatureBlock(); + + byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f); + + bool rv = Arrays.ConstantTimeAreEqual(block, fBlock); + + ClearBlock(block); + ClearBlock(fBlock); + + return rv; + } + } +} diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs index 771bc004b..046feb78c 100644 --- a/crypto/src/crypto/tls/AbstractTlsClient.cs +++ b/crypto/src/crypto/tls/AbstractTlsClient.cs @@ -117,27 +117,7 @@ namespace Org.BouncyCastle.Crypto.Tls { // TODO Provide a way for the user to specify the acceptable hash/signature algorithms. - byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; - - // TODO Sort out ECDSA signatures and add them as the preferred option here - byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa }; - - this.mSupportedSignatureAlgorithms = Platform.CreateArrayList(); - for (int i = 0; i < hashAlgorithms.Length; ++i) - { - for (int j = 0; j < signatureAlgorithms.Length; ++j) - { - this.mSupportedSignatureAlgorithms.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i], - signatureAlgorithms[j])); - } - } - - /* - * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1. - */ - this.mSupportedSignatureAlgorithms.Add(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, - SignatureAlgorithm.dsa)); + this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions); @@ -263,6 +243,14 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public override TlsCipher GetCipher() + { + int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite); + int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite); + + return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm); + } + public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket) { } diff --git a/crypto/src/crypto/tls/AbstractTlsContext.cs b/crypto/src/crypto/tls/AbstractTlsContext.cs index 83150d37e..e283ee58c 100644 --- a/crypto/src/crypto/tls/AbstractTlsContext.cs +++ b/crypto/src/crypto/tls/AbstractTlsContext.cs @@ -96,6 +96,15 @@ namespace Org.BouncyCastle.Crypto.Tls public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length) { + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 5.4. If a client or server chooses to continue with a full + * handshake without the extended master secret extension, [..] the client or server MUST + * NOT export any key material based on the new master secret for any subsequent + * application-level authentication. In particular, it MUST disable [RFC5705] [..]. + */ + if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length)) throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value"); diff --git a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs index 155ac94d8..c9ec06107 100644 --- a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs +++ b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected readonly int mKeyExchange; protected IList mSupportedSignatureAlgorithms; - protected TlsContext context; + protected TlsContext mContext; protected AbstractTlsKeyExchange(int keyExchange, IList supportedSignatureAlgorithms) { @@ -20,7 +20,7 @@ namespace Org.BouncyCastle.Crypto.Tls public virtual void Init(TlsContext context) { - this.context = context; + this.mContext = context; ProtocolVersion clientVersion = context.ClientVersion; diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs index b0a5f0d52..7fe3fcbe5 100644 --- a/crypto/src/crypto/tls/AbstractTlsServer.cs +++ b/crypto/src/crypto/tls/AbstractTlsServer.cs @@ -320,6 +320,14 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public override TlsCipher GetCipher() + { + int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite); + int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite); + + return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm); + } + public virtual NewSessionTicket GetNewSessionTicket() { /* diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs index ec98413b7..ff7e6da85 100644 --- a/crypto/src/crypto/tls/DefaultTlsClient.cs +++ b/crypto/src/crypto/tls/DefaultTlsClient.cs @@ -28,9 +28,18 @@ namespace Org.BouncyCastle.Crypto.Tls { return new int[] { + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, @@ -39,395 +48,28 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); - - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); - - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS); - - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); - - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); - - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); - - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return CreateRsaKeyExchange(); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DH_RSA: + return CreateDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.DHE_RSA: + return CreateDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDH_RSA: + return CreateECDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); + case KeyExchangeAlgorithm.ECDHE_ECDSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return CreateECDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.RSA: + return CreateRsaKeyExchange(); default: /* diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs index 75f6d8d88..b12c43e1c 100644 --- a/crypto/src/crypto/tls/DefaultTlsServer.cs +++ b/crypto/src/crypto/tls/DefaultTlsServer.cs @@ -20,6 +20,16 @@ namespace Org.BouncyCastle.Crypto.Tls { } + protected virtual TlsSignerCredentials GetDsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + protected virtual TlsSignerCredentials GetECDsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + protected virtual TlsEncryptionCredentials GetRsaEncryptionCredentials() { throw new TlsFatalAlert(AlertDescription.internal_error); @@ -45,6 +55,12 @@ namespace Org.BouncyCastle.Crypto.Tls CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256, @@ -56,472 +72,62 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsCredentials GetCredentials() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return GetRsaEncryptionCredentials(); - - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return GetRsaSignerCredentials(); - - default: - /* - * Note: internal error here; selected a key exchange we don't implement! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - public override TlsKeyExchange GetKeyExchange() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); - - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); - - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS); + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DHE_DSS: + return GetDsaSignerCredentials(); - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDHE_ECDSA: + return GetECDsaSignerCredentials(); - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); + case KeyExchangeAlgorithm.DHE_RSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return GetRsaSignerCredentials(); - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); + case KeyExchangeAlgorithm.RSA: + return GetRsaEncryptionCredentials(); - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); - - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); - - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return createRSAKeyExchange(); - - default: - /* - * Note: internal error here; selected a key exchange we don't implement! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } - public override TlsCipher GetCipher() + public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DH_RSA: + return CreateDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5); + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.DHE_RSA: + return CreateDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDH_RSA: + return CreateECDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.ECDHE_ECDSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return CreateECDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.RSA: + return CreateRsaKeyExchange(); default: /* - * Note: internal error here; selected a cipher suite we don't implement! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } @@ -548,7 +154,7 @@ namespace Org.BouncyCastle.Crypto.Tls mServerECPointFormats); } - protected virtual TlsKeyExchange createRSAKeyExchange() + protected virtual TlsKeyExchange CreateRsaKeyExchange() { return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms); } diff --git a/crypto/src/crypto/tls/DefaultTlsSrpGroupVerifier.cs b/crypto/src/crypto/tls/DefaultTlsSrpGroupVerifier.cs new file mode 100644 index 000000000..cc933bff9 --- /dev/null +++ b/crypto/src/crypto/tls/DefaultTlsSrpGroupVerifier.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class DefaultTlsSrpGroupVerifier + : TlsSrpGroupVerifier + { + protected static readonly IList DefaultGroups = Platform.CreateArrayList(); + + static DefaultTlsSrpGroupVerifier() + { + DefaultGroups.Add(Srp6StandardGroups.rfc5054_1024); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_1536); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_2048); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_3072); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_4096); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_6144); + DefaultGroups.Add(Srp6StandardGroups.rfc5054_8192); + } + + // Vector is (SRP6GroupParameters) + protected readonly IList mGroups; + + /** + * Accept only the group parameters specified in RFC 5054 Appendix A. + */ + public DefaultTlsSrpGroupVerifier() + : this(DefaultGroups) + { + } + + /** + * Specify a custom set of acceptable group parameters. + * + * @param groups a {@link Vector} of acceptable {@link SRP6GroupParameters} + */ + public DefaultTlsSrpGroupVerifier(IList groups) + { + this.mGroups = groups; + } + + public virtual bool Accept(Srp6GroupParameters group) + { + foreach (Srp6GroupParameters entry in mGroups) + { + if (AreGroupsEqual(group, entry)) + { + return true; + } + } + return false; + } + + protected virtual bool AreGroupsEqual(Srp6GroupParameters a, Srp6GroupParameters b) + { + return a == b || (AreParametersEqual(a.N, b.N) && AreParametersEqual(a.G, b.G)); + } + + protected virtual bool AreParametersEqual(BigInteger a, BigInteger b) + { + return a == b || a.Equals(b); + } + } +} diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs index 2aa4df692..76635065c 100644 --- a/crypto/src/crypto/tls/DtlsClientProtocol.cs +++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, state.clientContext, client, ContentType.handshake); TlsSession sessionToResume = state.client.GetSessionToResume(); - if (sessionToResume != null) + if (sessionToResume != null && sessionToResume.IsResumable) { SessionParameters sessionParameters = sessionToResume.ExportSessionParameters(); if (sessionParameters != null) @@ -143,6 +143,8 @@ namespace Org.BouncyCastle.Crypto.Tls IDictionary sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); + // TODO Check encrypt-then-MAC extension and maybe others + securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); securityParameters.masterSecret = Arrays.Clone(state.sessionParameters.MasterSecret); @@ -317,23 +319,17 @@ namespace Org.BouncyCastle.Crypto.Tls /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - byte[] hash; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + state.clientContext, signerCredentials); - if (TlsUtilities.IsTlsV12(state.clientContext)) + byte[] hash; + if (signatureAndHashAlgorithm == null) { - signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - { - throw new TlsFatalAlert(AlertDescription.internal_error); - } - - hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); + hash = securityParameters.SessionHash; } else { - signatureAndHashAlgorithm = null; - hash = securityParameters.SessionHash; + hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); @@ -375,6 +371,7 @@ namespace Org.BouncyCastle.Crypto.Tls .SetMasterSecret(securityParameters.masterSecret) .SetPeerCertificate(serverCertificate) .SetPskIdentity(securityParameters.pskIdentity) + .SetSrpIdentity(securityParameters.srpIdentity) .Build(); state.tlsSession = TlsUtilities.ImportSession(state.tlsSession.SessionID, state.sessionParameters); @@ -435,8 +432,6 @@ namespace Org.BouncyCastle.Crypto.Tls // Integer -> byte[] state.clientExtensions = client.GetClientExtensions(); - securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions); - // Cipher Suites (and SCSV) { /* @@ -651,15 +646,6 @@ namespace Org.BouncyCastle.Crypto.Tls IDictionary serverExtensions = TlsProtocol.ReadExtensions(buf); /* - * draft-ietf-tls-session-hash-01 5.2. If a server receives the "extended_master_secret" - * extension, it MUST include the "extended_master_secret" extension in its ServerHello - * message. - */ - bool serverSentExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions); - if (serverSentExtendedMasterSecret != securityParameters.extendedMasterSecret) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - - /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. However, see RFC 5746 exception below. We always include * the SCSV, so an Extended Server Hello is always allowed. @@ -689,15 +675,6 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.unsupported_extension); /* - * draft-ietf-tls-session-hash-01 5.2. Implementation note: if the server decides to - * proceed with resumption, the extension does not have any effect. Requiring the - * extension to be included anyway makes the extension negotiation logic easier, - * because it does not depend on whether resumption is accepted or not. - */ - if (extType == ExtensionType.extended_master_secret) - continue; - - /* * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and send a server hello containing no * extensions[.] @@ -748,6 +725,8 @@ namespace Org.BouncyCastle.Crypto.Tls securityParameters.encryptThenMac = serverSentEncryptThenMAC; + securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions); + state.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions, AlertDescription.illegal_parameter); @@ -760,6 +739,13 @@ namespace Org.BouncyCastle.Crypto.Tls ExtensionType.session_ticket, AlertDescription.illegal_parameter); } + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ + state.client.NotifySecureRenegotiation(state.secure_renegotiation); if (state.clientExtensions != null) diff --git a/crypto/src/crypto/tls/DtlsReliableHandshake.cs b/crypto/src/crypto/tls/DtlsReliableHandshake.cs index bf9e61d03..8e4439e67 100644 --- a/crypto/src/crypto/tls/DtlsReliableHandshake.cs +++ b/crypto/src/crypto/tls/DtlsReliableHandshake.cs @@ -114,17 +114,17 @@ namespace Org.BouncyCastle.Crypto.Tls { for (; ; ) { - int Received = mRecordLayer.Receive(buf, 0, receiveLimit, readTimeoutMillis); - if (Received < 0) + int received = mRecordLayer.Receive(buf, 0, receiveLimit, readTimeoutMillis); + if (received < 0) { break; } - if (Received < 12) + if (received < 12) { continue; } int fragment_length = TlsUtilities.ReadUint24(buf, 9); - if (Received != (fragment_length + 12)) + if (received != (fragment_length + 12)) { continue; } diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs index 3335a9f36..f148eb7d7 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs @@ -538,6 +538,12 @@ namespace Org.BouncyCastle.Crypto.Tls TlsServerContextImpl context = state.serverContext; SecurityParameters securityParameters = context.SecurityParameters; + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions); context.SetClientVersion(client_version); diff --git a/crypto/src/crypto/tls/ExporterLabel.cs b/crypto/src/crypto/tls/ExporterLabel.cs index 280321e2a..5970769d7 100644 --- a/crypto/src/crypto/tls/ExporterLabel.cs +++ b/crypto/src/crypto/tls/ExporterLabel.cs @@ -30,7 +30,7 @@ namespace Org.BouncyCastle.Crypto.Tls public const string dtls_srtp = "EXTRACTOR-dtls_srtp"; /* - * draft-ietf-tls-session-hash-01 + * draft-ietf-tls-session-hash-04 */ public static readonly string extended_master_secret = "extended master secret"; } diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs index acee380b6..b4b24f7c3 100644 --- a/crypto/src/crypto/tls/ExtensionType.cs +++ b/crypto/src/crypto/tls/ExtensionType.cs @@ -49,7 +49,7 @@ namespace Org.BouncyCastle.Crypto.Tls public const int encrypt_then_mac = 22; /* - * draft-ietf-tls-session-hash-01 + * draft-ietf-tls-session-hash-04 * * NOTE: Early code-point assignment */ diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs index 1f4b0865c..2ef80dcfd 100644 --- a/crypto/src/crypto/tls/PskTlsClient.cs +++ b/crypto/src/crypto/tls/PskTlsClient.cs @@ -32,87 +32,15 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); - - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + return CreatePskKeyExchange(keyExchangeAlgorithm); default: /* @@ -133,134 +61,6 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.internal_error); } - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves, diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs index bdb8b74a5..27d2b8119 100644 --- a/crypto/src/crypto/tls/PskTlsServer.cs +++ b/crypto/src/crypto/tls/PskTlsServer.cs @@ -44,301 +44,47 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsCredentials GetCredentials() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return null; + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + return null; - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return GetRsaEncryptionCredentials(); + case KeyExchangeAlgorithm.RSA_PSK: + return GetRsaEncryptionCredentials(); - default: - /* Note: internal error here; selected a key exchange we don't implement! */ - throw new TlsFatalAlert(AlertDescription.internal_error); + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); - - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK); - - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + return CreatePskKeyExchange(keyExchangeAlgorithm); + + default: + /* + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } - protected TlsKeyExchange CreatePskKeyExchange(int keyExchange) + protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats); diff --git a/crypto/src/crypto/tls/SecurityParameters.cs b/crypto/src/crypto/tls/SecurityParameters.cs index 0f48ee23e..3b851587d 100644 --- a/crypto/src/crypto/tls/SecurityParameters.cs +++ b/crypto/src/crypto/tls/SecurityParameters.cs @@ -16,6 +16,7 @@ namespace Org.BouncyCastle.Crypto.Tls internal byte[] serverRandom = null; internal byte[] sessionHash = null; internal byte[] pskIdentity = null; + internal byte[] srpIdentity = null; // TODO Keep these internal, since it's maybe not the ideal place for them internal short maxFragmentLength = -1; @@ -93,5 +94,10 @@ namespace Org.BouncyCastle.Crypto.Tls { get { return pskIdentity; } } + + public virtual byte[] SrpIdentity + { + get { return srpIdentity; } + } } } diff --git a/crypto/src/crypto/tls/ServerSrpParams.cs b/crypto/src/crypto/tls/ServerSrpParams.cs new file mode 100644 index 000000000..556ac5310 --- /dev/null +++ b/crypto/src/crypto/tls/ServerSrpParams.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class ServerSrpParams + { + protected BigInteger m_N, m_g, m_B; + protected byte[] m_s; + + public ServerSrpParams(BigInteger N, BigInteger g, byte[] s, BigInteger B) + { + this.m_N = N; + this.m_g = g; + this.m_s = Arrays.Clone(s); + this.m_B = B; + } + + public virtual BigInteger B + { + get { return m_B; } + } + + public virtual BigInteger G + { + get { return m_g; } + } + + public virtual BigInteger N + { + get { return m_N; } + } + + public virtual byte[] S + { + get { return m_s; } + } + + /** + * Encode this {@link ServerSRPParams} to an {@link OutputStream}. + * + * @param output + * the {@link OutputStream} to encode to. + * @throws IOException + */ + public virtual void Encode(Stream output) + { + TlsSrpUtilities.WriteSrpParameter(m_N, output); + TlsSrpUtilities.WriteSrpParameter(m_g, output); + TlsUtilities.WriteOpaque8(m_s, output); + TlsSrpUtilities.WriteSrpParameter(m_B, output); + } + + /** + * Parse a {@link ServerSRPParams} from an {@link InputStream}. + * + * @param input + * the {@link InputStream} to parse from. + * @return a {@link ServerSRPParams} object. + * @throws IOException + */ + public static ServerSrpParams Parse(Stream input) + { + BigInteger N = TlsSrpUtilities.ReadSrpParameter(input); + BigInteger g = TlsSrpUtilities.ReadSrpParameter(input); + byte[] s = TlsUtilities.ReadOpaque8(input); + BigInteger B = TlsSrpUtilities.ReadSrpParameter(input); + + return new ServerSrpParams(N, g, s, B); + } + } +} diff --git a/crypto/src/crypto/tls/SessionParameters.cs b/crypto/src/crypto/tls/SessionParameters.cs index b17e931d7..a1eb5f27c 100644 --- a/crypto/src/crypto/tls/SessionParameters.cs +++ b/crypto/src/crypto/tls/SessionParameters.cs @@ -15,6 +15,7 @@ namespace Org.BouncyCastle.Crypto.Tls private byte[] mMasterSecret = null; private Certificate mPeerCertificate = null; private byte[] mPskIdentity = null; + private byte[] mSrpIdentity = null; private byte[] mEncodedServerExtensions = null; public Builder() @@ -27,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Tls Validate(this.mCompressionAlgorithm >= 0, "compressionAlgorithm"); Validate(this.mMasterSecret != null, "masterSecret"); return new SessionParameters(mCipherSuite, (byte)mCompressionAlgorithm, mMasterSecret, mPeerCertificate, - mPskIdentity, mEncodedServerExtensions); + mPskIdentity, mSrpIdentity, mEncodedServerExtensions); } public Builder SetCipherSuite(int cipherSuite) @@ -60,6 +61,12 @@ namespace Org.BouncyCastle.Crypto.Tls return this; } + public Builder SetSrpIdentity(byte[] srpIdentity) + { + this.mSrpIdentity = srpIdentity; + return this; + } + public Builder SetServerExtensions(IDictionary serverExtensions) { if (serverExtensions == null) @@ -87,16 +94,18 @@ namespace Org.BouncyCastle.Crypto.Tls private byte[] mMasterSecret; private Certificate mPeerCertificate; private byte[] mPskIdentity; + private byte[] mSrpIdentity; private byte[] mEncodedServerExtensions; private SessionParameters(int cipherSuite, byte compressionAlgorithm, byte[] masterSecret, - Certificate peerCertificate, byte[] pskIdentity, byte[] encodedServerExtensions) + Certificate peerCertificate, byte[] pskIdentity, byte[] srpIdentity, byte[] encodedServerExtensions) { this.mCipherSuite = cipherSuite; this.mCompressionAlgorithm = compressionAlgorithm; this.mMasterSecret = Arrays.Clone(masterSecret); this.mPeerCertificate = peerCertificate; this.mPskIdentity = Arrays.Clone(pskIdentity); + this.mSrpIdentity = Arrays.Clone(srpIdentity); this.mEncodedServerExtensions = encodedServerExtensions; } @@ -111,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Tls public SessionParameters Copy() { return new SessionParameters(mCipherSuite, mCompressionAlgorithm, mMasterSecret, mPeerCertificate, - mPskIdentity, mEncodedServerExtensions); + mPskIdentity, mSrpIdentity, mEncodedServerExtensions); } public int CipherSuite @@ -139,6 +148,11 @@ namespace Org.BouncyCastle.Crypto.Tls get { return mPskIdentity; } } + public byte[] SrpIdentity + { + get { return mSrpIdentity; } + } + public IDictionary ReadServerExtensions() { if (mEncodedServerExtensions == null) diff --git a/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs b/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs new file mode 100644 index 000000000..3e9737cd7 --- /dev/null +++ b/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * An implementation of {@link TlsSRPIdentityManager} that simulates the existence of "unknown" identities + * to obscure the fact that there is no verifier for them. + */ + public class SimulatedTlsSrpIdentityManager + : TlsSrpIdentityManager + { + private static readonly byte[] PREFIX_PASSWORD = Strings.ToByteArray("password"); + private static readonly byte[] PREFIX_SALT = Strings.ToByteArray("salt"); + + /** + * Create a {@link SimulatedTlsSRPIdentityManager} that implements the algorithm from RFC 5054 2.5.1.3 + * + * @param group the {@link SRP6GroupParameters} defining the group that SRP is operating in + * @param seedKey the secret "seed key" referred to in RFC 5054 2.5.1.3 + * @return an instance of {@link SimulatedTlsSRPIdentityManager} + */ + public static SimulatedTlsSrpIdentityManager GetRfc5054Default(Srp6GroupParameters group, byte[] seedKey) + { + Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator(); + verifierGenerator.Init(group, TlsUtilities.CreateHash(HashAlgorithm.sha1)); + + HMac mac = new HMac(TlsUtilities.CreateHash(HashAlgorithm.sha1)); + mac.Init(new KeyParameter(seedKey)); + + return new SimulatedTlsSrpIdentityManager(group, verifierGenerator, mac); + } + + protected readonly Srp6GroupParameters mGroup; + protected readonly Srp6VerifierGenerator mVerifierGenerator; + protected readonly IMac mMac; + + public SimulatedTlsSrpIdentityManager(Srp6GroupParameters group, Srp6VerifierGenerator verifierGenerator, IMac mac) + { + this.mGroup = group; + this.mVerifierGenerator = verifierGenerator; + this.mMac = mac; + } + + public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity) + { + mMac.BlockUpdate(PREFIX_SALT, 0, PREFIX_SALT.Length); + mMac.BlockUpdate(identity, 0, identity.Length); + + byte[] salt = new byte[mMac.GetMacSize()]; + mMac.DoFinal(salt, 0); + + mMac.BlockUpdate(PREFIX_PASSWORD, 0, PREFIX_PASSWORD.Length); + mMac.BlockUpdate(identity, 0, identity.Length); + + byte[] password = new byte[mMac.GetMacSize()]; + mMac.DoFinal(password, 0); + + BigInteger verifier = mVerifierGenerator.GenerateVerifier(salt, identity, password); + + return new TlsSrpLoginParameters(mGroup, verifier, salt); + } + } +} diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs index 5d82ed470..df1607751 100644 --- a/crypto/src/crypto/tls/SrpTlsClient.cs +++ b/crypto/src/crypto/tls/SrpTlsClient.cs @@ -6,20 +6,29 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Tls { - public abstract class SrpTlsClient + public class SrpTlsClient : AbstractTlsClient { + protected TlsSrpGroupVerifier mGroupVerifier; + protected byte[] mIdentity; protected byte[] mPassword; public SrpTlsClient(byte[] identity, byte[] password) - : this(new DefaultTlsCipherFactory(), identity, password) + : this(new DefaultTlsCipherFactory(), new DefaultTlsSrpGroupVerifier(), identity, password) { } public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password) + : this(cipherFactory, new DefaultTlsSrpGroupVerifier(), identity, password) + { + } + + public SrpTlsClient(TlsCipherFactory cipherFactory, TlsSrpGroupVerifier groupVerifier, + byte[] identity, byte[] password) : base(cipherFactory) { + this.mGroupVerifier = groupVerifier; this.mIdentity = Arrays.Clone(identity); this.mPassword = Arrays.Clone(password); } @@ -59,22 +68,14 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA); - - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS); + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.SRP: + case KeyExchangeAlgorithm.SRP_DSS: + case KeyExchangeAlgorithm.SRP_RSA: + return CreateSrpKeyExchange(keyExchangeAlgorithm); default: /* @@ -86,38 +87,18 @@ namespace Org.BouncyCastle.Crypto.Tls } } - public override TlsCipher GetCipher() + public override TlsAuthentication GetAuthentication() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } + /* + * Note: This method is not called unless a server certificate is sent, which may be the + * case e.g. for SRP_DSS or SRP_RSA key exchange. + */ + throw new TlsFatalAlert(AlertDescription.internal_error); } protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) { - return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mIdentity, mPassword); + return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mGroupVerifier, mIdentity, mPassword); } } } diff --git a/crypto/src/crypto/tls/SrpTlsServer.cs b/crypto/src/crypto/tls/SrpTlsServer.cs new file mode 100644 index 000000000..f97878380 --- /dev/null +++ b/crypto/src/crypto/tls/SrpTlsServer.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class SrpTlsServer + : AbstractTlsServer + { + protected TlsSrpIdentityManager mSrpIdentityManager; + + protected byte[] mSrpIdentity = null; + protected TlsSrpLoginParameters mLoginParameters = null; + + public SrpTlsServer(TlsSrpIdentityManager srpIdentityManager) + : this(new DefaultTlsCipherFactory(), srpIdentityManager) + { + } + + public SrpTlsServer(TlsCipherFactory cipherFactory, TlsSrpIdentityManager srpIdentityManager) + : base(cipherFactory) + { + this.mSrpIdentityManager = srpIdentityManager; + } + + protected virtual TlsSignerCredentials GetDsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + protected virtual TlsSignerCredentials GetRsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + protected override int[] GetCipherSuites() + { + return new int[] + { + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA + }; + } + + public override void ProcessClientExtensions(IDictionary clientExtensions) + { + base.ProcessClientExtensions(clientExtensions); + + this.mSrpIdentity = TlsSrpUtilities.GetSrpExtension(clientExtensions); + } + + public override int GetSelectedCipherSuite() + { + int cipherSuite = base.GetSelectedCipherSuite(); + + if (TlsSrpUtilities.IsSrpCipherSuite(cipherSuite)) + { + if (mSrpIdentity != null) + { + this.mLoginParameters = mSrpIdentityManager.GetLoginParameters(mSrpIdentity); + } + + if (mLoginParameters == null) + throw new TlsFatalAlert(AlertDescription.unknown_psk_identity); + } + + return cipherSuite; + } + + public override TlsCredentials GetCredentials() + { + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); + + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.SRP: + return null; + + case KeyExchangeAlgorithm.SRP_DSS: + return GetDsaSignerCredentials(); + + case KeyExchangeAlgorithm.SRP_RSA: + return GetRsaSignerCredentials(); + + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public override TlsKeyExchange GetKeyExchange() + { + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); + + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.SRP: + case KeyExchangeAlgorithm.SRP_DSS: + case KeyExchangeAlgorithm.SRP_RSA: + return CreateSrpKeyExchange(keyExchangeAlgorithm); + + default: + /* + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) + { + return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mSrpIdentity, mLoginParameters); + } + } +} diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 19e7d71aa..5b9e81b3f 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mRecordStream.Init(mTlsClientContext); TlsSession sessionToResume = tlsClient.GetSessionToResume(); - if (sessionToResume != null) + if (sessionToResume != null && sessionToResume.IsResumable) { SessionParameters sessionParameters = sessionToResume.ExportSessionParameters(); if (sessionParameters != null) @@ -373,21 +373,17 @@ namespace Org.BouncyCastle.Crypto.Tls /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - byte[] hash; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + Context, signerCredentials); - if (TlsUtilities.IsTlsV12(Context)) + byte[] hash; + if (signatureAndHashAlgorithm == null) { - signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); + hash = mSecurityParameters.SessionHash; } else { - signatureAndHashAlgorithm = null; - hash = mSecurityParameters.SessionHash; + hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); @@ -529,15 +525,7 @@ namespace Org.BouncyCastle.Crypto.Tls */ if (this.mConnectionState == CS_END) { - /* - * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal - * handshake_failure alert. - */ - if (TlsUtilities.IsSsl(Context)) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - - string message = "Renegotiation not supported"; - RaiseWarning(AlertDescription.no_renegotiation, message); + RefuseRenegotiation(); } break; } @@ -636,15 +624,6 @@ namespace Org.BouncyCastle.Crypto.Tls this.mServerExtensions = ReadExtensions(buf); /* - * draft-ietf-tls-session-hash-01 5.2. If a server receives the "extended_master_secret" - * extension, it MUST include the "extended_master_secret" extension in its ServerHello - * message. - */ - bool serverSentExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mServerExtensions); - if (serverSentExtendedMasterSecret != mSecurityParameters.extendedMasterSecret) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - - /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. * @@ -676,15 +655,6 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.unsupported_extension); /* - * draft-ietf-tls-session-hash-01 5.2. Implementation note: if the server decides to - * proceed with resumption, the extension does not have any effect. Requiring the - * extension to be included anyway makes the extension negotiation logic easier, - * because it does not depend on whether resumption is accepted or not. - */ - if (extType == ExtensionType.extended_master_secret) - continue; - - /* * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and Send a server hello containing no * extensions[.] @@ -737,8 +707,6 @@ namespace Org.BouncyCastle.Crypto.Tls sessionClientExtensions = null; sessionServerExtensions = this.mSessionParameters.ReadServerExtensions(); - - this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); } this.mSecurityParameters.cipherSuite = selectedCipherSuite; @@ -758,6 +726,8 @@ namespace Org.BouncyCastle.Crypto.Tls this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC; + this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); + this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); @@ -776,6 +746,13 @@ namespace Org.BouncyCastle.Crypto.Tls AlertDescription.illegal_parameter); } + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ + if (sessionClientExtensions != null) { this.mTlsClient.ProcessServerExtensions(sessionServerExtensions); @@ -832,8 +809,6 @@ namespace Org.BouncyCastle.Crypto.Tls this.mClientExtensions = this.mTlsClient.GetClientExtensions(); - this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); - HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello); TlsUtilities.WriteVersion(client_version, message); diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index b831249a6..211249fcc 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -4,6 +4,7 @@ using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Tls @@ -16,12 +17,10 @@ namespace Org.BouncyCastle.Crypto.Tls protected DHParameters mDHParameters; protected AsymmetricKeyParameter mServerPublicKey; - protected DHPublicKeyParameters mDHAgreeServerPublicKey; protected TlsAgreementCredentials mAgreementCredentials; - protected DHPrivateKeyParameters mDHAgreeClientPrivateKey; - protected DHPrivateKeyParameters mDHAgreeServerPrivateKey; - protected DHPublicKeyParameters mDHAgreeClientPublicKey; + protected DHPrivateKeyParameters mDHAgreePrivateKey; + protected DHPublicKeyParameters mDHAgreePublicKey; public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) : base(keyExchange, supportedSignatureAlgorithms) @@ -81,7 +80,7 @@ namespace Org.BouncyCastle.Crypto.Tls { try { - this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); } catch (InvalidCastException e) { @@ -165,26 +164,40 @@ namespace Org.BouncyCastle.Crypto.Tls */ if (mAgreementCredentials == null) { - this.mDHAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, - mDHAgreeServerPublicKey.Parameters, output); + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, + mDHParameters, output); } } - public override byte[] GeneratePremasterSecret() + public override void ProcessClientCertificate(Certificate clientCertificate) { - if (mAgreementCredentials != null) + // TODO Extract the public key + // TODO If the certificate is 'fixed', take the public key as dhAgreeClientPublicKey + } + + public override void ProcessClientKeyExchange(Stream input) + { + if (mDHAgreePublicKey != null) { - return mAgreementCredentials.GenerateAgreement(mDHAgreeServerPublicKey); + // For dss_fixed_dh and rsa_fixed_dh, the key arrived in the client certificate + return; } - if (mDHAgreeServerPrivateKey != null) + BigInteger Yc = TlsDHUtilities.ReadDHParameter(input); + + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters)); + } + + public override byte[] GeneratePremasterSecret() + { + if (mAgreementCredentials != null) { - return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeClientPublicKey, mDHAgreeServerPrivateKey); + return mAgreementCredentials.GenerateAgreement(mDHAgreePublicKey); } - if (mDHAgreeClientPrivateKey != null) + if (mDHAgreePrivateKey != null) { - return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeServerPublicKey, mDHAgreeClientPrivateKey); + return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey); } throw new TlsFatalAlert(AlertDescription.internal_error); diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index 3c05bb6f0..419d4e442 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -36,30 +36,18 @@ namespace Org.BouncyCastle.Crypto.Tls DigestInputBuffer buf = new DigestInputBuffer(); - this.mDHAgreeServerPrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, this.mDHParameters, buf); /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - IDigest d; - - if (TlsUtilities.IsTlsV12(context)) - { - signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); - } - else - { - signatureAndHashAlgorithm = null; - d = new CombinedHash(); - } - - SecurityParameters securityParameters = context.SecurityParameters; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); + + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); + + SecurityParameters securityParameters = mContext.SecurityParameters; d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); buf.UpdateDigest(d); @@ -76,21 +64,22 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); ServerDHParams dhParams = ServerDHParams.Parse(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); if (!signer.VerifySignature(signed_params.Signature)) throw new TlsFatalAlert(AlertDescription.decrypt_error); - this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); + this.mDHParameters = mDHAgreePublicKey.Parameters; } protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, diff --git a/crypto/src/crypto/tls/TlsDsaSigner.cs b/crypto/src/crypto/tls/TlsDsaSigner.cs index a5ac55974..f0c1e9451 100644 --- a/crypto/src/crypto/tls/TlsDsaSigner.cs +++ b/crypto/src/crypto/tls/TlsDsaSigner.cs @@ -64,8 +64,7 @@ namespace Org.BouncyCastle.Crypto.Tls if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext)) throw new InvalidOperationException(); - // TODO For TLS 1.2+, lift the SHA-1 restriction here - if (algorithm != null && (algorithm.Hash != HashAlgorithm.sha1 || algorithm.Signature != SignatureAlgorithm)) + if (algorithm != null && algorithm.Signature != SignatureAlgorithm) throw new InvalidOperationException(); byte hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.Hash; diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs index 42dc2f2ef..992be4aca 100644 --- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs @@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Tls { if (mAgreementCredentials == null) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, mServerECPointFormats, mECAgreePublicKey.Parameters, output); } } diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs index b99db0c18..b681aada3 100644 --- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs @@ -36,30 +36,18 @@ namespace Org.BouncyCastle.Crypto.Tls { DigestInputBuffer buf = new DigestInputBuffer(); - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, mNamedCurves, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, mNamedCurves, mClientECPointFormats, buf); /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - IDigest d; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); - if (TlsUtilities.IsTlsV12(context)) - { - signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); - } - else - { - signatureAndHashAlgorithm = null; - d = new CombinedHash(); - } + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); buf.UpdateDigest(d); @@ -76,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); @@ -85,7 +73,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] point = TlsUtilities.ReadOpaque8(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs index e938b1685..d0d794d0e 100644 --- a/crypto/src/crypto/tls/TlsEccUtilities.cs +++ b/crypto/src/crypto/tls/TlsEccUtilities.cs @@ -427,7 +427,7 @@ namespace Org.BouncyCastle.Crypto.Tls public static ECPrivateKeyParameters GenerateEphemeralClientKeyExchange(SecureRandom random, byte[] ecPointFormats, ECDomainParameters ecParams, Stream output) { - AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(random, ecParams); + AsymmetricCipherKeyPair kp = GenerateECKeyPair(random, ecParams); ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public; WriteECPoint(ecPointFormats, ecPublicKey.Q, output); diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 09838a717..4ea72cd57 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -99,6 +99,12 @@ namespace Org.BouncyCastle.Crypto.Tls { } + protected virtual void CheckReceivedChangeCipherSpec(bool expected) + { + if (expected != mReceivedChangeCipherSpec) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + protected virtual void CleanupHandshake() { if (this.mExpectedVerifyData != null) @@ -162,6 +168,8 @@ namespace Org.BouncyCastle.Crypto.Tls .SetCompressionAlgorithm(this.mSecurityParameters.compressionAlgorithm) .SetMasterSecret(this.mSecurityParameters.masterSecret) .SetPeerCertificate(this.mPeerCertificate) + .SetPskIdentity(this.mSecurityParameters.pskIdentity) + .SetSrpIdentity(this.mSecurityParameters.srpIdentity) // TODO Consider filtering extensions that aren't relevant to resumed sessions .SetServerExtensions(this.mServerExtensions) .Build(); @@ -259,6 +267,8 @@ namespace Org.BouncyCastle.Crypto.Tls */ byte[] buf = mHandshakeQueue.RemoveData(len, 4); + CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished); + /* * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages * starting at client hello up to, but not including, this finished message. @@ -270,15 +280,20 @@ namespace Org.BouncyCastle.Crypto.Tls break; case HandshakeType.finished: default: - if (type == HandshakeType.finished && this.mExpectedVerifyData == null) + { + TlsContext ctx = Context; + if (type == HandshakeType.finished + && this.mExpectedVerifyData == null + && ctx.SecurityParameters.MasterSecret != null) { - this.mExpectedVerifyData = CreateVerifyData(!Context.IsServer); + this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); } mRecordStream.UpdateHandshakeData(beginning, 0, 4); mRecordStream.UpdateHandshakeData(buf, 0, len); break; } + } /* * Now, parse the message. @@ -612,6 +627,9 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ProcessFinishedMessage(MemoryStream buf) { + if (mExpectedVerifyData == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + byte[] verify_data = TlsUtilities.ReadFully(mExpectedVerifyData.Length, buf); AssertEmpty(buf); @@ -751,6 +769,18 @@ namespace Org.BouncyCastle.Crypto.Tls return maxFragmentLength; } + protected virtual void RefuseRenegotiation() + { + /* + * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal + * handshake_failure alert. + */ + if (TlsUtilities.IsSsl(Context)) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + + RaiseWarning(AlertDescription.no_renegotiation, "Renegotiation not supported"); + } + /** * Make sure the InputStream 'buf' now empty. Fail otherwise. * diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs index a8d0867ef..0af7f7a69 100644 --- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -99,12 +99,12 @@ namespace Org.BouncyCastle.Crypto.Tls if (this.mDHParameters == null) throw new TlsFatalAlert(AlertDescription.internal_error); - this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, this.mDHParameters, buf); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, mNamedCurves, mClientECPointFormats, buf); } @@ -165,6 +165,7 @@ namespace Org.BouncyCastle.Crypto.Tls ServerDHParams serverDHParams = ServerDHParams.Parse(input); this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey); + this.mDHParameters = mDHAgreePublicKey.Parameters; } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { @@ -208,21 +209,21 @@ namespace Org.BouncyCastle.Crypto.Tls TlsUtilities.WriteOpaque16(psk_identity, output); - context.SecurityParameters.pskIdentity = psk_identity; + mContext.SecurityParameters.pskIdentity = psk_identity; if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, - mDHAgreePublicKey.Parameters, output); + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, + mDHParameters, output); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, mServerECPointFormats, mECAgreePublicKey.Parameters, output); } else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { - this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, + this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(mContext, this.mRsaServerPublicKey, output); } } @@ -235,7 +236,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (mPsk == null) throw new TlsFatalAlert(AlertDescription.unknown_psk_identity); - context.SecurityParameters.pskIdentity = psk_identity; + mContext.SecurityParameters.pskIdentity = psk_identity; if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { @@ -255,7 +256,7 @@ namespace Org.BouncyCastle.Crypto.Tls else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { byte[] encryptedPreMasterSecret; - if (TlsUtilities.IsSsl(context)) + if (TlsUtilities.IsSsl(mContext)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.ReadAll(input); diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs index 3a0a49154..b02d56486 100644 --- a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs @@ -16,13 +16,13 @@ namespace Org.BouncyCastle.Crypto.Tls public class TlsRsaKeyExchange : AbstractTlsKeyExchange { - protected AsymmetricKeyParameter serverPublicKey = null; + protected AsymmetricKeyParameter mServerPublicKey = null; - protected RsaKeyParameters rsaServerPublicKey = null; + protected RsaKeyParameters mRsaServerPublicKey = null; - protected TlsEncryptionCredentials serverCredentials = null; + protected TlsEncryptionCredentials mServerCredentials = null; - protected byte[] premasterSecret; + protected byte[] mPremasterSecret; public TlsRsaKeyExchange(IList supportedSignatureAlgorithms) : base(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms) @@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Tls ProcessServerCertificate(serverCredentials.Certificate); - this.serverCredentials = (TlsEncryptionCredentials)serverCredentials; + this.mServerCredentials = (TlsEncryptionCredentials)serverCredentials; } public override void ProcessServerCertificate(Certificate serverCertificate) @@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { @@ -62,10 +62,10 @@ namespace Org.BouncyCastle.Crypto.Tls } // Sanity check the PublicKeyFactory - if (this.serverPublicKey.IsPrivate) + if (this.mServerPublicKey.IsPrivate) throw new TlsFatalAlert(AlertDescription.internal_error); - this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey); + this.mRsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.mServerPublicKey); TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); @@ -97,13 +97,13 @@ namespace Org.BouncyCastle.Crypto.Tls public override void GenerateClientKeyExchange(Stream output) { - this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, rsaServerPublicKey, output); + this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(mContext, mRsaServerPublicKey, output); } public override void ProcessClientKeyExchange(Stream input) { byte[] encryptedPreMasterSecret; - if (TlsUtilities.IsSsl(context)) + if (TlsUtilities.IsSsl(mContext)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.ReadAll(input); @@ -113,16 +113,16 @@ namespace Org.BouncyCastle.Crypto.Tls encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input); } - this.premasterSecret = serverCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); + this.mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); } public override byte[] GeneratePremasterSecret() { - if (this.premasterSecret == null) + if (this.mPremasterSecret == null) throw new TlsFatalAlert(AlertDescription.internal_error); - byte[] tmp = this.premasterSecret; - this.premasterSecret = null; + byte[] tmp = this.mPremasterSecret; + this.mPremasterSecret = null; return tmp; } diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index b1fb830b6..fd6808382 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -179,6 +179,11 @@ namespace Org.BouncyCastle.Crypto.Tls break; } + case CS_END: + { + RefuseRenegotiation(); + break; + } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } @@ -496,6 +501,12 @@ namespace Org.BouncyCastle.Crypto.Tls */ this.mClientExtensions = ReadExtensions(buf); + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); ContextAdmin.SetClientVersion(client_version); diff --git a/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs b/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs new file mode 100644 index 000000000..185f2f50a --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs @@ -0,0 +1,17 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSrpGroupVerifier + { + /** + * Check whether the given SRP group parameters are acceptable for use. + * + * @param group the {@link SRP6GroupParameters} to check + * @return true if (and only if) the specified group parameters are acceptable + */ + bool Accept(Srp6GroupParameters group); + } +} diff --git a/crypto/src/crypto/tls/TlsSrpIdentityManager.cs b/crypto/src/crypto/tls/TlsSrpIdentityManager.cs new file mode 100644 index 000000000..080a0dc16 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpIdentityManager.cs @@ -0,0 +1,21 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSrpIdentityManager + { + /** + * Lookup the {@link TlsSRPLoginParameters} corresponding to the specified identity. + * + * NOTE: To avoid "identity probing", unknown identities SHOULD be handled as recommended in RFC + * 5054 2.5.1.3. {@link SimulatedTlsSRPIdentityManager} is provided for this purpose. + * + * @param identity + * the SRP identity sent by the connecting client + * @return the {@link TlsSRPLoginParameters} for the specified identity, or else 'simulated' + * parameters if the identity is not recognized. A null value is also allowed, but not + * recommended. + */ + TlsSrpLoginParameters GetLoginParameters(byte[] identity); + } +} diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs index f42f7456d..ce8e4834a 100644 --- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs @@ -16,36 +16,64 @@ namespace Org.BouncyCastle.Crypto.Tls public class TlsSrpKeyExchange : AbstractTlsKeyExchange { + protected static TlsSigner CreateSigner(int keyExchange) + { + switch (keyExchange) + { + case KeyExchangeAlgorithm.SRP: + return null; + case KeyExchangeAlgorithm.SRP_RSA: + return new TlsRsaSigner(); + case KeyExchangeAlgorithm.SRP_DSS: + return new TlsDssSigner(); + default: + throw new ArgumentException("unsupported key exchange algorithm"); + } + } + protected TlsSigner mTlsSigner; + protected TlsSrpGroupVerifier mGroupVerifier; protected byte[] mIdentity; protected byte[] mPassword; protected AsymmetricKeyParameter mServerPublicKey = null; - protected byte[] mS = null; - protected BigInteger mB = null; - protected Srp6Client mSrpClient = new Srp6Client(); + protected Srp6GroupParameters mSrpGroup = null; + protected Srp6Client mSrpClient = null; + protected Srp6Server mSrpServer = null; + protected BigInteger mSrpPeerCredentials = null; + protected BigInteger mSrpVerifier = null; + protected byte[] mSrpSalt = null; + + protected TlsSignerCredentials mServerCredentials = null; + [Obsolete("Use constructor taking an explicit 'groupVerifier' argument")] public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, byte[] password) - : base(keyExchange, supportedSignatureAlgorithms) + : this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsSrpGroupVerifier(), identity, password) { - switch (keyExchange) - { - case KeyExchangeAlgorithm.SRP: - this.mTlsSigner = null; - break; - case KeyExchangeAlgorithm.SRP_RSA: - this.mTlsSigner = new TlsRsaSigner(); - break; - case KeyExchangeAlgorithm.SRP_DSS: - this.mTlsSigner = new TlsDssSigner(); - break; - default: - throw new InvalidOperationException("unsupported key exchange algorithm"); - } + } + public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsSrpGroupVerifier groupVerifier, + byte[] identity, byte[] password) + : base(keyExchange, supportedSignatureAlgorithms) + { + this.mTlsSigner = CreateSigner(keyExchange); + this.mGroupVerifier = groupVerifier; this.mIdentity = identity; this.mPassword = password; + this.mSrpClient = new Srp6Client(); + } + + public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, + TlsSrpLoginParameters loginParameters) + : base(keyExchange, supportedSignatureAlgorithms) + { + this.mTlsSigner = CreateSigner(keyExchange); + this.mIdentity = identity; + this.mSrpServer = new Srp6Server(); + this.mSrpGroup = loginParameters.Group; + this.mSrpVerifier = loginParameters.Verifier; + this.mSrpSalt = loginParameters.Salt; } public override void Init(TlsContext context) @@ -91,14 +119,62 @@ namespace Org.BouncyCastle.Crypto.Tls base.ProcessServerCertificate(serverCertificate); } + public override void ProcessServerCredentials(TlsCredentials serverCredentials) + { + if ((mKeyExchange == KeyExchangeAlgorithm.SRP) || !(serverCredentials is TlsSignerCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + ProcessServerCertificate(serverCredentials.Certificate); + + this.mServerCredentials = (TlsSignerCredentials)serverCredentials; + } + public override bool RequiresServerKeyExchange { get { return true; } } + public override byte[] GenerateServerKeyExchange() + { + mSrpServer.Init(mSrpGroup, mSrpVerifier, TlsUtilities.CreateHash(HashAlgorithm.sha1), mContext.SecureRandom); + BigInteger B = mSrpServer.GenerateServerCredentials(); + + ServerSrpParams srpParams = new ServerSrpParams(mSrpGroup.N, mSrpGroup.G, mSrpSalt, B); + + DigestInputBuffer buf = new DigestInputBuffer(); + + srpParams.Encode(buf); + + if (mServerCredentials != null) + { + /* + * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 + */ + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); + + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); + + SecurityParameters securityParameters = mContext.SecurityParameters; + d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + buf.UpdateDigest(d); + + byte[] hash = new byte[d.GetDigestSize()]; + d.DoFinal(hash, 0); + + byte[] signature = mServerCredentials.GenerateCertificateSignature(hash); + + DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature); + signed_params.Encode(buf); + } + + return buf.ToArray(); + } + public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = null; Stream teeIn = input; @@ -109,14 +185,11 @@ namespace Org.BouncyCastle.Crypto.Tls teeIn = new TeeInputStream(input, buf); } - byte[] NBytes = TlsUtilities.ReadOpaque16(teeIn); - byte[] gBytes = TlsUtilities.ReadOpaque16(teeIn); - byte[] sBytes = TlsUtilities.ReadOpaque8(teeIn); - byte[] BBytes = TlsUtilities.ReadOpaque16(teeIn); + ServerSrpParams srpParams = ServerSrpParams.Parse(teeIn); if (buf != null) { - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); @@ -124,13 +197,12 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.decrypt_error); } - BigInteger N = new BigInteger(1, NBytes); - BigInteger g = new BigInteger(1, gBytes); + this.mSrpGroup = new Srp6GroupParameters(srpParams.N, srpParams.G); - // TODO Validate group parameters (see RFC 5054) - // throw new TlsFatalAlert(AlertDescription.insufficient_security); + if (!mGroupVerifier.Accept(mSrpGroup)) + throw new TlsFatalAlert(AlertDescription.insufficient_security); - this.mS = sBytes; + this.mSrpSalt = srpParams.S; /* * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if @@ -138,14 +210,14 @@ namespace Org.BouncyCastle.Crypto.Tls */ try { - this.mB = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes)); + this.mSrpPeerCredentials = Srp6Utilities.ValidatePublicValue(mSrpGroup.N, srpParams.B); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } - this.mSrpClient.Init(N, g, TlsUtilities.CreateHash(HashAlgorithm.sha1), context.SecureRandom); + this.mSrpClient.Init(mSrpGroup, TlsUtilities.CreateHash(HashAlgorithm.sha1), mContext.SecureRandom); } public override void ValidateCertificateRequest(CertificateRequest certificateRequest) @@ -160,16 +232,40 @@ namespace Org.BouncyCastle.Crypto.Tls public override void GenerateClientKeyExchange(Stream output) { - BigInteger A = mSrpClient.GenerateClientCredentials(mS, this.mIdentity, this.mPassword); - TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(A), output); + BigInteger A = mSrpClient.GenerateClientCredentials(mSrpSalt, mIdentity, mPassword); + TlsSrpUtilities.WriteSrpParameter(A, output); + + mContext.SecurityParameters.srpIdentity = Arrays.Clone(mIdentity); + } + + public override void ProcessClientKeyExchange(Stream input) + { + /* + * RFC 5054 2.5.4: The server MUST abort the handshake with an "illegal_parameter" alert if + * A % N = 0. + */ + try + { + this.mSrpPeerCredentials = Srp6Utilities.ValidatePublicValue(mSrpGroup.N, TlsSrpUtilities.ReadSrpParameter(input)); + } + catch (CryptoException e) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); + } + + mContext.SecurityParameters.srpIdentity = Arrays.Clone(mIdentity); } public override byte[] GeneratePremasterSecret() { try { + BigInteger S = mSrpServer != null + ? mSrpServer.CalculateSecret(mSrpPeerCredentials) + : mSrpClient.CalculateSecret(mSrpPeerCredentials); + // TODO Check if this needs to be a fixed size - return BigIntegers.AsUnsignedByteArray(mSrpClient.CalculateSecret(mB)); + return BigIntegers.AsUnsignedByteArray(S); } catch (CryptoException e) { diff --git a/crypto/src/crypto/tls/TlsSrpLoginParameters.cs b/crypto/src/crypto/tls/TlsSrpLoginParameters.cs new file mode 100644 index 000000000..5ae4641f6 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpLoginParameters.cs @@ -0,0 +1,36 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsSrpLoginParameters + { + protected readonly Srp6GroupParameters mGroup; + protected readonly BigInteger mVerifier; + protected readonly byte[] mSalt; + + public TlsSrpLoginParameters(Srp6GroupParameters group, BigInteger verifier, byte[] salt) + { + this.mGroup = group; + this.mVerifier = verifier; + this.mSalt = salt; + } + + public virtual Srp6GroupParameters Group + { + get { return mGroup; } + } + + public virtual byte[] Salt + { + get { return mSalt; } + } + + public virtual BigInteger Verifier + { + get { return mVerifier; } + } + } +} diff --git a/crypto/src/crypto/tls/TlsSrpUtilities.cs b/crypto/src/crypto/tls/TlsSrpUtilities.cs index bbb6ac280..873189dc6 100644 --- a/crypto/src/crypto/tls/TlsSrpUtilities.cs +++ b/crypto/src/crypto/tls/TlsSrpUtilities.cs @@ -2,6 +2,9 @@ using System.Collections; using System.IO; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + namespace Org.BouncyCastle.Crypto.Tls { public abstract class TlsSrpUtilities @@ -37,5 +40,35 @@ namespace Org.BouncyCastle.Crypto.Tls return identity; } + + public static BigInteger ReadSrpParameter(Stream input) + { + return new BigInteger(1, TlsUtilities.ReadOpaque16(input)); + } + + public static void WriteSrpParameter(BigInteger x, Stream output) + { + TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output); + } + + public static bool IsSrpCipherSuite(int cipherSuite) + { + switch (cipherSuite) + { + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return true; + + default: + return false; + } + } } } diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index 485ecb760..a8c8a2b28 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -21,6 +21,9 @@ namespace Org.BouncyCastle.Crypto.Tls public abstract class TlsUtilities { public static readonly byte[] EmptyBytes = new byte[0]; + public static readonly short[] EmptyShorts = new short[0]; + public static readonly int[] EmptyInts = new int[0]; + public static readonly long[] EmptyLongs = new long[0]; public static void CheckUint8(int i) { @@ -589,6 +592,37 @@ namespace Org.BouncyCastle.Crypto.Tls return extensions == null ? null : (byte[])extensions[extensionType]; } + public static IList GetDefaultSupportedSignatureAlgorithms() + { + byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha1, HashAlgorithm.sha224, HashAlgorithm.sha256, + HashAlgorithm.sha384, HashAlgorithm.sha512 }; + byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa, SignatureAlgorithm.dsa, + SignatureAlgorithm.ecdsa }; + + IList result = Platform.CreateArrayList(); + for (int i = 0; i < signatureAlgorithms.Length; ++i) + { + for (int j = 0; j < hashAlgorithms.Length; ++j) + { + result.Add(new SignatureAndHashAlgorithm(hashAlgorithms[j], signatureAlgorithms[i])); + } + } + return result; + } + + public static SignatureAndHashAlgorithm GetSignatureAndHashAlgorithm(TlsContext context, + TlsSignerCredentials signerCredentials) + { + SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; + if (IsTlsV12(context)) + { + signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; + if (signatureAndHashAlgorithm == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + } + return signatureAndHashAlgorithm; + } + public static bool HasExpectedEmptyExtensionData(IDictionary extensions, int extensionType, byte alertDescription) { @@ -941,6 +975,13 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public static IDigest CreateHash(SignatureAndHashAlgorithm signatureAndHashAlgorithm) + { + return signatureAndHashAlgorithm == null + ? new CombinedHash() + : CreateHash(signatureAndHashAlgorithm.Hash); + } + public static IDigest CloneHash(byte hashAlgorithm, IDigest hash) { switch (hashAlgorithm) @@ -1490,6 +1531,528 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public static int GetKeyExchangeAlgorithm(int ciphersuite) + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DH_DSS; + + case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DH_RSA; + + case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DHE_DSS; + + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + return KeyExchangeAlgorithm.DHE_PSK; + + case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DHE_RSA; + + case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return KeyExchangeAlgorithm.ECDH_ECDSA; + + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + return KeyExchangeAlgorithm.ECDH_RSA; + + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_ECDSA; + + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_PSK; + + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_RSA; + + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.PSK; + + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.RSA; + + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.RSA_PSK; + + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP; + + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP_DSS; + + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP_RSA; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public static int GetMacAlgorithm(int ciphersuite) + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return MacAlgorithm.cls_null; + + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + return MacAlgorithm.hmac_md5; + + case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return MacAlgorithm.hmac_sha1; + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + return MacAlgorithm.hmac_sha256; + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + return MacAlgorithm.hmac_sha384; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + public static ProtocolVersion GetMinimumVersion(int ciphersuite) { switch (ciphersuite) diff --git a/crypto/src/pkix/PkixParameters.cs b/crypto/src/pkix/PkixParameters.cs index 6df1b646f..47d3b5e37 100644 --- a/crypto/src/pkix/PkixParameters.cs +++ b/crypto/src/pkix/PkixParameters.cs @@ -745,7 +745,7 @@ namespace Org.BouncyCastle.Pkix } /** - * Returns the neccessary attributes which must be contained in an attribute + * Returns the necessary attributes which must be contained in an attribute * certificate. * <p> * The returned <code>ISet</code> is immutable and contains @@ -760,7 +760,7 @@ namespace Org.BouncyCastle.Pkix } /** - * Sets the neccessary which must be contained in an attribute certificate. + * Sets the necessary which must be contained in an attribute certificate. * <p> * The <code>ISet</code> must contain <code>String</code>s with the * OIDs. diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index c1aea50d6..bd1515147 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -534,6 +534,26 @@ namespace Org.BouncyCastle.Security return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true); } + if (mechanism.EndsWith("/X9.31")) + { + string x931 = mechanism.Substring(0, mechanism.Length - "/X9.31".Length); + int withPos = x931.IndexOf("WITH"); + if (withPos > 0) + { + int endPos = withPos + "WITH".Length; + + string digestName = x931.Substring(0, withPos); + IDigest digest = DigestUtilities.GetDigest(digestName); + + string cipherName = x931.Substring(endPos, x931.Length - endPos); + if (cipherName.Equals("RSA")) + { + IAsymmetricBlockCipher cipher = new RsaBlindedEngine(); + return new X931Signer(cipher, digest); + } + } + } + throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); } diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 59cff41e1..3fd7154d9 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -256,13 +256,37 @@ <Compile Include="src\crypto\test\VMPCMacTest.cs" /> <Compile Include="src\crypto\test\VMPCTest.cs" /> <Compile Include="src\crypto\test\WhirlpoolDigestTest.cs" /> + <Compile Include="src\crypto\test\X931SignerTest.cs" /> <Compile Include="src\crypto\test\XSalsa20Test.cs" /> <Compile Include="src\crypto\test\XTEATest.cs" /> + <Compile Include="src\crypto\tls\test\DtlsProtocolTest.cs" /> + <Compile Include="src\crypto\tls\test\DtlsTestCase.cs" /> + <Compile Include="src\crypto\tls\test\DtlsTestSuite.cs" /> + <Compile Include="src\crypto\tls\test\LoggingDatagramTransport.cs" /> + <Compile Include="src\crypto\tls\test\MockDatagramAssociation.cs" /> + <Compile Include="src\crypto\tls\test\MockDtlsClient.cs" /> + <Compile Include="src\crypto\tls\test\MockDtlsServer.cs" /> + <Compile Include="src\crypto\tls\test\MockPskTlsClient.cs" /> + <Compile Include="src\crypto\tls\test\MockPskTlsServer.cs" /> + <Compile Include="src\crypto\tls\test\MockSrpTlsClient.cs" /> + <Compile Include="src\crypto\tls\test\MockSrpTlsServer.cs" /> <Compile Include="src\crypto\tls\test\MockTlsClient.cs" /> <Compile Include="src\crypto\tls\test\MockTlsServer.cs" /> + <Compile Include="src\crypto\tls\test\NetworkStream.cs" /> + <Compile Include="src\crypto\tls\test\PipedStream.cs" /> + <Compile Include="src\crypto\tls\test\PskTlsClientTest.cs" /> <Compile Include="src\crypto\tls\test\TlsClientTest.cs" /> + <Compile Include="src\crypto\tls\test\TlsProtocolTest.cs" /> + <Compile Include="src\crypto\tls\test\TlsPskProtocolTest.cs" /> <Compile Include="src\crypto\tls\test\TlsServerTest.cs" /> + <Compile Include="src\crypto\tls\test\TlsSrpProtocolTest.cs" /> + <Compile Include="src\crypto\tls\test\TlsTestCase.cs" /> + <Compile Include="src\crypto\tls\test\TlsTestClientImpl.cs" /> + <Compile Include="src\crypto\tls\test\TlsTestConfig.cs" /> + <Compile Include="src\crypto\tls\test\TlsTestServerImpl.cs" /> + <Compile Include="src\crypto\tls\test\TlsTestSuite.cs" /> <Compile Include="src\crypto\tls\test\TlsTestUtilities.cs" /> + <Compile Include="src\crypto\tls\test\UnreliableDatagramTransport.cs" /> <Compile Include="src\math\ec\test\AllTests.cs" /> <Compile Include="src\math\ec\test\ECAlgorithmsTest.cs" /> <Compile Include="src\math\ec\test\ECPointPerformanceTest.cs" /> @@ -1199,9 +1223,17 @@ <EmbeddedResource Include="data\tls\server.tmpl" /> <EmbeddedResource Include="data\tls\x509-ca-key.pem" /> <EmbeddedResource Include="data\tls\x509-ca.pem" /> + <EmbeddedResource Include="data\tls\x509-client-dsa.pem" /> + <EmbeddedResource Include="data\tls\x509-client-ecdsa.pem" /> <EmbeddedResource Include="data\tls\x509-client-key.pem" /> + <EmbeddedResource Include="data\tls\x509-client-key-dsa.pem" /> + <EmbeddedResource Include="data\tls\x509-client-key-ecdsa.pem" /> <EmbeddedResource Include="data\tls\x509-client.pem" /> + <EmbeddedResource Include="data\tls\x509-server-dsa.pem" /> + <EmbeddedResource Include="data\tls\x509-server-ecdsa.pem" /> <EmbeddedResource Include="data\tls\x509-server-key.pem" /> + <EmbeddedResource Include="data\tls\x509-server-key-dsa.pem" /> + <EmbeddedResource Include="data\tls\x509-server-key-ecdsa.pem" /> <EmbeddedResource Include="data\tls\x509-server.pem" /> <EmbeddedResource Include="data\tls\keystores\client_store.dsa" /> <EmbeddedResource Include="data\tls\keystores\client_store.rsa" /> diff --git a/crypto/test/data/tls/x509-client-dsa.pem b/crypto/test/data/tls/x509-client-dsa.pem new file mode 100644 index 000000000..91d9e4415 --- /dev/null +++ b/crypto/test/data/tls/x509-client-dsa.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFmzCCBFOgAwIBAgIMVOBtHi6d3lDIPyoMMA0GCSqGSIb3DQEBCwUAMCMxITAf +BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5NTU0 +MloYDzIwMzUwMjEwMDk1NTQyWjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz +dCBDbGllbnQwggNHMIICOgYHKoZIzjgEATCCAi0CggEBAPvZZVsYbqUzF5Aq5JCU +GJtg9+Hgrab/2F8vnEKsYKWtKFY4BCalIbhbZ/e4VPAEV1SlV/GgmtkPVrOutThq +03j/eo98t82vismks6SMupNoyOiPqDZ+HyNEZFIQV9Ur/1D/tPBQGrD7Fbh5JOmK +QPCoo46t9Xclfm+8u8bUIhFQV4LIkug5YBm2J8wy5FeaRYno1+4Hp543oD6SkOtF +aJCp05nfiNRtaZy/LXr22UnSggG9M/zug+u3Bi2R70TI5FJq7TwYHfAlbesbLBjH +QHvE95WlFxK1YovmziBLfew5RClZ3kgj7f3SL/3WeRy2ittQaObwV27ZNj4enYAD +qkkCIQDsN/jM9mS5UDmPNRR6Wby2jvJQbHdm6yMqlFiIXVAECQKCAQEAzVrnDdM6 +kPTVALWJNYC279xIEMETimJGP39o3YXMJFlyoEzFYamJPneYlYpY4jGfuetC+jFn +HouDivtjdf/vAc+og4jaro4NcaDCjzPZBTQuvb0cFhlSbVZsit1IMv/sztJUdPcd +QKnGP+NfiChBDh8LLskvuVefEia0Ix/xwdK764zVn9oxiP5E2sKMMYnnFoVykbKU +W43sOONe+P2zOF3VTIOUngszcNDKJsXrFKZ+MtE9FvKduaXBmd0y9Pat7jFCodry +127mBeIZOKb9h3YMZCf7tQBFpX6o8JX4Ltw9hVRIsspgarli3K18WmOR+6pvAzJx +IxxiYDbo1PHMAgOCAQUAAoIBAGPk3p3hPR51sTwf2LwDrZ5Fh9tLzFoSh6ojjiR/ +FJsqwbrEEPYi4vozJOBao17qfZayMArcq7QB5eUzBaeeggvyYgYPUIUh8kBZqeLp +WtWYBXwDqNQiRSAqX0nl35SZEnyyou4kidHFW4SWSbTQw9pkM1gtP2Q7pkxabdjt +fQTJsilslKFhoV/zWYsa72YJ1GilnDLwPanaBDdpnX84W+TDS2Gy2wb0o15etOTU +Ly9EoHisZZfdwdIoAd0pJbjSHAJnudB+skL2VfPwfwxQDOTV7gh6XIe5h5bLKR3x +ruLjNx1ppcTkjKmUruTp7V+/sH9EAS8B9epiNDGwL0s8gX6jdjB0MAwGA1UdEwEB +/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDwYDVR0PAQH/BAUDAweAADAdBgNV +HQ4EFgQUGvXFed+UN0C5+YrVvcR+7cn9U6swHwYDVR0jBBgwFoAU9mOvr6Pi7+4O +5bKxRihqeCkyHukwDQYJKoZIhvcNAQELBQADggExAChl15lXRB43Oh+qIeibolYt +OBCHlUQcQcFzqK556TKNQfhWoRv1ovxbxgPokogfnLfxKdmHrb4E+aF0syxNpXGn +gBY2G7uyuKjoJnMNsxdTiS6jzps+LlgwHMYsFac0vcJATVz1U8hoR90B4pwkNkXv +ErVXj4WvHqB5a4gsqPpAslZvhxOgWLvjA+1V4HohspnMVTup3zG6frdmwLWZ+FPI +LyrEaUaWiilFl83RWuVlExhxGyfLF8u/06OJYHCUNtHT4UQavFzQMz5UwruGor7x +n8QEE84SXaQxIyWO5T2vnlxZ0+fw/0GXyJS0F0WvJ5WkK+s+y6nXZ8Hq2fDecDWn +1nw44LpnwGb//010RdtOeAHAQmGuuEf8rf1Xiw990hAYvTzM4cT9/l22vQPR3rg= +-----END CERTIFICATE----- diff --git a/crypto/test/data/tls/x509-client-ecdsa.pem b/crypto/test/data/tls/x509-client-ecdsa.pem new file mode 100644 index 000000000..fd8bc845b --- /dev/null +++ b/crypto/test/data/tls/x509-client-ecdsa.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqzCCAWOgAwIBAgIMVOBhzQE9XhiRAUXpMA0GCSqGSIb3DQEBCwUAMCMxITAf +BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5MDcy +NVoYDzIwMzUwMjEwMDkwNzI1WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz +dCBDbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASWdahP6F9xwnD6eABg +2AwifyDDCw5jy5hGe+Lnvyjok/zdkw2n8lWCFdhInFC7mRcGS7aduF7dykv9C9oU +mY17o3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA8GA1Ud +DwEB/wQFAwMHgAAwHQYDVR0OBBYEFAg1z6i+u89U0RQrH9ApFWIklZrpMB8GA1Ud +IwQYMBaAFPZjr6+j4u/uDuWysUYoangpMh7pMA0GCSqGSIb3DQEBCwUAA4IBMQCL +RJIeoOlVOcseShihLd3OU7NU3tGeLDnEcwPOAPYsDN1c7V/zROTD/0W0nhSVdRfB +AyxjjDjq3J/MTf1DrouEynoAU8SZL5OnxbceX74U2WsSaJU0PAaw9zTOaKoOuTET +EVs/OMx00XXhZcu+lPFAKT3YNJKO1Rm7Sy4vnY4jnsuRsk9+D6E3CmDSnKQC/g90 +/0djrDTYpL9Lyd5zzekZPpzX7YgNfmq2X04521+3ahfq4bBMC8GRdAuon2h2FwFX ++aH9cjHHDgxPt5pHkg3Uk+Cl6KhVb2ilS0uYd4XaMPXOUOUOxRpmQ3/7YhNgyyaL +IOP+fWkbOiFbUTDaOcbBo9y8gvy7+sXuGF5k4nHXNs46Ew1gThQPFtZjqgdiEi+A +5hYd5P2j0V9L9LprzM79 +-----END CERTIFICATE----- diff --git a/crypto/test/data/tls/x509-client-key-dsa.pem b/crypto/test/data/tls/x509-client-key-dsa.pem new file mode 100644 index 000000000..e4e9632c7 --- /dev/null +++ b/crypto/test/data/tls/x509-client-key-dsa.pem @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQD72WVbGG6lMxeQKuSQlBibYPfh +4K2m/9hfL5xCrGClrShWOAQmpSG4W2f3uFTwBFdUpVfxoJrZD1azrrU4atN4/3qP +fLfNr4rJpLOkjLqTaMjoj6g2fh8jRGRSEFfVK/9Q/7TwUBqw+xW4eSTpikDwqKOO +rfV3JX5vvLvG1CIRUFeCyJLoOWAZtifMMuRXmkWJ6NfuB6eeN6A+kpDrRWiQqdOZ +34jUbWmcvy169tlJ0oIBvTP87oPrtwYtke9EyORSau08GB3wJW3rGywYx0B7xPeV +pRcStWKL5s4gS33sOUQpWd5II+390i/91nkctorbUGjm8Fdu2TY+Hp2AA6pJAiEA +7Df4zPZkuVA5jzUUelm8to7yUGx3ZusjKpRYiF1QBAkCggEBAM1a5w3TOpD01QC1 +iTWAtu/cSBDBE4piRj9/aN2FzCRZcqBMxWGpiT53mJWKWOIxn7nrQvoxZx6Lg4r7 +Y3X/7wHPqIOI2q6ODXGgwo8z2QU0Lr29HBYZUm1WbIrdSDL/7M7SVHT3HUCpxj/j +X4goQQ4fCy7JL7lXnxImtCMf8cHSu+uM1Z/aMYj+RNrCjDGJ5xaFcpGylFuN7Djj +Xvj9szhd1UyDlJ4LM3DQyibF6xSmfjLRPRbynbmlwZndMvT2re4xQqHa8tdu5gXi +GTim/Yd2DGQn+7UARaV+qPCV+C7cPYVUSLLKYGq5YtytfFpjkfuqbwMycSMcYmA2 +6NTxzAIEIgIgC6eNrpVR96umhuvIbLz6sy2YwlGFpkK+LLJOL2GmQ4g= +-----END PRIVATE KEY----- diff --git a/crypto/test/data/tls/x509-client-key-ecdsa.pem b/crypto/test/data/tls/x509-client-key-ecdsa.pem new file mode 100644 index 000000000..89232e303 --- /dev/null +++ b/crypto/test/data/tls/x509-client-key-ecdsa.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGUAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHoweAIBAQQhANLHM3ugk0ZTEYNx +uKn3ytAv71M61ChZAjWdC9nW1U7zoAoGCCqGSM49AwEHoUQDQgAElnWoT+hfccJw ++ngAYNgMIn8gwwsOY8uYRnvi578o6JP83ZMNp/JVghXYSJxQu5kXBku2nbhe3cpL +/QvaFJmNew== +-----END PRIVATE KEY----- diff --git a/crypto/test/data/tls/x509-server-dsa.pem b/crypto/test/data/tls/x509-server-dsa.pem new file mode 100644 index 000000000..1078dbcbc --- /dev/null +++ b/crypto/test/data/tls/x509-server-dsa.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFmjCCBFKgAwIBAgIMVOBtTzLTG8B9QCZvMA0GCSqGSIb3DQEBCwUAMCMxITAf +BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5NTYz +MVoYDzIwMzUwMjEwMDk1NjMxWjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz +dCBTZXJ2ZXIwggNGMIICOQYHKoZIzjgEATCCAiwCggEBANblGd/puZYWDvmSMCx0 +AnQQcbmjUhB3MN68/fhkKFwBPU1QhJRiSEVDG1bnsUP55EQKDs1vpiSXgy89P3aT +cagq0M+urrN97MPeKoBF8sk4o6axruspxD41OyKhW68Nnk54E+3mEPABS4yYpsuE +hFfaZhOUXdA9aUFWnPN7oo7QlI+F7la8bluz8G8j81aMsEwjBdEKg+2Mp1+33NVa +IWEegnunVEkb0vJd/WwLZYj+OgmK4fn/qqIdRXIbjeNUvpAtklE5NrARswI0RXuX +yWxPfBrQSbWk3DQvbuWbEeSUrhYY67YbpPGA5Rng8awpxdXhvzsSmT9c6BlrLfF6 +IN0CIQDWtWHaMmlAVZW9p0Dmsj70sNHJxOYWlqjCEzF7axV3fwKCAQAgFZojuX/n +leri2E9C6b8cQTof46JZeAeG2Svk8I91cnIv0iXTHfyzWLWDAYnfeuMmt+nMA6/A +1K94YI1duc3iahLa5U3fOACWJdFtL/CAFVyNth7lDeHbWTFjM5HgA76pzmAfvFtZ +pcJp1AUZZB+3coKSr6ZrMagt1HhoefGyo7JkPpsxGiFEKB79rXkFi0AEsSnbduFE +czrg8DBdXm9//yUQnTw2pphcwLZt6t6Eq3Wrpu364Dn+hJegpLfA6uOhtRJw+7xv +5jkBbvIxp1PLZEn16qmPKMs3Im4QUa2u5F0nLYUGHi01i5OSn0UWnom8EcDis/0Q +CrkyBaiMaNkkA4IBBQACggEAQob2cpVeV4uwnX8XutQLro6BkEFMhpaQLUzbI97J +Nh1OUMnW3K2KCCdhygTYfH3j2S8ys4W30zutHyhiApUdYUZKxNXXu4+NPoLwCyAE +rrN5db5QgVx8aOG/Gfmp4POMpeGKioXgOsSWpUB0uyedgT4sszq/vuZc455HiS07 +LTlaJjeIQFtKdVYXGKNWqP/WLRnjSY9IXA5hxBXvlNAVGS/M4TvBWURUJF33THTq +ioS0DYJ9Ikyn2fsgLgSRRyNU7Y5945yUhY5p6E6Njk0ZBB+2YUtB6TQhPvEY/G48 +xwH4hTZppmmfu2UIE+YlsWv10buTOT+mxU/5LjDI6RQM2KN2MHQwDAYDVR0TAQH/ +BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB4AAMB0GA1Ud +DgQWBBS8bllTQWk2fm2R6XSZEIoRTd6/+zAfBgNVHSMEGDAWgBT2Y6+vo+Lv7g7l +srFGKGp4KTIe6TANBgkqhkiG9w0BAQsFAAOCATEAptRUkWUT+MdvD7v733B6Gad+ +wO0G9n7Au7ZsS6NVPxc4DrozFyyhPU1uOl1koUyYQP52V1lkm1+rS7tQXm4+32iz +bLwDCYn4LD1IZQ2hTNY/g/U0oA1dp3ZOJeydZDZ9Bm1NWYeWqfHk/ZiHMdrEdIUo +7Zkg1T0ZBvmBXTUJzeDqIV0fMotFOQBJg5avyCcX56jHXbu2AmGQsQf6NoniXG37 +wY/xiPSUUmOKjAU/B4tc24ADa5r37JzlHbpOGe1nTb8AYxjyPDdjO4Um2BugKE+K +rq+NJMg8Ej2sXLOnS2FweCoIR+RXGAUUBizlHMKJ2UGQ5sCX7U86qvniMcO8CsXR +7eSkBTYpxVLENxb2zf3g22972QWuL9eHyQfuO5dca2JnenZv1aIrhTH59fX8Sw== +-----END CERTIFICATE----- diff --git a/crypto/test/data/tls/x509-server-ecdsa.pem b/crypto/test/data/tls/x509-server-ecdsa.pem new file mode 100644 index 000000000..221fce99a --- /dev/null +++ b/crypto/test/data/tls/x509-server-ecdsa.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqzCCAWOgAwIBAgIMVOBhgRR/e3iAhKcbMA0GCSqGSIb3DQEBCwUAMCMxITAf +BgNVBAMTGEJvdW5jeUNhc3RsZSBUTFMgVGVzdCBDQTAiGA8yMDE1MDIxNTA5MDYw +OVoYDzIwMzUwMjEwMDkwNjA5WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVz +dCBTZXJ2ZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQzME1njDHqizStYiqf +xC45McfdqtcDFCsyik7g7JwwGBzDI3WTP5stb8gLHwGARqkaTIDr/wau+N12bIxp +Tj6Co3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud +DwEB/wQFAwMHgAAwHQYDVR0OBBYEFOaifCD845nra+asxN59LzV1LlkxMB8GA1Ud +IwQYMBaAFPZjr6+j4u/uDuWysUYoangpMh7pMA0GCSqGSIb3DQEBCwUAA4IBMQCc +wMTPTd/82sDeJkN6B8M2AFfLf/0uw01/2I/UQp2rJCJu1Yps9S1foHz939o4qJA3 ++kieb3eVE8rcMQHMv42hagj09LmYY1Unzdu8xJDMq7gDIph72Fjy5YFqb9je79C4 +JPOadGsAsG9OY9DxTKsHyiX3Mqztx1hUQ0mNiAyaFEDGus+ZhSGMdHj0uR1LqZL9 +9OgszZY0UomZfhwnPg2sHumdh+13RZ38w33b43LpCcyu7v05szquqJ8lnol8j10r +6sH1xXZmb6OJIXZeHTnX5Dv1z0/R8qyG3gyVU7sP+8KVk529Q/YjIJ8YEV1LSERW +9cKbI+8DMxVE/z01gd0YLqpPcDSfzGUTww+lMWyGQ+KDUD2bC2O4LbZhzT+ZxCPN ++mw+T5KV78wcG02PThMf +-----END CERTIFICATE----- diff --git a/crypto/test/data/tls/x509-server-key-dsa.pem b/crypto/test/data/tls/x509-server-key-dsa.pem new file mode 100644 index 000000000..d6073b31f --- /dev/null +++ b/crypto/test/data/tls/x509-server-key-dsa.pem @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICZAIBADCCAjkGByqGSM44BAEwggIsAoIBAQDW5Rnf6bmWFg75kjAsdAJ0EHG5 +o1IQdzDevP34ZChcAT1NUISUYkhFQxtW57FD+eRECg7Nb6Ykl4MvPT92k3GoKtDP +rq6zfezD3iqARfLJOKOmsa7rKcQ+NTsioVuvDZ5OeBPt5hDwAUuMmKbLhIRX2mYT +lF3QPWlBVpzze6KO0JSPhe5WvG5bs/BvI/NWjLBMIwXRCoPtjKdft9zVWiFhHoJ7 +p1RJG9LyXf1sC2WI/joJiuH5/6qiHUVyG43jVL6QLZJROTawEbMCNEV7l8lsT3wa +0Em1pNw0L27lmxHklK4WGOu2G6TxgOUZ4PGsKcXV4b87Epk/XOgZay3xeiDdAiEA +1rVh2jJpQFWVvadA5rI+9LDRycTmFpaowhMxe2sVd38CggEAIBWaI7l/55Xq4thP +Qum/HEE6H+OiWXgHhtkr5PCPdXJyL9Il0x38s1i1gwGJ33rjJrfpzAOvwNSveGCN +XbnN4moS2uVN3zgAliXRbS/wgBVcjbYe5Q3h21kxYzOR4AO+qc5gH7xbWaXCadQF +GWQft3KCkq+mazGoLdR4aHnxsqOyZD6bMRohRCge/a15BYtABLEp23bhRHM64PAw +XV5vf/8lEJ08NqaYXMC2berehKt1q6bt+uA5/oSXoKS3wOrjobUScPu8b+Y5AW7y +MadTy2RJ9eqpjyjLNyJuEFGtruRdJy2FBh4tNYuTkp9FFp6JvBHA4rP9EAq5MgWo +jGjZJAQiAiBhYRIk49XUmvOqUx953A+n8/KWUfyZyTHPkcIXBvW+Ig== +-----END PRIVATE KEY----- diff --git a/crypto/test/data/tls/x509-server-key-ecdsa.pem b/crypto/test/data/tls/x509-server-key-ecdsa.pem new file mode 100644 index 000000000..01fe38567 --- /dev/null +++ b/crypto/test/data/tls/x509-server-key-ecdsa.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIGUAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHoweAIBAQQhALoiXMjOXuPkNVT6 +g/8PnBmXj8wEvWXCyrpO+fh9EMTdoAoGCCqGSM49AwEHoUQDQgAEMzBNZ4wx6os0 +rWIqn8QuOTHH3arXAxQrMopO4OycMBgcwyN1kz+bLW/ICx8BgEapGkyA6/8Grvjd +dmyMaU4+gg== +-----END PRIVATE KEY----- diff --git a/crypto/test/lib/nunit.core.dll b/crypto/test/lib/nunit.core.dll index f58c07d42..8d99c637d 100644 --- a/crypto/test/lib/nunit.core.dll +++ b/crypto/test/lib/nunit.core.dll Binary files differdiff --git a/crypto/test/lib/nunit.core.interfaces.dll b/crypto/test/lib/nunit.core.interfaces.dll index cdf50b687..70a76b21c 100644 --- a/crypto/test/lib/nunit.core.interfaces.dll +++ b/crypto/test/lib/nunit.core.interfaces.dll Binary files differdiff --git a/crypto/test/lib/nunit.framework.dll b/crypto/test/lib/nunit.framework.dll index c7b1c65d9..ba484ba8c 100644 --- a/crypto/test/lib/nunit.framework.dll +++ b/crypto/test/lib/nunit.framework.dll Binary files differdiff --git a/crypto/test/src/asn1/test/AllTests.cs b/crypto/test/src/asn1/test/AllTests.cs index a1ae8fd48..ad2f90362 100644 --- a/crypto/test/src/asn1/test/AllTests.cs +++ b/crypto/test/src/asn1/test/AllTests.cs @@ -9,24 +9,22 @@ namespace Org.BouncyCastle.Asn1.Tests { public static void Main(string[] args) { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("ASN.1 tests"); - - suite.Add(new AllTests()); - - // TODO Add these tests to RegressionTest list - suite.Add(new Asn1SequenceParserTest()); - suite.Add(new OctetStringTest()); - suite.Add(new ParseTest()); - suite.Add(new TimeTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("ASN.1 tests"); + // TODO Add these tests to RegressionTest list + suite.Add(new Asn1SequenceParserTest()); + suite.Add(new OctetStringTest()); + suite.Add(new ParseTest()); + suite.Add(new TimeTest()); + return suite; + } } } } diff --git a/crypto/test/src/cms/test/AllTests.cs b/crypto/test/src/cms/test/AllTests.cs index 1ce3b7c8d..b7ac7644b 100644 --- a/crypto/test/src/cms/test/AllTests.cs +++ b/crypto/test/src/cms/test/AllTests.cs @@ -9,27 +9,26 @@ namespace Org.BouncyCastle.Cms.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("CMS Tests"); - - suite.Add(new CompressedDataTest()); - suite.Add(new CompressedDataStreamTest()); - suite.Add(new EnvelopedDataTest()); - suite.Add(new EnvelopedDataStreamTest()); - suite.Add(new Rfc4134Test()); - suite.Add(new SignedDataTest()); - suite.Add(new SignedDataStreamTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("CMS Tests"); + suite.Add(new CompressedDataTest()); + suite.Add(new CompressedDataStreamTest()); + suite.Add(new EnvelopedDataTest()); + suite.Add(new EnvelopedDataStreamTest()); + suite.Add(new Rfc4134Test()); + suite.Add(new SignedDataTest()); + suite.Add(new SignedDataStreamTest()); + return suite; + } } } } diff --git a/crypto/test/src/crypto/io/test/AllTests.cs b/crypto/test/src/crypto/io/test/AllTests.cs index 0296a2dc0..5c8c759f9 100644 --- a/crypto/test/src/crypto/io/test/AllTests.cs +++ b/crypto/test/src/crypto/io/test/AllTests.cs @@ -7,21 +7,20 @@ namespace Org.BouncyCastle.Crypto.IO.Tests { public class AllTests { - public static void Main( - string[] args) - { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - public static TestSuite suite() - { - TestSuite suite = new TestSuite("IO tests"); - - suite.Add(new CipherStreamTest()); - - return suite; - } + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("IO tests"); + suite.Add(new CipherStreamTest()); + return suite; + } + } } } diff --git a/crypto/test/src/crypto/test/AllTests.cs b/crypto/test/src/crypto/test/AllTests.cs index 1cb1b965d..3d8ef5602 100644 --- a/crypto/test/src/crypto/test/AllTests.cs +++ b/crypto/test/src/crypto/test/AllTests.cs @@ -10,19 +10,24 @@ namespace Org.BouncyCastle.Crypto.Tests [TestFixture] public class AllTests { - [Suite] - public static TestSuite Suite - { - get - { - TestSuite suite = new TestSuite("Lightweight Crypto Tests"); - suite.Add(new AllTests()); - suite.Add(new GcmReorderTest()); - return suite; - } - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - [Test] + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("Lightweight Crypto Tests"); + suite.Add(new AllTests()); + suite.Add(new GcmReorderTest()); + return suite; + } + } + + [Test] public void TestCrypto() { foreach (Org.BouncyCastle.Utilities.Test.ITest test in RegressionTest.tests) @@ -35,13 +40,5 @@ namespace Org.BouncyCastle.Crypto.Tests } } } - - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - Suite.Run(el); - } } } diff --git a/crypto/test/src/crypto/test/CCMTest.cs b/crypto/test/src/crypto/test/CCMTest.cs index 4a54fb4f9..8c46e11e7 100644 --- a/crypto/test/src/crypto/test/CCMTest.cs +++ b/crypto/test/src/crypto/test/CCMTest.cs @@ -81,7 +81,38 @@ namespace Org.BouncyCastle.Crypto.Tests // checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5); - // + // decryption with output specified, non-zero offset. + ccm.Init(false, new AeadParameters(new KeyParameter(K2), 48, N2, A2)); + + byte[] inBuf = new byte[C2.Length + 10]; + byte[] outBuf = new byte[ccm.GetOutputSize(C2.Length) + 10]; + + Array.Copy(C2, 0, inBuf, 10, C2.Length); + + int len = ccm.ProcessPacket(inBuf, 10, C2.Length, outBuf, 10); + byte[] output = ccm.ProcessPacket(C2, 0, C2.Length); + + if (len != output.Length || !isEqual(output, outBuf, 10)) + { + Fail("decryption output incorrect"); + } + + // encryption with output specified, non-zero offset. + ccm.Init(true, new AeadParameters(new KeyParameter(K2), 48, N2, A2)); + + int inLen = len; + inBuf = outBuf; + outBuf = new byte[ccm.GetOutputSize(inLen) + 10]; + + len = ccm.ProcessPacket(inBuf, 10, inLen, outBuf, 10); + output = ccm.ProcessPacket(inBuf, 10, inLen); + + if (len != output.Length || !isEqual(output, outBuf, 10)) + { + Fail("encryption output incorrect"); + } + + // // exception tests // @@ -121,6 +152,17 @@ namespace Org.BouncyCastle.Crypto.Tests } } + private bool isEqual(byte[] exp, byte[] other, int off) + { + for (int i = 0; i != exp.Length; i++) + { + if (exp[i] != other[off + i]) + return false; + } + + return true; + } + private void checkVectors( int count, CcmBlockCipher ccm, @@ -203,7 +245,8 @@ namespace Org.BouncyCastle.Crypto.Tests if (!AreEqual(p, dec)) { - Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType); + Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType, + Hex.ToHexString(p), Hex.ToHexString(dec)); } if (!AreEqual(t, ccm.GetMac())) diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index 27d6bb0e9..0b7a0f72d 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -118,7 +118,8 @@ namespace Org.BouncyCastle.Crypto.Tests new SipHashTest(), new Poly1305Test(), new OcbTest(), - new SM3DigestTest() + new SM3DigestTest(), + new X931SignerTest() }; public static void Main( diff --git a/crypto/test/src/crypto/test/SRP6Test.cs b/crypto/test/src/crypto/test/SRP6Test.cs index 3b80e2c16..6b64df924 100644 --- a/crypto/test/src/crypto/test/SRP6Test.cs +++ b/crypto/test/src/crypto/test/SRP6Test.cs @@ -23,15 +23,7 @@ namespace Org.BouncyCastle.Crypto.Tests return new BigInteger(1, Hex.Decode(hex)); } - // 1024 bit example prime from RFC5054 and corresponding generator - private static readonly BigInteger N_1024 = FromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" - + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" - + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" - + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" - + "FD5138FE8376435B9FC61D2FC0EB06E3"); - private static readonly BigInteger g_1024 = BigInteger.Two; - - private readonly SecureRandom random = new SecureRandom(); + private readonly SecureRandom random = new SecureRandom(); public override string Name { @@ -42,9 +34,9 @@ namespace Org.BouncyCastle.Crypto.Tests { rfc5054AppendixBTestVectors(); - testMutualVerification(N_1024, g_1024); - testClientCatchesBadB(N_1024, g_1024); - testServerCatchesBadA(N_1024, g_1024); + testMutualVerification(Srp6StandardGroups.rfc5054_1024); + testClientCatchesBadB(Srp6StandardGroups.rfc5054_1024); + testServerCatchesBadA(Srp6StandardGroups.rfc5054_1024); testWithRandomParams(256); testWithRandomParams(384); @@ -56,8 +48,8 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] I = Encoding.UTF8.GetBytes("alice"); byte[] P = Encoding.UTF8.GetBytes("password123"); byte[] s = Hex.Decode("BEB25379D1A8581EB5A727673A2441EE"); - BigInteger N = N_1024; - BigInteger g = g_1024; + BigInteger N = Srp6StandardGroups.rfc5054_1024.N; + BigInteger g = Srp6StandardGroups.rfc5054_1024.G; BigInteger a = FromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393"); BigInteger b = FromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20"); @@ -148,13 +140,10 @@ namespace Org.BouncyCastle.Crypto.Tests paramGen.Init(bits, 25, random); DHParameters parameters = paramGen.GenerateParameters(); - BigInteger g = parameters.G; - BigInteger p = parameters.P; - - testMutualVerification(p, g); + testMutualVerification(new Srp6GroupParameters(parameters.P, parameters.G)); } - private void testMutualVerification(BigInteger N, BigInteger g) + private void testMutualVerification(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -162,16 +151,16 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6VerifierGenerator gen = new Srp6VerifierGenerator(); - gen.Init(N, g, new Sha256Digest()); + gen.Init(group, new Sha256Digest()); BigInteger v = gen.GenerateVerifier(s, I, P); Srp6Client client = new Srp6Client(); - client.Init(N, g, new Sha256Digest(), random); + client.Init(group, new Sha256Digest(), random); Srp6Server server = new Srp6Server(); - server.Init(N, g, v, new Sha256Digest(), random); + server.Init(group, v, new Sha256Digest(), random); - BigInteger A = client.GenerateClientCredentials(s, I, P); + BigInteger A = client.GenerateClientCredentials(s, I, P); BigInteger B = server.GenerateServerCredentials(); BigInteger clientS = client.CalculateSecret(B); @@ -183,7 +172,7 @@ namespace Org.BouncyCastle.Crypto.Tests } } - private void testClientCatchesBadB(BigInteger N, BigInteger g) + private void testClientCatchesBadB(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -191,7 +180,7 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6Client client = new Srp6Client(); - client.Init(N, g, new Sha256Digest(), random); + client.Init(group, new Sha256Digest(), random); client.GenerateClientCredentials(s, I, P); @@ -207,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - client.CalculateSecret(N); + client.CalculateSecret(group.N); Fail("Client failed to detect invalid value for 'B'"); } catch (CryptoException) @@ -216,7 +205,7 @@ namespace Org.BouncyCastle.Crypto.Tests } } - private void testServerCatchesBadA(BigInteger N, BigInteger g) + private void testServerCatchesBadA(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -224,11 +213,11 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6VerifierGenerator gen = new Srp6VerifierGenerator(); - gen.Init(N, g, new Sha256Digest()); + gen.Init(group, new Sha256Digest()); BigInteger v = gen.GenerateVerifier(s, I, P); Srp6Server server = new Srp6Server(); - server.Init(N, g, v, new Sha256Digest(), random); + server.Init(group, v, new Sha256Digest(), random); server.GenerateServerCredentials(); @@ -244,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - server.CalculateSecret(N); + server.CalculateSecret(group.N); Fail("Client failed to detect invalid value for 'A'"); } catch (CryptoException) diff --git a/crypto/test/src/crypto/test/X931SignerTest.cs b/crypto/test/src/crypto/test/X931SignerTest.cs new file mode 100644 index 000000000..d03cbc8e4 --- /dev/null +++ b/crypto/test/src/crypto/test/X931SignerTest.cs @@ -0,0 +1,145 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class X931SignerTest + : SimpleTest + { + public override string Name + { + get { return "X931Signer"; } + } + + public override void PerformTest() + { + BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt")); + BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ==")); + BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt")); + BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ==")); + BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ==")); + BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E=")); + BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE=")); + BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0=")); + BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg==")); + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp); + RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv); + + byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 }; + + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + signer.Init(true, rsaPrivate); + signer.BlockUpdate(msg, 0, msg.Length); + byte[] sig = signer.GenerateSignature(); + + signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + signer.Init(false, rsaPublic); + signer.BlockUpdate(msg, 0, msg.Length); + if (!signer.VerifySignature(sig)) + { + Fail("X9.31 Signer failed."); + } + + ShouldPassSignatureTest1(); + ShouldPassSignatureTest2(); + ShouldPassSignatureTest3(); + } + + private void ShouldPassSignatureTest1() + { + BigInteger n = new BigInteger("c9be1b28f8caccca65d86cc3c9bbcc13eccc059df3b80bd2292b811eff3aa0dd75e1e85c333b8e3fa9bed53bb20f5359ff4e6900c5e9a388e3a4772a583a79e2299c76582c2b27694b65e9ba22e66bfb817f8b70b22206d7d8ae488c86dbb7137c26d5eff9b33c90e6cee640630313b7a715802e15142fef498c404a8de19674974785f0f852e2d470fe85a2e54ffca9f5851f672b71df691785a5cdabe8f14aa628942147de7593b2cf962414a5b59c632c4e14f1768c0ab2e9250824beea60a3529f11bf5e070ce90a47686eb0be1086fb21f0827f55295b4a48307db0b048c05a4aec3f488c576ca6f1879d354224c7e84cbcd8e76dd217a3de54dba73c35", 16); + BigInteger e = new BigInteger("e75b1b", 16); + byte[] msg = Hex.Decode("5bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce"); + byte[] sig = Hex.Decode("0fe8bb8e3109a1eb7489ef35bf4c1a0780071da789c8bd226a4170538eafefdd30b732d628f0e87a0b9450051feae9754d4fb61f57862d10f0bacc4f660d13281d0cd1141c006ade5186ff7d961a4c6cd0a4b352fc1295c5afd088f80ac1f8e192ef116a010a442655fe8ff5eeacea15807906fb0f0dfa86e680d4c005872357f7ece9aa4e20b15d5f709b30f08648ecaa34f2fbf54eb6b414fa2ff6f87561f70163235e69ccb4ac82a2e46d3be214cc2ef5263b569b2d8fd839b21a9e102665105ea762bda25bb446cfd831487a6b846100dee113ae95ae64f4af22c428c87bab809541c962bb3a56d4c86588e0af4ebc7fcc66dadced311051356d3ea745f7"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 1 failed."); + } + } + + private void ShouldPassSignatureTest2() + { + BigInteger n = new BigInteger("b746ba6c3c0be64bbe33aa55b2929b0af4e86d773d44bfe5914db9287788c4663984b61a418d2eecca30d752ff6b620a07ec72eeb2b422d2429da352407b99982800b9dd7697be6a7b1baa98ca5f4fc2fe33400f20b9dba337ac25c987804165d4a6e0ee4d18eabd6de5abdfe578cae6713ff91d16c80a5bb20217fe614d9509e75a43e1825327b9da8f0a9f6eeaa1c04b69fb4bacc073569fff4ab491becbe6d0441d437fc3fa823239c4a0f75321666b68dd3f66e2dd394089a15bcc288a68a4eb0a48e17d639743b9dea0a91cc35820544732aff253f8ca9967c609dc01c2f8cd0313a7a91cfa94ff74289a1d2b6f19d1811f4b9a65f4cce9e5759b4cc64f", 16); + BigInteger e = new BigInteger("dcbbdb", 16); + byte[] msg = Hex.Decode("a5d3c8a060f897bbbc20ae0955052f37fbc70986b6e11c65075c9f457142bfa93856897c69020aa81a91b5e4f39e05cdeecc63395ab849c8262ca8bc5c96870aecb8edb0aba0024a9bdb71e06de6100344e5c318bc979ef32b8a49a8278ba99d4861bce42ebbc5c8c666aaa6cac39aff8779f2cae367620f9edd4cb1d80b6c8c"); + byte[] sig = Hex.Decode("39fbbd1804c689a533b0043f84da0f06081038c0fbf31e443e46a05e58f50de5198bbca40522afefaba3aed7082a6cb93b1da39f1f5a42246bf64930781948d300549bef0f8d554ecfca60a1b1ecba95a7014ee4545ad4f0c4e3a31942c6738b4ccd6244b6a21267dadf0826a5f713f13b1f5a9ab8501d957a26d4948278ac67851071a315674bdab173bfef2c2690c8373da6bf3d69f30c0e5da8883de872f59521b40793854085641adf98d13db991c5d0a8aaa0222934fa33332e90ef0b954e195cb267d6ffb36c96e14d1ec7b915a87598b4461a3146566354dc2ae748c84ee0cd46543b53ebff8cdf47725b280a1f799fb6ebb4a31ad2bdd5178250f83a"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha224Digest()); + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 2 failed."); + } + } + + private void ShouldPassSignatureTest3() + { + BigInteger n = new BigInteger("dcb5686a3d2063a3f9cf7b9b32d2d3765b4c449b09b4960245a9111cd3b0cbd3260496885b8e1fa5db33b03efcc759d9c1afe29d93c6faebc7e0efada334b5b9a29655e2da2c8f11103d8203be311feab7ae88e9f1b2ec7d8fc655d77202b1681dd9717ec0f525b35584987e19539635a1ed23ca482a00149c609a23dc1645fd", 16); + BigInteger e = new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc9f7", 16); + BigInteger d = new BigInteger("189d6345099098992e0c9ca5f281e1338092342fa0acc85cc2a111f30f9bd2fb4753cd1a48ef0ddca9bf1af33ec76fb2e23a9fb4896c26f2235b516f7c05ef7ae81e70f4b491a5fedba9b935e9c76d761a813ce7776ff8a1e5efe1166ff2eca26aa900da88c908d51af9de26977fe39719cc781df32216fa41b838f0c63803c3", 16); + + byte[] msg = Hex.Decode("911475c6e210ef4ac65b6fe8d2bfe5e01b959771b137c4ef69b88716e0d2ff9ebc1fad0f358c1dd7d50cc99a7b893ac9a6207076f08d8467d9e48c69c683bfe64a44dabaa3f7c243880f6ab7229bf7bb587822314fc5de5131983bfb2eef8b4bc1eac36f353724b567cd1ae8cddd64ddb7057549d5c81ad5fa3b5e751f00abf5"); + byte[] sig = Hex.Decode("02c50ec0ac8a7f38ef5630c396964d6a6daaa7e3083ab5b57fa2a2632f3b70e2e85c8456cd774d45d7e44fcb063f0f04fff9f1e3adfda11272535a92cb59320b190b5ee4261f23d6ceaa925df3a7bfa42e26bf61ea9645d9d64b3c90a820802768a6e209c9f83705375a3867afccc037e8242a98fa4c3db6b2d9877754d47289"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + + signer.Init(true, new RsaKeyParameters(true, n, d)); + + signer.BlockUpdate(msg, 0, msg.Length); + + byte[] s = signer.GenerateSignature(); + + if (!Arrays.AreEqual(sig, s)) + { + Fail("RSA X931 sig test 3 failed."); + } + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 3 failed."); + } + } + + public static void Main(string[] args) + { + RunTest(new X931SignerTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs new file mode 100644 index 000000000..bc99ccc63 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class DtlsProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom); + DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom); + + MockDatagramAssociation network = new MockDatagramAssociation(1500); + + Server server = new Server(serverProtocol, network.Server); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + DatagramTransport clientTransport = network.Client; + + clientTransport = new UnreliableDatagramTransport(clientTransport, secureRandom, 0, 0); + + clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out); + + MockDtlsClient client = new MockDtlsClient(null); + + DtlsTransport dtlsClient = clientProtocol.Connect(client, clientTransport); + + for (int i = 1; i <= 10; ++i) + { + byte[] data = new byte[i]; + Arrays.Fill(data, (byte)i); + dtlsClient.Send(data, 0, data.Length); + } + + byte[] buf = new byte[dtlsClient.GetReceiveLimit()]; + while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0) + { + } + + dtlsClient.Close(); + + server.Shutdown(serverThread); + } + + internal class Server + { + private readonly DtlsServerProtocol mServerProtocol; + private readonly DatagramTransport mServerTransport; + private volatile bool isShutdown = false; + + internal Server(DtlsServerProtocol serverProtocol, DatagramTransport serverTransport) + { + this.mServerProtocol = serverProtocol; + this.mServerTransport = serverTransport; + } + + public void Run() + { + try + { + MockDtlsServer server = new MockDtlsServer(); + DtlsTransport dtlsServer = mServerProtocol.Accept(server, mServerTransport); + byte[] buf = new byte[dtlsServer.GetReceiveLimit()]; + while (!isShutdown) + { + int length = dtlsServer.Receive(buf, 0, buf.Length, 1000); + if (length >= 0) + { + dtlsServer.Send(buf, 0, length); + } + } + dtlsServer.Close(); + } + catch (Exception e) + { + Console.Error.WriteLine(e.StackTrace); + } + } + + internal void Shutdown(Thread serverThread) + { + if (!isShutdown) + { + isShutdown = true; + serverThread.Join(); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs new file mode 100644 index 000000000..d4af04fac --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs @@ -0,0 +1,153 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class DtlsTestCase + { + private static void CheckDtlsVersion(ProtocolVersion version) + { + if (version != null && !version.IsDtls) + throw new InvalidOperationException("Non-DTLS version"); + } + + [Test, TestCaseSource(typeof(DtlsTestSuite), "Suite")] + public void RunTest(TlsTestConfig config) + { + CheckDtlsVersion(config.clientMinimumVersion); + CheckDtlsVersion(config.clientOfferVersion); + CheckDtlsVersion(config.serverMaximumVersion); + CheckDtlsVersion(config.serverMinimumVersion); + + SecureRandom secureRandom = new SecureRandom(); + + DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom); + DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom); + + MockDatagramAssociation network = new MockDatagramAssociation(1500); + + TlsTestClientImpl clientImpl = new TlsTestClientImpl(config); + TlsTestServerImpl serverImpl = new TlsTestServerImpl(config); + + Server server = new Server(this, serverProtocol, network.Server, serverImpl); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + Exception caught = null; + try + { + DatagramTransport clientTransport = network.Client; + + if (TlsTestConfig.DEBUG) + { + clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out); + } + + DtlsTransport dtlsClient = clientProtocol.Connect(clientImpl, clientTransport); + + for (int i = 1; i <= 10; ++i) + { + byte[] data = new byte[i]; + Arrays.Fill(data, (byte)i); + dtlsClient.Send(data, 0, data.Length); + } + + byte[] buf = new byte[dtlsClient.GetReceiveLimit()]; + while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0) + { + } + + dtlsClient.Close(); + } + catch (Exception e) + { + caught = e; + LogException(caught); + } + + server.Shutdown(serverThread); + + // TODO Add checks that the various streams were closed + + Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end"); + Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end"); + + Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description"); + Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description"); + + if (config.expectFatalAlertConnectionEnd == -1) + { + Assert.IsNull(caught, "Unexpected client exception"); + Assert.IsNull(server.mCaught, "Unexpected server exception"); + } + } + + protected void LogException(Exception e) + { + if (TlsTestConfig.DEBUG) + { + Console.Error.WriteLine(e.StackTrace); + } + } + + internal class Server + { + private readonly DtlsTestCase mOuter; + private readonly DtlsServerProtocol mServerProtocol; + private readonly DatagramTransport mServerTransport; + private readonly TlsTestServerImpl mServerImpl; + + private volatile bool isShutdown = false; + internal Exception mCaught = null; + + internal Server(DtlsTestCase outer, DtlsServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl) + { + this.mOuter = outer; + this.mServerProtocol = serverProtocol; + this.mServerTransport = serverTransport; + this.mServerImpl = serverImpl; + } + + public void Run() + { + try + { + DtlsTransport dtlsServer = mServerProtocol.Accept(mServerImpl, mServerTransport); + byte[] buf = new byte[dtlsServer.GetReceiveLimit()]; + while (!isShutdown) + { + int length = dtlsServer.Receive(buf, 0, buf.Length, 100); + if (length >= 0) + { + dtlsServer.Send(buf, 0, length); + } + } + dtlsServer.Close(); + } + catch (Exception e) + { + mCaught = e; + mOuter.LogException(mCaught); + } + } + + internal void Shutdown(Thread serverThread) + { + if (!isShutdown) + { + isShutdown = true; + serverThread.Interrupt(); + serverThread.Join(); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs new file mode 100644 index 000000000..eb9d42e5f --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class DtlsTestSuite + { + // Make the access to constants less verbose + internal class C : TlsTestConfig {} + + public DtlsTestSuite() + { + } + + public static IEnumerable Suite() + { + IList testSuite = new ArrayList(); + + AddFallbackTests(testSuite); + AddVersionTests(testSuite, ProtocolVersion.DTLSv10); + AddVersionTests(testSuite, ProtocolVersion.DTLSv12); + + return testSuite; + } + + private static void AddFallbackTests(IList testSuite) + { + { + TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + c.clientFallback = true; + + testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + } + + /* + * 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 + */ + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + // c.clientOfferVersion = ProtocolVersion.DTLSv10; + // c.clientFallback = true; + // c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); + + // testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); + //} + + { + TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + c.clientOfferVersion = ProtocolVersion.DTLSv10; + + testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + } + } + + private static void AddVersionTests(IList testSuite, ProtocolVersion version) + { + string prefix = version.ToString() + .Replace(" ", "") + .Replace("\\", "") + .Replace(".", "") + + "_"; + + /* + * 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 + */ + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; + // c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); + //} + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; + // c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); + //} + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_NONE; + // c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; + // c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); + //} + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.serverCertReq = C.SERVER_CERT_REQ_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + } + } + + private static TlsTestConfig CreateDtlsTestConfig(ProtocolVersion version) + { + TlsTestConfig c = new TlsTestConfig(); + c.clientMinimumVersion = ProtocolVersion.DTLSv10; + /* + * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with + * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server + */ + c.clientOfferVersion = version; + c.serverMaximumVersion = version; + c.serverMinimumVersion = ProtocolVersion.DTLSv10; + return c; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs b/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs new file mode 100644 index 000000000..a26c5bdbf --- /dev/null +++ b/crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Text; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class LoggingDatagramTransport + : DatagramTransport + { + private static readonly string HEX_CHARS = "0123456789ABCDEF"; + + private readonly DatagramTransport transport; + private readonly TextWriter output; + private readonly long launchTimestamp; + + public LoggingDatagramTransport(DatagramTransport transport, TextWriter output) + { + this.transport = transport; + this.output = output; + this.launchTimestamp = DateTimeUtilities.CurrentUnixMs(); + } + + public virtual int GetReceiveLimit() + { + return transport.GetReceiveLimit(); + } + + public virtual int GetSendLimit() + { + return transport.GetSendLimit(); + } + + public virtual int Receive(byte[] buf, int off, int len, int waitMillis) + { + int length = transport.Receive(buf, off, len, waitMillis); + if (length >= 0) + { + DumpDatagram("Received", buf, off, length); + } + return length; + } + + public virtual void Send(byte[] buf, int off, int len) + { + DumpDatagram("Sending", buf, off, len); + transport.Send(buf, off, len); + } + + public virtual void Close() + { + } + + private void DumpDatagram(string verb, byte[] buf, int off, int len) + { + long timestamp = DateTimeUtilities.CurrentUnixMs() - launchTimestamp; + StringBuilder sb = new StringBuilder("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:"); + for (int pos = 0; pos < len; ++pos) + { + if (pos % 16 == 0) + { + sb.Append(Environment.NewLine); + sb.Append(" "); + } + else if (pos % 16 == 8) + { + sb.Append('-'); + } + else + { + sb.Append(' '); + } + int val = buf[off + pos] & 0xFF; + sb.Append(HEX_CHARS[val >> 4]); + sb.Append(HEX_CHARS[val & 0xF]); + } + Dump(sb.ToString()); + } + + private void Dump(string s) + { + lock (this) output.WriteLine(s); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs new file mode 100644 index 000000000..48df36ca9 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; +using System.IO; +using System.Net; +using System.Threading; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDatagramAssociation + { + private int mtu; + private MockDatagramTransport client, server; + + public MockDatagramAssociation(int mtu) + { + this.mtu = mtu; + + IList clientQueue = new ArrayList(); + IList serverQueue = new ArrayList(); + + this.client = new MockDatagramTransport(this, clientQueue, serverQueue); + this.server = new MockDatagramTransport(this, serverQueue, clientQueue); + } + + public virtual DatagramTransport Client + { + get { return client; } + } + + public virtual DatagramTransport Server + { + get { return server; } + } + + private class MockDatagramTransport + : DatagramTransport + { + private readonly MockDatagramAssociation mOuter; + + private IList receiveQueue, sendQueue; + + internal MockDatagramTransport(MockDatagramAssociation outer, IList receiveQueue, IList sendQueue) + { + this.mOuter = outer; + this.receiveQueue = receiveQueue; + this.sendQueue = sendQueue; + } + + public virtual int GetReceiveLimit() + { + return mOuter.mtu; + } + + public virtual int GetSendLimit() + { + return mOuter.mtu; + } + + public virtual int Receive(byte[] buf, int off, int len, int waitMillis) + { + lock (receiveQueue) + { + if (receiveQueue.Count < 1) + { + try + { + Monitor.Wait(receiveQueue, waitMillis); + } + catch (ThreadInterruptedException) + { + // TODO Keep waiting until full wait expired? + } + if (receiveQueue.Count < 1) + { + return -1; + } + } + byte[] packet = (byte[])receiveQueue[0]; + receiveQueue.RemoveAt(0); + int copyLength = System.Math.Min(len, packet.Length); + Array.Copy(packet, 0, buf, off, copyLength); + return copyLength; + } + } + + public virtual void Send(byte[] buf, int off, int len) + { + if (len > mOuter.mtu) + { + // TODO Simulate rejection? + } + + byte[] packet = Arrays.CopyOfRange(buf, off, off + len); + + lock (sendQueue) + { + sendQueue.Add(packet); + Monitor.PulseAll(sendQueue); + } + } + + public virtual void Close() + { + // TODO? + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs new file mode 100644 index 000000000..e3c604db7 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDtlsClient + : DefaultTlsClient + { + protected TlsSession mSession; + + public MockDtlsClient(TlsSession session) + { + this.mSession = session; + } + + public override TlsSession GetSessionToResume() + { + return this.mSession; + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override ProtocolVersion ClientVersion + { + get { return ProtocolVersion.DTLSv12; } + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.DTLSv10; } + } + + //public override int[] GetCipherSuites() + //{ + // return Arrays.Concatenate(base.GetCipherSuites(), + // new int[] + // { + // CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + // CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + // }); + //} + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); + TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); + TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("Negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + internal class MyTlsAuthentication + : TlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public virtual void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("DTLS client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + + public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) + { + byte[] certificateTypes = certificateRequest.CertificateTypes; + if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) + return null; + + return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms, + SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem"); + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDtlsServer.cs b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs new file mode 100644 index 000000000..19062181b --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDtlsServer + : DefaultTlsServer + { + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + protected override int[] GetCipherSuites() + { + return Arrays.Concatenate(base.GetCipherSuites(), + new int[] + { + CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + }); + } + + public override CertificateRequest GetCertificateRequest() + { + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + + IList serverSigAlgs = null; + if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) + { + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + } + + IList certificateAuthorities = new ArrayList(); + certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); + + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); + } + + public override void NotifyClientCertificate(Certificate clientCertificate) + { + X509CertificateStructure[] chain = clientCertificate.GetCertificateList(); + Console.WriteLine("DTLS server received client certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.DTLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.DTLSv10; } + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[] { "x509-server.pem", "x509-ca.pem" }, + "x509-server-key.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs new file mode 100644 index 000000000..dfc0e93a0 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockPskTlsClient + : PskTlsClient + { + internal TlsSession mSession; + + internal MockPskTlsClient(TlsSession session) + : this(session, new BasicTlsPskIdentity("client", new byte[16])) + { + } + + internal MockPskTlsClient(TlsSession session, TlsPskIdentity pskIdentity) + : base(pskIdentity) + { + this.mSession = session; + } + + public override TlsSession GetSessionToResume() + { + return this.mSession; + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + public override int[] GetCipherSuites() + { + return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA }; + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("TLS-PSK client negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + internal class MyTlsAuthentication + : ServerOnlyTlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public override void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("TLS-PSK client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs new file mode 100644 index 000000000..7394a2077 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockPskTlsServer + : PskTlsServer + { + internal MockPskTlsServer() + : base(new MyIdentityManager()) + { + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + byte[] pskIdentity = mContext.SecurityParameters.PskIdentity; + if (pskIdentity != null) + { + string name = Strings.FromUtf8ByteArray(pskIdentity); + Console.WriteLine("TLS-PSK server completed handshake for PSK identity: " + name); + } + } + + protected override int[] GetCipherSuites() + { + return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA }; + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + Console.WriteLine("TLS-PSK server negotiated " + serverVersion); + + return serverVersion; + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, + "x509-server-key.pem"); + } + + internal class MyIdentityManager + : TlsPskIdentityManager + { + public virtual byte[] GetHint() + { + return Strings.ToUtf8ByteArray("hint"); + } + + public virtual byte[] GetPsk(byte[] identity) + { + if (identity != null) + { + string name = Strings.FromUtf8ByteArray(identity); + if (name.Equals("client")) + { + return new byte[16]; + } + } + return null; + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs new file mode 100644 index 000000000..8a6b9f496 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockSrpTlsClient + : SrpTlsClient + { + internal TlsSession mSession; + + internal MockSrpTlsClient(TlsSession session, byte[] identity, byte[] password) + : base(identity, password) + { + this.mSession = session; + } + + public override TlsSession GetSessionToResume() + { + return this.mSession; + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("TLS-SRP client negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + internal class MyTlsAuthentication + : ServerOnlyTlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public override void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("TLS-SRP client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs new file mode 100644 index 000000000..c15f63e0b --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockSrpTlsServer + : SrpTlsServer + { + internal static readonly Srp6GroupParameters TEST_GROUP = Srp6StandardGroups.rfc5054_1024; + internal static readonly byte[] TEST_IDENTITY = Strings.ToUtf8ByteArray("client"); + internal static readonly byte[] TEST_PASSWORD = Strings.ToUtf8ByteArray("password"); + internal static readonly byte[] TEST_SALT = Strings.ToUtf8ByteArray("salt"); + internal static readonly byte[] TEST_SEED_KEY = Strings.ToUtf8ByteArray("seed_key"); + + internal MockSrpTlsServer() + : base(new MyIdentityManager()) + { + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + byte[] srpIdentity = mContext.SecurityParameters.SrpIdentity; + if (srpIdentity != null) + { + string name = Strings.FromUtf8ByteArray(srpIdentity); + Console.WriteLine("TLS-SRP server completed handshake for SRP identity: " + name); + } + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + Console.WriteLine("TLS-SRP server negotiated " + serverVersion); + + return serverVersion; + } + + protected override TlsSignerCredentials GetDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa, + "x509-server-dsa.pem", "x509-server-key-dsa.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + + internal class MyIdentityManager + : TlsSrpIdentityManager + { + protected SimulatedTlsSrpIdentityManager unknownIdentityManager = SimulatedTlsSrpIdentityManager.GetRfc5054Default( + TEST_GROUP, TEST_SEED_KEY); + + public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity) + { + if (Arrays.AreEqual(TEST_IDENTITY, identity)) + { + Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator(); + verifierGenerator.Init(TEST_GROUP, TlsUtilities.CreateHash(HashAlgorithm.sha1)); + + BigInteger verifier = verifierGenerator.GenerateVerifier(TEST_SALT, identity, TEST_PASSWORD); + + return new TlsSrpLoginParameters(TEST_GROUP, verifier, TEST_SALT); + } + + return unknownIdentityManager.GetLoginParameters(identity); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index a458e32e6..7c1198632 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -45,25 +45,24 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests + ", " + AlertDescription.GetText(alertDescription)); } - public override int[] GetCipherSuites() - { - return Arrays.Concatenate(base.GetCipherSuites(), - new int[] - { - CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, - CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, - CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, - CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, - }); - } + //public override int[] GetCipherSuites() + //{ + // return Arrays.Concatenate(base.GetCipherSuites(), + // new int[] + // { + // CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + // CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + // }); + //} public override IDictionary GetClientExtensions() { IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); - // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though) -// TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); + TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); return clientExtensions; @@ -121,8 +120,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests for (int i = 0; i != chain.Length; i++) { X509CertificateStructure entry = chain[i]; - // TODO Create Fingerprint based on certificate signature algorithm digest - Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } } @@ -133,27 +132,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) return null; - SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; - IList sigAlgs = certificateRequest.SupportedSignatureAlgorithms; - if (sigAlgs != null) - { - foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs) - { - if (sigAlg.Signature == SignatureAlgorithm.rsa) - { - signatureAndHashAlgorithm = sigAlg; - break; - } - } - - if (signatureAndHashAlgorithm == null) - { - return null; - } - } - - return TlsTestUtilities.LoadSignerCredentials(mContext, new string[] { "x509-client.pem", "x509-ca.pem" }, - "x509-client-key.pem", signatureAndHashAlgorithm); + return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms, + SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem"); } }; } diff --git a/crypto/test/src/crypto/tls/test/MockTlsServer.cs b/crypto/test/src/crypto/tls/test/MockTlsServer.cs index 14d6b9839..8fce95d63 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsServer.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsServer.cs @@ -61,29 +61,19 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests public override CertificateRequest GetCertificateRequest() { - IList serverSigAlgs = null; + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + IList serverSigAlgs = null; if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) { - byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; - byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa }; - - serverSigAlgs = new ArrayList(); - for (int i = 0; i < hashAlgorithms.Length; ++i) - { - for (int j = 0; j < signatureAlgorithms.Length; ++j) - { - serverSigAlgs.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i], - signatureAlgorithms[j])); - } - } + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); } IList certificateAuthorities = new ArrayList(); certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); - return new CertificateRequest(new byte[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities); + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); } public override void NotifyClientCertificate(Certificate clientCertificate) @@ -101,37 +91,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() { - return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" }, "x509-server-key.pem"); } protected override TlsSignerCredentials GetRsaSignerCredentials() { - /* - * TODO Note that this code fails to provide default value for the client supported - * algorithms if it wasn't sent. - */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; - IList sigAlgs = mSupportedSignatureAlgorithms; - if (sigAlgs != null) - { - foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs) - { - if (sigAlg.Signature == SignatureAlgorithm.rsa) - { - signatureAndHashAlgorithm = sigAlg; - break; - } - } - - if (signatureAndHashAlgorithm == null) - { - return null; - } - } - - return TlsTestUtilities.LoadSignerCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, - "x509-server-key.pem", signatureAndHashAlgorithm); + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); } } } diff --git a/crypto/test/src/crypto/tls/test/NetworkStream.cs b/crypto/test/src/crypto/tls/test/NetworkStream.cs new file mode 100644 index 000000000..04de81e13 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/NetworkStream.cs @@ -0,0 +1,101 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class NetworkStream + : Stream + { + private readonly Stream mInner; + private bool mClosed = false; + + internal NetworkStream(Stream inner) + { + this.mInner = inner; + } + + internal virtual bool IsClosed + { + get { lock (this) return mClosed; } + } + + public override bool CanRead + { + get { return mInner.CanRead; } + } + + public override bool CanSeek + { + get { return mInner.CanSeek; } + } + + public override bool CanWrite + { + get { return mInner.CanWrite; } + } + + public override void Close() + { + lock (this) mClosed = true; + } + + public override void Flush() + { + mInner.Flush(); + } + + public override long Length + { + get { return mInner.Length; } + } + + public override long Position + { + get { return mInner.Position; } + set { mInner.Position = value; } + } + + public override long Seek(long offset, SeekOrigin origin) + { + return mInner.Seek(offset, origin); + } + + public override void SetLength(long value) + { + mInner.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + CheckNotClosed(); + return mInner.Read(buffer, offset, count); + } + + public override int ReadByte() + { + CheckNotClosed(); + return mInner.ReadByte(); + } + + public override void Write(byte[] buf, int off, int len) + { + CheckNotClosed(); + mInner.Write(buf, off, len); + } + + public override void WriteByte(byte value) + { + CheckNotClosed(); + mInner.WriteByte(value); + } + + private void CheckNotClosed() + { + lock (this) + { + if (mClosed) + throw new ObjectDisposedException(this.GetType().Name); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/PipedStream.cs b/crypto/test/src/crypto/tls/test/PipedStream.cs new file mode 100644 index 000000000..6b2c15059 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/PipedStream.cs @@ -0,0 +1,134 @@ +using System; +using System.IO; +using System.Threading; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class PipedStream + : Stream + { + private readonly MemoryStream mBuf = new MemoryStream(); + private bool mClosed = false; + + private PipedStream mOther = null; + private long mReadPos = 0; + + internal PipedStream() + { + } + + internal PipedStream(PipedStream other) + { + lock (other) + { + this.mOther = other; + other.mOther = this; + } + } + + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override void Close() + { + lock (this) + { + mClosed = true; + Monitor.PulseAll(this); + } + } + + public override void Flush() + { + } + + public override long Length + { + get { throw new NotImplementedException(); } + } + + public override long Position + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + lock (mOther) + { + WaitForData(); + int len = (int)System.Math.Min(count, mOther.mBuf.Position - mReadPos); + Array.Copy(mOther.mBuf.GetBuffer(), mReadPos, buffer, offset, len); + mReadPos += len; + return len; + } + } + + public override int ReadByte() + { + lock (mOther) + { + WaitForData(); + bool eof = (mReadPos >= mOther.mBuf.Position); + return eof ? -1 : mOther.mBuf.GetBuffer()[mReadPos++]; + } + } + + public override void Write(byte[] buf, int off, int len) + { + lock (this) + { + CheckOpen(); + mBuf.Write(buf, off, len); + Monitor.PulseAll(this); + } + } + + public override void WriteByte(byte value) + { + lock (this) + { + CheckOpen(); + mBuf.WriteByte(value); + Monitor.PulseAll(mBuf); + } + } + + private void CheckOpen() + { + if (mClosed) + throw new ObjectDisposedException(this.GetType().Name); + } + + private void WaitForData() + { + while (mReadPos >= mOther.mBuf.Position && !mOther.mClosed) + { + Monitor.Wait(mOther); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs new file mode 100644 index 000000000..7072c7105 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using System.Net.Sockets; +using System.Text; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + /** + * A simple test designed to conduct a TLS handshake with an external TLS server. + * <p> + * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in + * this package (under 'src/test/resources') for help configuring an external TLS server. + * </p><p> + * In both cases, extra options are required to enable PSK ciphersuites and configure identities/keys. + * </p> + */ + public class PskTlsClientTest + { + private static readonly SecureRandom secureRandom = new SecureRandom(); + + public static void Main(string[] args) + { + string hostname = "localhost"; + int port = 5556; + + long time1 = DateTime.UtcNow.Ticks; + + /* + * Note: This is the default PSK identity for 'openssl s_server' testing, the server must be + * started with "-psk 6161616161" to make the keys match, and possibly the "-psk_hint" + * option should be present. + */ + string psk_identity = "Client_identity"; + byte[] psk = new byte[]{ 0x61, 0x61, 0x61, 0x61, 0x61 }; + + BasicTlsPskIdentity pskIdentity = new BasicTlsPskIdentity(psk_identity, psk); + + MockPskTlsClient client = new MockPskTlsClient(null, pskIdentity); + TlsClientProtocol protocol = OpenTlsConnection(hostname, port, client); + protocol.Close(); + + long time2 = DateTime.UtcNow.Ticks; + Console.WriteLine("Elapsed 1: " + (time2 - time1)/TimeSpan.TicksPerMillisecond + "ms"); + + client = new MockPskTlsClient(client.GetSessionToResume(), pskIdentity); + protocol = OpenTlsConnection(hostname, port, client); + + long time3 = DateTime.UtcNow.Ticks; + Console.WriteLine("Elapsed 2: " + (time3 - time2)/TimeSpan.TicksPerMillisecond + "ms"); + + byte[] req = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n\r\n"); + + Stream tlsStream = protocol.Stream; + tlsStream.Write(req, 0, req.Length); + tlsStream.Flush(); + + StreamReader reader = new StreamReader(tlsStream); + + String line; + while ((line = reader.ReadLine()) != null) + { + Console.WriteLine(">>> " + line); + } + + protocol.Close(); + } + + internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client) + { + TcpClient tcp = new TcpClient(hostname, port); + + TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom); + protocol.Connect(client); + return protocol; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs new file mode 100644 index 000000000..ba5b90c75 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + MockTlsClient client = new MockTlsClient(null); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockTlsServer server = new MockTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs new file mode 100644 index 000000000..b059bb2cb --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsPskProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + MockPskTlsClient client = new MockPskTlsClient(null); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockPskTlsServer server = new MockPskTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs new file mode 100644 index 000000000..32e126ff2 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsSrpProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + MockSrpTlsClient client = new MockSrpTlsClient(null, MockSrpTlsServer.TEST_IDENTITY, MockSrpTlsServer.TEST_PASSWORD); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockSrpTlsServer server = new MockSrpTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs new file mode 100644 index 000000000..4b0c12710 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs @@ -0,0 +1,164 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsTestCase + { + private static void CheckTlsVersion(ProtocolVersion version) + { + if (version != null && !version.IsTls) + throw new InvalidOperationException("Non-TLS version"); + } + + [Test, TestCaseSource(typeof(TlsTestSuite), "Suite")] + public void RunTest(TlsTestConfig config) + { + CheckTlsVersion(config.clientMinimumVersion); + CheckTlsVersion(config.clientOfferVersion); + CheckTlsVersion(config.serverMaximumVersion); + CheckTlsVersion(config.serverMinimumVersion); + + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + NetworkStream clientNet = new NetworkStream(clientPipe); + NetworkStream serverNet = new NetworkStream(serverPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNet, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNet, secureRandom); + + TlsTestClientImpl clientImpl = new TlsTestClientImpl(config); + TlsTestServerImpl serverImpl = new TlsTestServerImpl(config); + + Server server = new Server(this, serverProtocol, serverImpl); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + Exception caught = null; + try + { + clientProtocol.Connect(clientImpl); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + } + catch (Exception e) + { + caught = e; + LogException(caught); + } + + server.AllowExit(); + serverThread.Join(); + + Assert.IsTrue(clientNet.IsClosed, "Client Stream not closed"); + Assert.IsTrue(serverNet.IsClosed, "Server Stream not closed"); + + Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end"); + Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end"); + + Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description"); + Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description"); + + if (config.expectFatalAlertConnectionEnd == -1) + { + Assert.IsNull(caught, "Unexpected client exception"); + Assert.IsNull(server.mCaught, "Unexpected server exception"); + } + } + + protected virtual void LogException(Exception e) + { + if (TlsTestConfig.DEBUG) + { + Console.Error.WriteLine(e); + } + } + + internal class Server + { + protected readonly TlsTestCase mOuter; + protected readonly TlsServerProtocol mServerProtocol; + protected readonly TlsTestServerImpl mServerImpl; + + internal bool mCanExit = false; + internal Exception mCaught = null; + + internal Server(TlsTestCase outer, TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl) + { + this.mOuter = outer; + this.mServerProtocol = serverProtocol; + this.mServerImpl = serverImpl; + } + + internal void AllowExit() + { + lock (this) + { + mCanExit = true; + Monitor.PulseAll(this); + } + } + + public void Run() + { + try + { + mServerProtocol.Accept(mServerImpl); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception e) + { + mCaught = e; + mOuter.LogException(mCaught); + } + + WaitExit(); + } + + protected void WaitExit() + { + lock (this) + { + while (!mCanExit) + { + try + { + Monitor.Wait(this); + } + catch (ThreadInterruptedException) + { + } + } + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs new file mode 100644 index 000000000..48af9e0f8 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs @@ -0,0 +1,262 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestClientImpl + : DefaultTlsClient + { + protected readonly TlsTestConfig mConfig; + + protected int firstFatalAlertConnectionEnd = -1; + protected int firstFatalAlertDescription = -1; + + internal TlsTestClientImpl(TlsTestConfig config) + { + this.mConfig = config; + } + + internal int FirstFatalAlertConnectionEnd + { + get { return firstFatalAlertConnectionEnd; } + } + + internal int FirstFatalAlertDescription + { + get { return firstFatalAlertDescription; } + } + + public override ProtocolVersion ClientVersion + { + get + { + if (mConfig.clientOfferVersion != null) + { + return mConfig.clientOfferVersion; + } + + return base.ClientVersion; + } + } + + public override ProtocolVersion MinimumVersion + { + get + { + if (mConfig.clientMinimumVersion != null) + { + return mConfig.clientMinimumVersion; + } + + return base.MinimumVersion; + } + } + + public override bool IsFallback + { + get { return mConfig.clientFallback; } + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.client; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.server; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS client negotiated " + serverVersion); + } + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(this, mContext); + } + + protected virtual Certificate CorruptCertificate(Certificate cert) + { + X509CertificateStructure[] certList = cert.GetCertificateList(); + certList[0] = CorruptCertificateSignature(certList[0]); + return new Certificate(certList); + } + + protected virtual X509CertificateStructure CorruptCertificateSignature(X509CertificateStructure cert) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + v.Add(cert.TbsCertificate); + v.Add(cert.SignatureAlgorithm); + v.Add(CorruptBitString(cert.Signature)); + + return X509CertificateStructure.GetInstance(new DerSequence(v)); + } + + protected virtual DerBitString CorruptBitString(DerBitString bs) + { + return new DerBitString(CorruptBit(bs.GetBytes())); + } + + protected virtual byte[] CorruptBit(byte[] bs) + { + bs = Arrays.Clone(bs); + + // Flip a random bit + int bit = mContext.SecureRandom.Next(bs.Length << 3); + bs[bit >> 3] ^= (byte)(1 << (bit & 7)); + + return bs; + } + + internal class MyTlsAuthentication + : TlsAuthentication + { + private readonly TlsTestClientImpl mOuter; + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsTestClientImpl outer, TlsContext context) + { + this.mOuter = outer; + this.mContext = context; + } + + public virtual void NotifyServerCertificate(Certificate serverCertificate) + { + bool isEmpty = serverCertificate == null || serverCertificate.IsEmpty; + + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + + // TODO Cache test resources? + if (isEmpty || !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-dsa.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-ecdsa.pem")))) + { + throw new TlsFatalAlert(AlertDescription.bad_certificate); + } + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + } + + public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) + { + if (mOuter.mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE) + throw new InvalidOperationException(); + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE) + return null; + + byte[] certificateTypes = certificateRequest.CertificateTypes; + if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) + { + return null; + } + + TlsSignerCredentials signerCredentials = TlsTestUtilities.LoadSignerCredentials(mContext, + certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-client.pem", "x509-client-key.pem"); + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID) + { + return signerCredentials; + } + + return new MyTlsSignerCredentials(mOuter, signerCredentials); + } + }; + + internal class MyTlsSignerCredentials + : TlsSignerCredentials + { + private readonly TlsTestClientImpl mOuter; + private readonly TlsSignerCredentials mInner; + + internal MyTlsSignerCredentials(TlsTestClientImpl outer, TlsSignerCredentials inner) + { + this.mOuter = outer; + this.mInner = inner; + } + + public virtual byte[] GenerateCertificateSignature(byte[] hash) + { + byte[] sig = mInner.GenerateCertificateSignature(hash); + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_VERIFY) + { + sig = mOuter.CorruptBit(sig); + } + + return sig; + } + + public virtual Certificate Certificate + { + get + { + Certificate cert = mInner.Certificate; + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_CERT) + { + cert = mOuter.CorruptCertificate(cert); + } + + return cert; + } + } + + public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm + { + get { return mInner.SignatureAndHashAlgorithm; } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs new file mode 100644 index 000000000..0d1e7badb --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs @@ -0,0 +1,101 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class TlsTestConfig + { + public static readonly bool DEBUG = false; + + /** + * Client does not authenticate, ignores any certificate request + */ + public const int CLIENT_AUTH_NONE = 0; + + /** + * Client will authenticate if it receives a certificate request + */ + public const int CLIENT_AUTH_VALID = 1; + + /** + * Client will authenticate if it receives a certificate request, with an invalid certificate + */ + public const int CLIENT_AUTH_INVALID_CERT = 2; + + /** + * Client will authenticate if it receives a certificate request, with an invalid CertificateVerify signature + */ + public const int CLIENT_AUTH_INVALID_VERIFY = 3; + + /** + * Server will not request a client certificate + */ + public const int SERVER_CERT_REQ_NONE = 0; + + /** + * Server will request a client certificate but receiving one is optional + */ + public const int SERVER_CERT_REQ_OPTIONAL = 1; + + /** + * Server will request a client certificate and receiving one is mandatory + */ + public const int SERVER_CERT_REQ_MANDATORY = 2; + + /** + * Configures the client authentication behaviour of the test client. Use CLIENT_AUTH_* constants. + */ + public int clientAuth = CLIENT_AUTH_VALID; + + /** + * Configures the minimum protocol version the client will accept. If null, uses the library's default. + */ + public ProtocolVersion clientMinimumVersion = null; + + /** + * Configures the protocol version the client will offer. If null, uses the library's default. + */ + public ProtocolVersion clientOfferVersion = null; + + /** + * Configures whether the client will indicate version fallback via TLS_FALLBACK_SCSV. + */ + public bool clientFallback = false; + + /** + * Configures whether the test server will send a certificate request. + */ + public int serverCertReq = SERVER_CERT_REQ_OPTIONAL; + + /** + * Configures the maximum protocol version the server will accept. If null, uses the library's default. + */ + public ProtocolVersion serverMaximumVersion = null; + + /** + * Configures the minimum protocol version the server will accept. If null, uses the library's default. + */ + public ProtocolVersion serverMinimumVersion = null; + + /** + * Configures the connection end that a fatal alert is expected to be raised. Use ConnectionEnd.* constants. + */ + public int expectFatalAlertConnectionEnd = -1; + + /** + * Configures the type of fatal alert expected to be raised. Use AlertDescription.* constants. + */ + public int expectFatalAlertDescription = -1; + + public void ExpectClientFatalAlert(byte alertDescription) + { + this.expectFatalAlertConnectionEnd = ConnectionEnd.client; + this.expectFatalAlertDescription = alertDescription; + } + + public void ExpectServerFatalAlert(byte alertDescription) + { + this.expectFatalAlertConnectionEnd = ConnectionEnd.server; + this.expectFatalAlertDescription = alertDescription; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs new file mode 100644 index 000000000..152d5dbdc --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestServerImpl + : DefaultTlsServer + { + protected readonly TlsTestConfig mConfig; + + protected int firstFatalAlertConnectionEnd = -1; + protected int firstFatalAlertDescription = -1; + + internal TlsTestServerImpl(TlsTestConfig config) + { + this.mConfig = config; + } + + internal int FirstFatalAlertConnectionEnd + { + get { return firstFatalAlertConnectionEnd; } + } + + internal int FirstFatalAlertDescription + { + get { return firstFatalAlertDescription; } + } + + protected override ProtocolVersion MaximumVersion + { + get + { + if (mConfig.serverMaximumVersion != null) + { + return mConfig.serverMaximumVersion; + } + + return base.MaximumVersion; + } + } + + protected override ProtocolVersion MinimumVersion + { + get + { + if (mConfig.serverMinimumVersion != null) + { + return mConfig.serverMinimumVersion; + } + + return base.MinimumVersion; + } + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.server; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.client; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS server negotiated " + serverVersion); + } + + return serverVersion; + } + + public override CertificateRequest GetCertificateRequest() + { + if (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE) + { + return null; + } + + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + + IList serverSigAlgs = null; + if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) + { + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + } + + IList certificateAuthorities = new ArrayList(); + certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); + + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); + } + + public override void NotifyClientCertificate(Certificate clientCertificate) + { + bool isEmpty = (clientCertificate == null || clientCertificate.IsEmpty); + + if (isEmpty != (mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE)) + { + throw new InvalidOperationException(); + } + if (isEmpty && (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_MANDATORY)) + { + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + + X509CertificateStructure[] chain = clientCertificate.GetCertificateList(); + + // TODO Cache test resources? + if (!isEmpty && !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-dsa.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-ecdsa.pem")))) + { + throw new TlsFatalAlert(AlertDescription.bad_certificate); + } + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS server received client certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + } + + protected override TlsSignerCredentials GetDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa, + "x509-server-dsa.pem", "x509-server-key-dsa.pem"); + } + + protected override TlsSignerCredentials GetECDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.ecdsa, + "x509-server-ecdsa.pem", "x509-server-key-ecdsa.pem"); + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" }, + "x509-server-key.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs new file mode 100644 index 000000000..dfd09d06e --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class TlsTestSuite + { + // Make the access to constants less verbose + internal class C : TlsTestConfig {} + + public TlsTestSuite() + { + } + + public static IEnumerable Suite() + { + IList testSuite = new ArrayList(); + + AddFallbackTests(testSuite); + AddVersionTests(testSuite, ProtocolVersion.TLSv10); + AddVersionTests(testSuite, ProtocolVersion.TLSv11); + AddVersionTests(testSuite, ProtocolVersion.TLSv12); + + return testSuite; + } + + private static void AddFallbackTests(IList testSuite) + { + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientFallback = true; + + testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientOfferVersion = ProtocolVersion.TLSv11; + c.clientFallback = true; + c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); + + testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientOfferVersion = ProtocolVersion.TLSv11; + + testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + } + } + + private static void AddVersionTests(IList testSuite, ProtocolVersion version) + { + string prefix = version.ToString() + .Replace(" ", "") + .Replace("\\", "") + .Replace(".", "") + + "_"; + + { + TlsTestConfig c = CreateTlsTestConfig(version); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; + c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; + c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; + c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.serverCertReq = C.SERVER_CERT_REQ_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + } + } + + private static TlsTestConfig CreateTlsTestConfig(ProtocolVersion version) + { + TlsTestConfig c = new TlsTestConfig(); + c.clientMinimumVersion = ProtocolVersion.TLSv10; + c.clientOfferVersion = ProtocolVersion.TLSv12; + c.serverMaximumVersion = version; + c.serverMinimumVersion = ProtocolVersion.TLSv10; + return c; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs index 272dfd4fd..a76858ce6 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Globalization; using System.IO; using System.Text; @@ -89,6 +90,34 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm); } + internal static TlsSignerCredentials LoadSignerCredentials(TlsContext context, IList supportedSignatureAlgorithms, + byte signatureAlgorithm, string certResource, string keyResource) + { + /* + * TODO Note that this code fails to provide default value for the client supported + * algorithms if it wasn't sent. + */ + + SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; + if (supportedSignatureAlgorithms != null) + { + foreach (SignatureAndHashAlgorithm alg in supportedSignatureAlgorithms) + { + if (alg.Signature == signatureAlgorithm) + { + signatureAndHashAlgorithm = alg; + break; + } + } + + if (signatureAndHashAlgorithm == null) + return null; + } + + return LoadSignerCredentials(context, new String[]{ certResource, "x509-ca.pem" }, + keyResource, signatureAndHashAlgorithm); + } + internal static Certificate LoadCertificateChain(string[] resources) { X509CertificateStructure[] chain = new X509CertificateStructure[resources.Length]; diff --git a/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs new file mode 100644 index 000000000..b771ab7cf --- /dev/null +++ b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs @@ -0,0 +1,84 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class UnreliableDatagramTransport + : DatagramTransport + { + private readonly DatagramTransport transport; + private readonly Random random; + private readonly int percentPacketLossReceiving, percentPacketLossSending; + + public UnreliableDatagramTransport(DatagramTransport transport, Random random, + int percentPacketLossReceiving, int percentPacketLossSending) + { + if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100) + throw new ArgumentException("out of range", "percentPacketLossReceiving"); + if (percentPacketLossSending < 0 || percentPacketLossSending > 100) + throw new ArgumentException("out of range", "percentPacketLossSending"); + + this.transport = transport; + this.random = random; + this.percentPacketLossReceiving = percentPacketLossReceiving; + this.percentPacketLossSending = percentPacketLossSending; + } + + public virtual int GetReceiveLimit() + { + return transport.GetReceiveLimit(); + } + + public virtual int GetSendLimit() + { + return transport.GetSendLimit(); + } + + public virtual int Receive(byte[] buf, int off, int len, int waitMillis) + { + long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis; + for (;;) + { + int length = transport.Receive(buf, off, len, waitMillis); + if (length < 0 || !LostPacket(percentPacketLossReceiving)) + { + return length; + } + + Console.WriteLine("PACKET LOSS (" + length + " byte packet not received)"); + + long now = DateTimeUtilities.CurrentUnixMs(); + if (now >= endMillis) + { + return -1; + } + + waitMillis = (int)(endMillis - now); + } + } + + public virtual void Send(byte[] buf, int off, int len) + { + if (LostPacket(percentPacketLossSending)) + { + Console.WriteLine("PACKET LOSS (" + len + " byte packet not sent)"); + } + else + { + transport.Send(buf, off, len); + } + } + + public virtual void Close() + { + transport.Close(); + } + + private bool LostPacket(int percentPacketLoss) + { + return percentPacketLoss > 0 && random.Next(100) < percentPacketLoss; + } + } +} diff --git a/crypto/test/src/math/ec/test/AllTests.cs b/crypto/test/src/math/ec/test/AllTests.cs index d4c7dc768..3e014ffd2 100644 --- a/crypto/test/src/math/ec/test/AllTests.cs +++ b/crypto/test/src/math/ec/test/AllTests.cs @@ -7,22 +7,21 @@ namespace Org.BouncyCastle.Math.EC.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("EC Math tests"); - - suite.Add(new ECAlgorithmsTest()); - suite.Add(new ECPointTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("EC Math tests"); + suite.Add(new ECAlgorithmsTest()); + suite.Add(new ECPointTest()); + return suite; + } } } } diff --git a/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs index 6f2b50140..40cfe3774 100644 --- a/crypto/test/src/math/test/AllTests.cs +++ b/crypto/test/src/math/test/AllTests.cs @@ -7,21 +7,20 @@ namespace Org.BouncyCastle.Math.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("Math tests"); - - suite.Add(new BigIntegerTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("Math tests"); + suite.Add(new BigIntegerTest()); + return suite; + } } } } diff --git a/crypto/test/src/ocsp/test/AllTests.cs b/crypto/test/src/ocsp/test/AllTests.cs index 2b30e3ad4..5e919fd91 100644 --- a/crypto/test/src/ocsp/test/AllTests.cs +++ b/crypto/test/src/ocsp/test/AllTests.cs @@ -9,21 +9,20 @@ namespace Org.BouncyCastle.Ocsp.Tests { public class AllTests { - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - public static TestSuite suite() - { - TestSuite suite = new TestSuite("OCSP Tests"); - - suite.Add(new OcspTest()); - - return suite; - } + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OCSP Tests"); + suite.Add(new OcspTest()); + return suite; + } + } } } diff --git a/crypto/test/src/openpgp/examples/test/AllTests.cs b/crypto/test/src/openpgp/examples/test/AllTests.cs index 180d2fa80..e9a7a744d 100644 --- a/crypto/test/src/openpgp/examples/test/AllTests.cs +++ b/crypto/test/src/openpgp/examples/test/AllTests.cs @@ -382,22 +382,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests return bRd.ReadLine(); } - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); - } - - public static TestSuite suite() - { - TestSuite suite = new TestSuite("OpenPGP Example Tests"); - - suite.Add(new AllTests()); - - return suite; - } - + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } + + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OpenPGP Example Tests"); + suite.Add(new AllTests()); + return suite; + } + } } } diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs index 921208179..f843d0479 100644 --- a/crypto/test/src/openssl/test/AllTests.cs +++ b/crypto/test/src/openssl/test/AllTests.cs @@ -32,19 +32,24 @@ namespace Org.BouncyCastle.OpenSsl.Tests return (char[]) password.Clone(); } } - - [Suite] - public static TestSuite Suite - { - get - { - TestSuite suite = new TestSuite("OpenSSL Tests"); - suite.Add(new AllTests()); - return suite; - } - } - [Test] + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } + + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OpenSSL Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] public void TestOpenSsl() { Org.BouncyCastle.Utilities.Test.ITest[] tests = new Org.BouncyCastle.Utilities.Test.ITest[]{ @@ -121,13 +126,5 @@ namespace Org.BouncyCastle.OpenSsl.Tests Assert.AreEqual(privKey, rdKey); } - - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - Suite.Run(el); - } } } diff --git a/crypto/test/src/tsp/test/AllTests.cs b/crypto/test/src/tsp/test/AllTests.cs index 66dc9c480..3e8b0cd5e 100644 --- a/crypto/test/src/tsp/test/AllTests.cs +++ b/crypto/test/src/tsp/test/AllTests.cs @@ -9,24 +9,23 @@ namespace Org.BouncyCastle.Tsp.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("TSP Tests"); - - suite.Add(new GenTimeAccuracyUnitTest()); - suite.Add(new ParseTest()); - suite.Add(new TimeStampTokenInfoUnitTest()); - suite.Add(new TspTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("TSP Tests"); + suite.Add(new GenTimeAccuracyUnitTest()); + suite.Add(new ParseTest()); + suite.Add(new TimeStampTokenInfoUnitTest()); + suite.Add(new TspTest()); + return suite; + } } } } diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs index b44949383..c36f79304 100644 --- a/crypto/test/src/util/io/pem/test/AllTests.cs +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -19,18 +19,23 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests [TestFixture] public class AllTests { - [Suite] - public static TestSuite Suite - { - get - { - TestSuite suite = new TestSuite("PEM Utilities Tests"); - suite.Add(new AllTests()); - return suite; - } - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - [Test] + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("PEM Utilities Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] public void TestPemLength() { for (int i = 1; i != 60; i++) @@ -65,13 +70,5 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests Assert.AreEqual(sw.ToString().Length, pWrt.GetOutputSize(pemObj)); } - - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - Suite.Run(el); - } } } |