From ae227e65ab48b8747c80e1b336a3e6896e9e346e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 16 Dec 2015 22:50:41 +0700 Subject: Validate CertificateVerify signature algorithm (TLS 1.2+) - check the algorithm is in the CertificateRequest list - add (D)TLS test scenarios for various failure modes --- crypto/crypto.csproj | 20 ++++ crypto/src/crypto/tls/DeferredHash.cs | 2 +- crypto/src/crypto/tls/DtlsServerProtocol.cs | 23 ++-- crypto/src/crypto/tls/HashAlgorithm.cs | 28 +++++ crypto/src/crypto/tls/TlsServerProtocol.cs | 17 ++- crypto/src/crypto/tls/TlsUtilities.cs | 42 ++++++- crypto/test/UnitTests.csproj | 4 + crypto/test/src/crypto/tls/test/DtlsTestCase.cs | 9 +- .../src/crypto/tls/test/DtlsTestClientProtocol.cs | 28 +++++ .../src/crypto/tls/test/DtlsTestServerProtocol.cs | 18 +++ crypto/test/src/crypto/tls/test/DtlsTestSuite.cs | 122 +++++++++++++++------ crypto/test/src/crypto/tls/test/TlsTestCase.cs | 8 +- .../test/src/crypto/tls/test/TlsTestClientImpl.cs | 11 +- .../src/crypto/tls/test/TlsTestClientProtocol.cs | 29 +++++ crypto/test/src/crypto/tls/test/TlsTestConfig.cs | 19 ++++ .../test/src/crypto/tls/test/TlsTestServerImpl.cs | 27 ++++- .../src/crypto/tls/test/TlsTestServerProtocol.cs | 19 ++++ crypto/test/src/crypto/tls/test/TlsTestSuite.cs | 74 +++++++++++-- 18 files changed, 426 insertions(+), 74 deletions(-) create mode 100644 crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs create mode 100644 crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index e6ab94ee2..e4bd2e036 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11839,6 +11839,16 @@ SubType = "Code" BuildAction = "Compile" /> + + + + = (1 << 15)) - { + if (supportedSignatureAlgorithms == null) + throw new ArgumentNullException("supportedSignatureAlgorithms"); + if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15)) throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms"); - } // supported_signature_algorithms int length = 2 * supportedSignatureAlgorithms.Count; @@ -762,6 +771,27 @@ namespace Org.BouncyCastle.Crypto.Tls return supportedSignatureAlgorithms; } + public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm) + { + if (supportedSignatureAlgorithms == null) + throw new ArgumentNullException("supportedSignatureAlgorithms"); + if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15)) + throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms"); + if (signatureAlgorithm == null) + throw new ArgumentNullException("signatureAlgorithm"); + + if (signatureAlgorithm.Signature != SignatureAlgorithm.anonymous) + { + foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms) + { + if (entry.Hash == signatureAlgorithm.Hash && entry.Signature == signatureAlgorithm.Signature) + return; + } + } + + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size) { ProtocolVersion version = context.ServerVersion; diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 71896d203..24a60346e 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -277,6 +277,8 @@ + + @@ -299,8 +301,10 @@ + + diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs index d4af04fac..5e43337f4 100644 --- a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs +++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs @@ -28,8 +28,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests SecureRandom secureRandom = new SecureRandom(); - DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom); - DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom); + DtlsTestClientProtocol clientProtocol = new DtlsTestClientProtocol(secureRandom, config); + DtlsTestServerProtocol serverProtocol = new DtlsTestServerProtocol(secureRandom, config); MockDatagramAssociation network = new MockDatagramAssociation(1500); @@ -101,14 +101,15 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests internal class Server { private readonly DtlsTestCase mOuter; - private readonly DtlsServerProtocol mServerProtocol; + private readonly DtlsTestServerProtocol 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) + internal Server(DtlsTestCase outer, DtlsTestServerProtocol serverProtocol, + DatagramTransport serverTransport, TlsTestServerImpl serverImpl) { this.mOuter = outer; this.mServerProtocol = serverProtocol; diff --git a/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs b/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs new file mode 100644 index 000000000..41ed93eb0 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestClientProtocol.cs @@ -0,0 +1,28 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class DtlsTestClientProtocol + : DtlsClientProtocol + { + protected readonly TlsTestConfig config; + + public DtlsTestClientProtocol(SecureRandom secureRandom, TlsTestConfig config) + : base(secureRandom) + { + this.config = config; + } + + protected override byte[] GenerateCertificateVerify(ClientHandshakeState state, DigitallySigned certificateVerify) + { + if (certificateVerify.Algorithm != null && config.clientAuthSigAlgClaimed != null) + { + certificateVerify = new DigitallySigned(config.clientAuthSigAlgClaimed, certificateVerify.Signature); + } + + return base.GenerateCertificateVerify(state, certificateVerify); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs b/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs new file mode 100644 index 000000000..006473cef --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestServerProtocol.cs @@ -0,0 +1,18 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class DtlsTestServerProtocol + : DtlsServerProtocol + { + protected readonly TlsTestConfig config; + + public DtlsTestServerProtocol(SecureRandom secureRandom, TlsTestConfig config) + : base(secureRandom) + { + this.config = config; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs index eb9d42e5f..69ce36071 100644 --- a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs +++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs @@ -31,7 +31,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); c.clientFallback = true; - testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + AddTestCase(testSuite, c, "FallbackGood"); } /* @@ -40,20 +40,22 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests * alerts being raised */ - //{ - // TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); - // c.clientOfferVersion = ProtocolVersion.DTLSv10; - // c.clientFallback = true; - // c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); +#if false + { + TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + c.clientOfferVersion = ProtocolVersion.DTLSv10; + c.clientFallback = true; + c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); - // testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); - //} + AddTestCase(testSuite, c, "FallbackBad"); + } +#endif { TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); c.clientOfferVersion = ProtocolVersion.DTLSv10; - testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + AddTestCase(testSuite, c, "FallbackNone"); } } @@ -71,52 +73,110 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests * alerts being raised */ - //{ - // TlsTestConfig c = CreateDtlsTestConfig(version); - // c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; - // c.ExpectServerFatalAlert(AlertDescription.decrypt_error); +#if false + /* + * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is + * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms(); + c.ExpectClientFatalAlert(AlertDescription.internal_error); - // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); - //} + AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg"); + } - //{ - // TlsTestConfig c = CreateDtlsTestConfig(version); - // c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; - // c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + /* + * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is + * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server + * when it verifies the selected algorithm against the CertificateRequest supported + * algorithms. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.ExpectServerFatalAlert(AlertDescription.illegal_parameter); - // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); - //} + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg"); + } - //{ - // TlsTestConfig c = CreateDtlsTestConfig(version); - // c.clientAuth = C.CLIENT_AUTH_NONE; - // c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; - // c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + /* + * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends + * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the + * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms, + * we expect fatal alert to come from the server when it finds the claimed algorithm + * doesn't match the client certificate. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); + c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.ExpectServerFatalAlert(AlertDescription.decrypt_error); - // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); - //} + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch"); + } { TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; + c.ExpectServerFatalAlert(AlertDescription.decrypt_error); - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature"); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; + c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + + AddTestCase(testSuite, c, prefix + "BadClientCertificate"); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; + c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + + AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined"); + } +#endif + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + + AddTestCase(testSuite, c, prefix + "GoodDefault"); } { TlsTestConfig c = CreateDtlsTestConfig(version); c.serverCertReq = C.SERVER_CERT_REQ_NONE; - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + AddTestCase(testSuite, c, prefix + "GoodNoCertReq"); } { TlsTestConfig c = CreateDtlsTestConfig(version); c.clientAuth = C.CLIENT_AUTH_NONE; - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + AddTestCase(testSuite, c, prefix + "GoodOptionalCertReqDeclined"); } } + private static void AddTestCase(IList testSuite, TlsTestConfig config, String name) + { + testSuite.Add(new TestCaseData(config).SetName(name)); + } + private static TlsTestConfig CreateDtlsTestConfig(ProtocolVersion version) { TlsTestConfig c = new TlsTestConfig(); diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs index 4b0c12710..7fb5db6ce 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestCase.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs @@ -35,8 +35,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests NetworkStream clientNet = new NetworkStream(clientPipe); NetworkStream serverNet = new NetworkStream(serverPipe); - TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNet, secureRandom); - TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNet, secureRandom); + TlsTestClientProtocol clientProtocol = new TlsTestClientProtocol(clientNet, secureRandom, config); + TlsTestServerProtocol serverProtocol = new TlsTestServerProtocol(serverNet, secureRandom, config); TlsTestClientImpl clientImpl = new TlsTestClientImpl(config); TlsTestServerImpl serverImpl = new TlsTestServerImpl(config); @@ -104,13 +104,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests internal class Server { protected readonly TlsTestCase mOuter; - protected readonly TlsServerProtocol mServerProtocol; + protected readonly TlsTestServerProtocol mServerProtocol; protected readonly TlsTestServerImpl mServerImpl; internal bool mCanExit = false; internal Exception mCaught = null; - internal Server(TlsTestCase outer, TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl) + internal Server(TlsTestCase outer, TlsTestServerProtocol serverProtocol, TlsTestServerImpl serverImpl) { this.mOuter = outer; this.mServerProtocol = serverProtocol; diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs index 0cc1883ba..f313f75fe 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.IO; using Org.BouncyCastle.Asn1; @@ -201,9 +202,15 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests return null; } + IList supportedSigAlgs = certificateRequest.SupportedSignatureAlgorithms; + if (supportedSigAlgs != null && mOuter.mConfig.clientAuthSigAlg != null) + { + supportedSigAlgs = new ArrayList(1); + supportedSigAlgs.Add(mOuter.mConfig.clientAuthSigAlg); + } + TlsSignerCredentials signerCredentials = TlsTestUtilities.LoadSignerCredentials(mContext, - certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa, - "x509-client.pem", "x509-client-key.pem"); + supportedSigAlgs, SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem"); if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID) { diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs b/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs new file mode 100644 index 000000000..97b7c91bc --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestClientProtocol.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestClientProtocol + : TlsClientProtocol + { + protected readonly TlsTestConfig config; + + public TlsTestClientProtocol(Stream stream, SecureRandom secureRandom, TlsTestConfig config) + : base(stream, secureRandom) + { + this.config = config; + } + + protected override void SendCertificateVerifyMessage(DigitallySigned certificateVerify) + { + if (certificateVerify.Algorithm != null && config.clientAuthSigAlgClaimed != null) + { + certificateVerify = new DigitallySigned(config.clientAuthSigAlgClaimed, certificateVerify.Signature); + } + + base.SendCertificateVerifyMessage(certificateVerify); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs index 0d1e7badb..212d2b63c 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; namespace Org.BouncyCastle.Crypto.Tls.Tests { @@ -46,6 +47,18 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests */ public int clientAuth = CLIENT_AUTH_VALID; + /** + * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to + * be used for the CertificateVerify signature (if one is sent). + */ + public SignatureAndHashAlgorithm clientAuthSigAlg = null; + + /** + * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to + * be _claimed_ in the CertificateVerify (if one is sent), independently of what was actually used. + */ + public SignatureAndHashAlgorithm clientAuthSigAlgClaimed = null; + /** * Configures the minimum protocol version the client will accept. If null, uses the library's default. */ @@ -66,6 +79,12 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests */ public int serverCertReq = SERVER_CERT_REQ_OPTIONAL; + /** + * If TLS 1.2 or higher is negotiated, configures the set of supported signature algorithms in the + * CertificateRequest (if one is sent). If null, uses a default set. + */ + public IList serverCertReqSigAlgs = null; + /** * Configures the maximum protocol version the server will accept. If null, uses the library's default. */ diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs index 152d5dbdc..6f9d35b5c 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.IO; +using System.Threading; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.X509; @@ -72,11 +73,11 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests + ", " + AlertDescription.GetText(alertDescription)); if (message != null) { - output.WriteLine("> " + message); + SafeWriteLine(output, "> " + message); } if (cause != null) { - output.WriteLine(cause); + SafeWriteLine(output, cause); } } } @@ -92,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests if (TlsTestConfig.DEBUG) { TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; - output.WriteLine("TLS server received alert: " + AlertLevel.GetText(alertLevel) + SafeWriteLine(output, "TLS server received alert: " + AlertLevel.GetText(alertLevel) + ", " + AlertDescription.GetText(alertDescription)); } } @@ -122,7 +123,11 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests IList serverSigAlgs = null; if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) { - serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + serverSigAlgs = mConfig.serverCertReqSigAlgs; + if (serverSigAlgs == null) + { + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + } } IList certificateAuthorities = new ArrayList(); @@ -190,5 +195,19 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, "x509-server.pem", "x509-server-key.pem"); } + + private static void SafeWriteLine(TextWriter output, object line) + { + try + { + output.WriteLine(line); + } + catch (ThreadInterruptedException) + { + /* + * For some reason the NUnit plugin in Visual Studio started throwing these during alert logging + */ + } + } } } diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs b/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs new file mode 100644 index 000000000..845b7f0b9 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestServerProtocol.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestServerProtocol + : TlsServerProtocol + { + protected readonly TlsTestConfig config; + + public TlsTestServerProtocol(Stream stream, SecureRandom secureRandom, TlsTestConfig config) + : base(stream, secureRandom) + { + this.config = config; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs index dfd09d06e..0770187d5 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); c.clientFallback = true; - testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + AddTestCase(testSuite, c, "FallbackGood"); } { @@ -41,14 +41,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests c.clientFallback = true; c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); - testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); + AddTestCase(testSuite, c, "FallbackBad"); } { TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); c.clientOfferVersion = ProtocolVersion.TLSv11; - testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + AddTestCase(testSuite, c, "FallbackNone"); } } @@ -63,7 +63,58 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { TlsTestConfig c = CreateTlsTestConfig(version); - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + AddTestCase(testSuite, c, prefix + "GoodDefault"); + } + + /* + * Server only declares support for SHA1/RSA, client selects MD5/RSA. Since the client is + * NOT actually tracking MD5 over the handshake, we expect fatal alert from the client. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultRsaSignatureAlgorithms(); + c.ExpectClientFatalAlert(AlertDescription.internal_error); + + AddTestCase(testSuite, c, prefix + "BadCertificateVerifyHashAlg"); + } + + /* + * Server only declares support for SHA1/ECDSA, client selects SHA1/RSA. Since the client is + * actually tracking SHA1 over the handshake, we expect fatal alert to come from the server + * when it verifies the selected algorithm against the CertificateRequest supported + * algorithms. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.ExpectServerFatalAlert(AlertDescription.illegal_parameter); + + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlg"); + } + + /* + * Server only declares support for SHA1/ECDSA, client signs with SHA1/RSA, but sends + * SHA1/ECDSA in the CertificateVerify. Since the client is actually tracking SHA1 over the + * handshake, and the claimed algorithm is in the CertificateRequest supported algorithms, + * we expect fatal alert to come from the server when it finds the claimed algorithm + * doesn't match the client certificate. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_VALID; + c.clientAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa); + c.clientAuthSigAlgClaimed = new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa); + c.serverCertReqSigAlgs = TlsUtilities.GetDefaultECDsaSignatureAlgorithms(); + c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySigAlgMismatch"); } { @@ -71,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; c.ExpectServerFatalAlert(AlertDescription.decrypt_error); - testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); + AddTestCase(testSuite, c, prefix + "BadCertificateVerifySignature"); } { @@ -79,7 +130,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; c.ExpectServerFatalAlert(AlertDescription.bad_certificate); - testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); + AddTestCase(testSuite, c, prefix + "BadClientCertificate"); } { @@ -88,24 +139,29 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; c.ExpectServerFatalAlert(AlertDescription.handshake_failure); - testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); + AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined"); } { TlsTestConfig c = CreateTlsTestConfig(version); c.serverCertReq = C.SERVER_CERT_REQ_NONE; - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + AddTestCase(testSuite, c, prefix + "GoodNoCertReq"); } { TlsTestConfig c = CreateTlsTestConfig(version); c.clientAuth = C.CLIENT_AUTH_NONE; - testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + AddTestCase(testSuite, c, prefix + "GoodOptionalCertReqDeclined"); } } + private static void AddTestCase(IList testSuite, TlsTestConfig config, string name) + { + testSuite.Add(new TestCaseData(config).SetName(name)); + } + private static TlsTestConfig CreateTlsTestConfig(ProtocolVersion version) { TlsTestConfig c = new TlsTestConfig(); -- cgit 1.5.1 From 1175209f51004a66b46ca92d14a9339e9e3e5972 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 16 Dec 2015 23:09:12 +0700 Subject: Validate ServerKeyExchange signature algorithm (TLS 1.2+) - check the algorithm is in signature_algorithms (or the implicit defaults if that extension was not sent) - add (D)TLS test scenarios to cover these checks --- crypto/src/crypto/tls/AbstractTlsKeyExchange.cs | 11 +++++++ crypto/src/crypto/tls/TlsDheKeyExchange.cs | 2 +- crypto/src/crypto/tls/TlsECDheKeyExchange.cs | 2 +- crypto/src/crypto/tls/TlsSrpKeyExchange.cs | 2 +- crypto/test/src/crypto/tls/test/DtlsTestSuite.cs | 34 ++++++++++++++++++++++ .../test/src/crypto/tls/test/TlsTestClientImpl.cs | 11 +++++++ crypto/test/src/crypto/tls/test/TlsTestConfig.cs | 11 +++++++ .../test/src/crypto/tls/test/TlsTestServerImpl.cs | 18 ++++++++++-- crypto/test/src/crypto/tls/test/TlsTestSuite.cs | 29 ++++++++++++++++++ 9 files changed, 114 insertions(+), 6 deletions(-) diff --git a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs index c9ec06107..09fb8782d 100644 --- a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs +++ b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs @@ -18,6 +18,17 @@ namespace Org.BouncyCastle.Crypto.Tls this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms; } + protected virtual DigitallySigned ParseSignature(Stream input) + { + DigitallySigned signature = DigitallySigned.Parse(mContext, input); + SignatureAndHashAlgorithm signatureAlgorithm = signature.Algorithm; + if (signatureAlgorithm != null) + { + TlsUtilities.VerifySupportedSignatureAlgorithm(mSupportedSignatureAlgorithms, signatureAlgorithm); + } + return signature; + } + public virtual void Init(TlsContext context) { this.mContext = context; diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index 9831e8cd7..cdd629247 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Tls ServerDHParams dhParams = ServerDHParams.Parse(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs index b681aada3..e0553b3f0 100644 --- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs @@ -73,7 +73,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] point = TlsUtilities.ReadOpaque8(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs index ce8e4834a..09fa72348 100644 --- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs @@ -189,7 +189,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (buf != null) { - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs index 69ce36071..e9e4411af 100644 --- a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs +++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs @@ -149,6 +149,35 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined"); } + + /* + * Server selects MD5/RSA for ServerKeyExchange signature, which is not in the default + * supported signature algorithms that the client sent. We expect fatal alert from the + * client when it verifies the selected algorithm against the supported algorithms. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.ExpectClientFatalAlert(AlertDescription.illegal_parameter); + + AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg"); + } + + /* + * Server selects MD5/RSA for ServerKeyExchange signature, which is not the default {sha1,rsa} + * implied by the absent signature_algorithms extension. We expect fatal alert from the + * client when it verifies the selected algorithm against the implicit default. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientSendSignatureAlgorithms = false; + c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.ExpectClientFatalAlert(AlertDescription.illegal_parameter); + + AddTestCaseDebug(testSuite, c, prefix + "BadServerKeyExchangeSigAlg2"); + } #endif { @@ -173,6 +202,11 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests } private static void AddTestCase(IList testSuite, TlsTestConfig config, String name) + { + //testSuite.Add(new TestCaseData(config).SetName(name)); + } + + private static void AddTestCaseDebug(IList testSuite, TlsTestConfig config, String name) { testSuite.Add(new TestCaseData(config).SetName(name)); } diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs index f313f75fe..864a0a5cc 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs @@ -57,6 +57,17 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests } } + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = base.GetClientExtensions(); + if (clientExtensions != null && !mConfig.clientSendSignatureAlgorithms) + { + clientExtensions.Remove(ExtensionType.signature_algorithms); + this.mSupportedSignatureAlgorithms = null; + } + return clientExtensions; + } + public override bool IsFallback { get { return mConfig.clientFallback; } diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs index 212d2b63c..ccbb919d2 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs @@ -74,6 +74,17 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests */ public bool clientFallback = false; + /** + * Configures whether a (TLS 1.2+) client will send the signature_algorithms extension in ClientHello. + */ + public bool clientSendSignatureAlgorithms = true; + + /** + * If not null, and TLS 1.2 or higher is negotiated, selects a fixed signature/hash algorithm to + * be used for the ServerKeyExchange signature (if one is sent). + */ + public SignatureAndHashAlgorithm serverAuthSigAlg = null; + /** * Configures whether the test server will send a certificate request. */ diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs index 6f9d35b5c..9edd2e524 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs @@ -172,15 +172,27 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests } } + protected virtual IList GetSupportedSignatureAlgorithms() + { + if (TlsUtilities.IsTlsV12(mContext) && mConfig.serverAuthSigAlg != null) + { + IList signatureAlgorithms = new ArrayList(1); + signatureAlgorithms.Add(mConfig.serverAuthSigAlg); + return signatureAlgorithms; + } + + return mSupportedSignatureAlgorithms; + } + protected override TlsSignerCredentials GetDsaSignerCredentials() { - return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa, + return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), SignatureAlgorithm.dsa, "x509-server-dsa.pem", "x509-server-key-dsa.pem"); } protected override TlsSignerCredentials GetECDsaSignerCredentials() { - return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.ecdsa, + return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), SignatureAlgorithm.ecdsa, "x509-server-ecdsa.pem", "x509-server-key-ecdsa.pem"); } @@ -192,7 +204,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests protected override TlsSignerCredentials GetRsaSignerCredentials() { - return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + return TlsTestUtilities.LoadSignerCredentials(mContext, GetSupportedSignatureAlgorithms(), 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 index 0770187d5..77cebe0a6 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs @@ -142,6 +142,35 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests AddTestCase(testSuite, c, prefix + "BadMandatoryCertReqDeclined"); } + /* + * Server selects MD5/RSA for ServerKeyExchange signature, which is not in the default + * supported signature algorithms that the client sent. We expect fatal alert from the + * client when it verifies the selected algorithm against the supported algorithms. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.ExpectClientFatalAlert(AlertDescription.illegal_parameter); + + AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg"); + } + + /* + * Server selects MD5/RSA for ServerKeyExchange signature, which is not the default {sha1,rsa} + * implied by the absent signature_algorithms extension. We expect fatal alert from the + * client when it verifies the selected algorithm against the implicit default. + */ + if (TlsUtilities.IsTlsV12(version)) + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientSendSignatureAlgorithms = false; + c.serverAuthSigAlg = new SignatureAndHashAlgorithm(HashAlgorithm.md5, SignatureAlgorithm.rsa); + c.ExpectClientFatalAlert(AlertDescription.illegal_parameter); + + AddTestCase(testSuite, c, prefix + "BadServerKeyExchangeSigAlg2"); + } + { TlsTestConfig c = CreateTlsTestConfig(version); c.serverCertReq = C.SERVER_CERT_REQ_NONE; -- cgit 1.5.1 From 98f46b1c9e71acb14fe3b7f91711a5557f1fee1f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 17 Dec 2015 14:59:21 +0700 Subject: Add .userprefs to ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3b2c97a3b..bc7a62d4b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.suo *.swp *.user +*.userprefs *.vsp *.nupkg -- cgit 1.5.1 From 67acfffc68a2483dc3ca48a3a95fa132d6910107 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 18 Dec 2015 14:37:17 +0700 Subject: Check CertificateRequest syntax server-side --- crypto/src/crypto/tls/DtlsServerProtocol.cs | 3 +++ crypto/src/crypto/tls/TlsServerProtocol.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs index e2e9eddfc..c556d6320 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs @@ -156,6 +156,9 @@ namespace Org.BouncyCastle.Crypto.Tls state.certificateRequest = state.server.GetCertificateRequest(); if (state.certificateRequest != null) { + if (TlsUtilities.IsTlsV12(state.serverContext) != (state.certificateRequest.SupportedSignatureAlgorithms != null)) + throw new TlsFatalAlert(AlertDescription.internal_error); + state.keyExchange.ValidateCertificateRequest(state.certificateRequest); byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest); diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index 5716c0cd1..1b790c9e0 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -200,6 +200,9 @@ namespace Org.BouncyCastle.Crypto.Tls this.mCertificateRequest = mTlsServer.GetCertificateRequest(); if (this.mCertificateRequest != null) { + if (TlsUtilities.IsTlsV12(Context) != (mCertificateRequest.SupportedSignatureAlgorithms != null)) + throw new TlsFatalAlert(AlertDescription.internal_error); + this.mKeyExchange.ValidateCertificateRequest(mCertificateRequest); SendCertificateRequestMessage(mCertificateRequest); -- cgit 1.5.1 From 9d2816f7c430dc4fcf26b2940e3c5aa1a5aefcd7 Mon Sep 17 00:00:00 2001 From: David Hook Date: Sat, 19 Dec 2015 10:11:53 +1100 Subject: Added support for fixed salt. --- crypto/src/crypto/signers/PssSigner.cs | 46 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index 03890902b..61e7dae01 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -25,6 +25,7 @@ namespace Org.BouncyCastle.Crypto.Signers private int hLen; private int mgfhLen; private int sLen; + private bool sSet; private int emBits; private byte[] salt; private byte[] mDash; @@ -35,7 +36,7 @@ namespace Org.BouncyCastle.Crypto.Signers IAsymmetricBlockCipher cipher, IDigest digest) { - return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), TrailerImplicit); + return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), null, TrailerImplicit); } public static PssSigner CreateRawSigner( @@ -45,7 +46,7 @@ namespace Org.BouncyCastle.Crypto.Signers int saltLen, byte trailer) { - return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, trailer); + return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, null, trailer); } public PssSigner( @@ -67,7 +68,19 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public PssSigner( + /// Basic constructor + /// the asymmetric cipher to use. + /// the digest to use. + /// the fixed salt to be used. + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + byte[] salt) + : this(cipher, digest, digest, digest, salt.Length, salt, TrailerImplicit) + { + } + + public PssSigner( IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest, @@ -91,7 +104,7 @@ namespace Org.BouncyCastle.Crypto.Signers IDigest mgfDigest, int saltLen, byte trailer) - : this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, trailer) + : this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, null, trailer) { } @@ -101,6 +114,7 @@ namespace Org.BouncyCastle.Crypto.Signers IDigest contentDigest2, IDigest mgfDigest, int saltLen, + byte[] salt, byte trailer) { this.cipher = cipher; @@ -110,7 +124,15 @@ namespace Org.BouncyCastle.Crypto.Signers this.hLen = contentDigest2.GetDigestSize(); this.mgfhLen = mgfDigest.GetDigestSize(); this.sLen = saltLen; - this.salt = new byte[saltLen]; + this.sSet = salt != null; + if (sSet) + { + this.salt = salt; + } + else + { + this.salt = new byte[saltLen]; + } this.mDash = new byte[8 + saltLen + hLen]; this.trailer = trailer; } @@ -197,7 +219,10 @@ namespace Org.BouncyCastle.Crypto.Signers if (sLen != 0) { - random.NextBytes(salt); + if (!sSet) + { + random.NextBytes(salt); + } salt.CopyTo(mDash, mDash.Length - sLen); } @@ -270,7 +295,14 @@ namespace Org.BouncyCastle.Crypto.Signers return false; } - Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen); + if (sSet) + { + Array.Copy(salt, 0, mDash, mDash.Length - sLen, sLen); + } + else + { + Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen); + } contentDigest2.BlockUpdate(mDash, 0, mDash.Length); contentDigest2.DoFinal(mDash, mDash.Length - hLen); -- cgit 1.5.1 From 0b4afcc3e4f3804562294b71265edd2ac2f00f9c Mon Sep 17 00:00:00 2001 From: David Hook Date: Sat, 19 Dec 2015 10:36:47 +1100 Subject: Added test against fixed salt. --- crypto/src/crypto/signers/PssSigner.cs | 11 +++++++++- crypto/test/src/crypto/test/PSSTest.cs | 38 +++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index 61e7dae01..23b7c0f49 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -89,7 +89,16 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public PssSigner( + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest, + IDigest mgfDigest, + byte[] salt) + : this(cipher, contentDigest, contentDigest, mgfDigest, salt.Length, salt, TrailerImplicit) + { + } + + public PssSigner( IAsymmetricBlockCipher cipher, IDigest digest, int saltLen, diff --git a/crypto/test/src/crypto/test/PSSTest.cs b/crypto/test/src/crypto/test/PSSTest.cs index 91d8d3a6e..8578d254f 100644 --- a/crypto/test/src/crypto/test/PSSTest.cs +++ b/crypto/test/src/crypto/test/PSSTest.cs @@ -319,9 +319,45 @@ namespace Org.BouncyCastle.Crypto.Tests { Fail("loop test failed - failures: " + failed); } + + fixedSaltTest(); } - public static void Main( + private void fixedSaltTest() + { + byte[] data = Hex.Decode("010203040506070809101112131415"); + + PssSigner eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("deadbeef")); + + eng.Init(true, prv8); + + eng.BlockUpdate(data, 0, data.Length); + + byte[] s = eng.GenerateSignature(); + + eng.Init(false, pub8); + + eng.BlockUpdate(data, 0, data.Length); + + if (!eng.VerifySignature(s)) + { + Fail("fixed salt failed"); + } + + // test failure + eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("beefbeef")); + + eng.Init(false, pub8); + + eng.BlockUpdate(data, 0, data.Length); + + if (eng.VerifySignature(s)) + { + Fail("fixed salt failure verfied"); + } + } + + public static void Main( string[] args) { RunTest(new PssTest()); -- cgit 1.5.1 From 9edba71a655a0df5f39e1cef3632bb9561bae6ae Mon Sep 17 00:00:00 2001 From: David Hook Date: Sat, 19 Dec 2015 11:08:12 +1100 Subject: Added use of standard salt if provided. --- crypto/src/crypto/signers/Iso9796d2PssSigner.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs index fb117c19d..3aa2e3719 100644 --- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs @@ -486,7 +486,14 @@ namespace Org.BouncyCastle.Crypto.Signers digest.BlockUpdate(m2Hash, 0, m2Hash.Length); // Update for the salt - digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength); + if (standardSalt != null) + { + digest.BlockUpdate(standardSalt, 0, standardSalt.Length); + } + else + { + digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength); + } byte[] hash = new byte[digest.GetDigestSize()]; digest.DoFinal(hash, 0); -- cgit 1.5.1 From 2e91027902f5293f34127b787aa5de74f6849a4f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 21 Dec 2015 19:47:41 +0700 Subject: BJA-584 Fix DTLS record-layer version handling - Also https://github.com/bcgit/bc-java/pull/111 --- crypto/src/crypto/tls/DtlsClientProtocol.cs | 11 +++++++-- crypto/src/crypto/tls/DtlsRecordLayer.cs | 30 ++++++++++++++--------- crypto/src/crypto/tls/DtlsServerProtocol.cs | 12 ++++----- crypto/test/src/crypto/tls/test/DtlsTestSuite.cs | 11 +-------- crypto/test/src/crypto/tls/test/MockDtlsClient.cs | 9 +++++-- crypto/test/src/crypto/tls/test/MockTlsClient.cs | 9 +++++-- 6 files changed, 49 insertions(+), 33 deletions(-) diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs index 411e7cca2..7cb554ae8 100644 --- a/crypto/src/crypto/tls/DtlsClientProtocol.cs +++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs @@ -74,13 +74,16 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.clientContext, recordLayer); byte[] clientHelloBody = GenerateClientHello(state, state.client); + + recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10); + handshake.SendMessage(HandshakeType.client_hello, clientHelloBody); DtlsReliableHandshake.Message serverMessage = handshake.ReceiveMessage(); while (serverMessage.Type == HandshakeType.hello_verify_request) { - ProtocolVersion recordLayerVersion = recordLayer.ResetDiscoveredPeerVersion(); + ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; ProtocolVersion client_version = state.clientContext.ClientVersion; /* @@ -92,6 +95,8 @@ namespace Org.BouncyCastle.Crypto.Tls if (!recordLayerVersion.IsEqualOrEarlierVersionOf(client_version)) throw new TlsFatalAlert(AlertDescription.illegal_parameter); + recordLayer.ReadVersion = null; + byte[] cookie = ProcessHelloVerifyRequest(state, serverMessage.Body); byte[] patched = PatchClientHelloWithCookie(clientHelloBody, cookie); @@ -103,7 +108,9 @@ namespace Org.BouncyCastle.Crypto.Tls if (serverMessage.Type == HandshakeType.server_hello) { - ReportServerVersion(state, recordLayer.DiscoveredPeerVersion); + ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; + ReportServerVersion(state, recordLayerVersion); + recordLayer.SetWriteVersion(recordLayerVersion); ProcessServerHello(state, serverMessage.Body); } diff --git a/crypto/src/crypto/tls/DtlsRecordLayer.cs b/crypto/src/crypto/tls/DtlsRecordLayer.cs index 70befd9e4..6796f4cbb 100644 --- a/crypto/src/crypto/tls/DtlsRecordLayer.cs +++ b/crypto/src/crypto/tls/DtlsRecordLayer.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls private volatile bool mClosed = false; private volatile bool mFailed = false; - private volatile ProtocolVersion mDiscoveredPeerVersion = null; + private volatile ProtocolVersion mReadVersion = null, mWriteVersion = null; private volatile bool mInHandshake; private volatile int mPlaintextLimit; private DtlsEpoch mCurrentEpoch, mPendingEpoch; @@ -52,16 +52,15 @@ namespace Org.BouncyCastle.Crypto.Tls this.mPlaintextLimit = plaintextLimit; } - internal virtual ProtocolVersion DiscoveredPeerVersion + internal virtual ProtocolVersion ReadVersion { - get { return mDiscoveredPeerVersion; } + get { return mReadVersion; } + set { this.mReadVersion = value; } } - internal virtual ProtocolVersion ResetDiscoveredPeerVersion() + internal virtual void SetWriteVersion(ProtocolVersion writeVersion) { - ProtocolVersion result = mDiscoveredPeerVersion; - mDiscoveredPeerVersion = null; - return result; + this.mWriteVersion = writeVersion; } internal virtual void InitPendingEpoch(TlsCipher pendingCipher) @@ -199,7 +198,12 @@ namespace Org.BouncyCastle.Crypto.Tls } ProtocolVersion version = TlsUtilities.ReadVersion(record, 1); - if (mDiscoveredPeerVersion != null && !mDiscoveredPeerVersion.Equals(version)) + if (!version.IsDtls) + { + continue; + } + + if (mReadVersion != null && !mReadVersion.Equals(version)) { continue; } @@ -215,9 +219,9 @@ namespace Org.BouncyCastle.Crypto.Tls continue; } - if (mDiscoveredPeerVersion == null) + if (mReadVersion == null) { - mDiscoveredPeerVersion = version; + mReadVersion = version; } switch (type) @@ -469,6 +473,10 @@ namespace Org.BouncyCastle.Crypto.Tls private void SendRecord(byte contentType, byte[] buf, int off, int len) { + // Never send anything until a valid ClientHello has been received + if (mWriteVersion == null) + return; + if (len > this.mPlaintextLimit) throw new TlsFatalAlert(AlertDescription.internal_error); @@ -489,7 +497,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] record = new byte[ciphertext.Length + RECORD_HEADER_LENGTH]; TlsUtilities.WriteUint8(contentType, record, 0); - ProtocolVersion version = mDiscoveredPeerVersion != null ? mDiscoveredPeerVersion : mContext.ClientVersion; + ProtocolVersion version = mWriteVersion; TlsUtilities.WriteVersion(version, record, 1); TlsUtilities.WriteUint16(recordEpoch, record, 3); TlsUtilities.WriteUint48(recordSequenceNumber, record, 5); diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs index c556d6320..171984b6f 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs @@ -76,12 +76,8 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsReliableHandshake.Message clientMessage = handshake.ReceiveMessage(); - { - // NOTE: After receiving a record from the client, we discover the record layer version - ProtocolVersion client_version = recordLayer.DiscoveredPeerVersion; - // TODO Read RFCs for guidance on the expected record layer version number - state.serverContext.SetClientVersion(client_version); - } + // NOTE: DTLSRecordLayer requires any DTLS version, we don't otherwise constrain this + //ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; if (clientMessage.Type == HandshakeType.client_hello) { @@ -97,6 +93,10 @@ namespace Org.BouncyCastle.Crypto.Tls ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); + ProtocolVersion recordLayerVersion = state.serverContext.ServerVersion; + recordLayer.ReadVersion = recordLayerVersion; + recordLayer.SetWriteVersion(recordLayerVersion); + handshake.SendMessage(HandshakeType.server_hello, serverHelloBody); } diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs index e9e4411af..a1ba62dde 100644 --- a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs +++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs @@ -202,11 +202,6 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests } private static void AddTestCase(IList testSuite, TlsTestConfig config, String name) - { - //testSuite.Add(new TestCaseData(config).SetName(name)); - } - - private static void AddTestCaseDebug(IList testSuite, TlsTestConfig config, String name) { testSuite.Add(new TestCaseData(config).SetName(name)); } @@ -215,11 +210,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { 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.clientOfferVersion = ProtocolVersion.DTLSv12; c.serverMaximumVersion = version; c.serverMinimumVersion = ProtocolVersion.DTLSv10; return c; diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs index e3c604db7..25057b8ce 100644 --- a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs @@ -73,8 +73,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); - TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); - TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + { + /* + * NOTE: If you are copying test code, do not blindly set these extensions in your own client. + */ + TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); + TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + } return clientExtensions; } diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index 7c1198632..35c5b3599 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -63,8 +63,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); - TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); - TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + { + /* + * NOTE: If you are copying test code, do not blindly set these extensions in your own client. + */ + TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); + TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + } return clientExtensions; } -- cgit 1.5.1 From d23f5025d8281432258b906ab07dcf96db37703f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 25 Dec 2015 00:23:52 +0700 Subject: Fix VmpcMac to actually use offset in BlockUpdate() - https://github.com/bcgit/bc-java/issues/127 --- crypto/src/crypto/macs/VMPCMac.cs | 2 +- crypto/test/src/crypto/test/VMPCMacTest.cs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crypto/src/crypto/macs/VMPCMac.cs b/crypto/src/crypto/macs/VMPCMac.cs index 89916355c..6f2da075c 100644 --- a/crypto/src/crypto/macs/VMPCMac.cs +++ b/crypto/src/crypto/macs/VMPCMac.cs @@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Macs for (int i = 0; i < len; i++) { - Update(input[i]); + Update(input[inOff + i]); } } } diff --git a/crypto/test/src/crypto/test/VMPCMacTest.cs b/crypto/test/src/crypto/test/VMPCMacTest.cs index 0ddb5506f..b9a5e3a93 100644 --- a/crypto/test/src/crypto/test/VMPCMacTest.cs +++ b/crypto/test/src/crypto/test/VMPCMacTest.cs @@ -35,16 +35,17 @@ namespace Org.BouncyCastle.Crypto.Tests ICipherParameters kpwiv = new ParametersWithIV(kp, Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155")); - byte[] m = new byte[256]; + int offset = 117; + byte[] m = new byte[512]; for (int i = 0; i < 256; i++) { - m[i] = (byte) i; + m[offset + i] = (byte)i; } - VmpcMac mac = new VmpcMac(); + VmpcMac mac = new VmpcMac(); mac.Init(kpwiv); - mac.BlockUpdate(m, 0, m.Length); + mac.BlockUpdate(m, offset, 256); byte[] output = new byte[20]; mac.DoFinal(output, 0); @@ -57,7 +58,7 @@ namespace Org.BouncyCastle.Crypto.Tests } } - [Test] + [Test] public void TestFunction() { string resultText = Perform().ToString(); -- cgit 1.5.1 From ca836115b48bd3b78312b2a5c88370ff7ef9d338 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 28 Dec 2015 12:25:40 +0700 Subject: XML doc for TlsClient.ClientHelloRecordLayerVersion --- crypto/src/crypto/tls/AbstractTlsClient.cs | 11 ++--------- crypto/src/crypto/tls/TlsClient.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs index 046feb78c..fedca0934 100644 --- a/crypto/src/crypto/tls/AbstractTlsClient.cs +++ b/crypto/src/crypto/tls/AbstractTlsClient.cs @@ -66,22 +66,15 @@ namespace Org.BouncyCastle.Crypto.Tls return null; } - /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value - * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest - * version number supported by the client, and the value of ClientHello.client_version. No - * single value will guarantee interoperability with all old servers, but this is a complex - * topic beyond the scope of this document." - */ public virtual ProtocolVersion ClientHelloRecordLayerVersion { get { // "{03,00}" - // return ProtocolVersion.SSLv3; + //return ProtocolVersion.SSLv3; // "the lowest version number supported by the client" - // return getMinimumVersion(); + //return MinimumVersion; // "the value of ClientHello.client_version" return ClientVersion; diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs index 116f6a779..73f169054 100644 --- a/crypto/src/crypto/tls/TlsClient.cs +++ b/crypto/src/crypto/tls/TlsClient.cs @@ -23,6 +23,18 @@ namespace Org.BouncyCastle.Crypto.Tls /// TlsSession GetSessionToResume(); + /// + /// Return the to use for the TLSPlaintext.version field prior to + /// receiving the server version. NOTE: This method is not called for DTLS. + /// + /// + /// See RFC 5246 E.1.: "TLS clients that wish to negotiate with older servers MAY send any value + /// {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest + /// version number supported by the client, and the value of ClientHello.client_version. No + /// single value will guarantee interoperability with all old servers, but this is a complex + /// topic beyond the scope of this document." + /// + /// The to use. ProtocolVersion ClientHelloRecordLayerVersion { get; } ProtocolVersion ClientVersion { get; } -- cgit 1.5.1 From 125e93ac90fab535316f55695f14dde8e9c76c97 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 28 Dec 2015 14:59:52 +0700 Subject: Optimized Sqrt and Trace for custom binary curves --- crypto/src/math/ec/custom/sec/SecT113Field.cs | 16 +++++++++ .../src/math/ec/custom/sec/SecT113FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT131Field.cs | 27 ++++++++++++++ .../src/math/ec/custom/sec/SecT131FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT163Field.cs | 27 ++++++++++++++ .../src/math/ec/custom/sec/SecT163FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT193Field.cs | 23 ++++++++++++ .../src/math/ec/custom/sec/SecT193FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT233Field.cs | 41 +++++++++++++++++++++ .../src/math/ec/custom/sec/SecT233FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT239Field.cs | 42 ++++++++++++++++++++++ .../src/math/ec/custom/sec/SecT239FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT283Field.cs | 32 +++++++++++++++++ .../src/math/ec/custom/sec/SecT283FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT409Field.cs | 36 +++++++++++++++++++ .../src/math/ec/custom/sec/SecT409FieldElement.cs | 4 ++- crypto/src/math/ec/custom/sec/SecT571Field.cs | 31 ++++++++++++++++ .../src/math/ec/custom/sec/SecT571FieldElement.cs | 4 ++- crypto/src/math/raw/Interleave.cs | 12 +++++++ crypto/test/src/math/ec/test/ECPointTest.cs | 13 +++++++ 20 files changed, 327 insertions(+), 9 deletions(-) diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs index 640c6e787..49773b66d 100644 --- a/crypto/src/math/ec/custom/sec/SecT113Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs @@ -102,6 +102,16 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 1] = z1 & M49; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0 = Interleave.Unshuffle(x[0]), u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + z[0] = e0 ^ (c0 << 57) ^ (c0 << 5); + z[1] = (c0 >> 7) ^ (c0 >> 59); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat128.CreateExt64(); @@ -131,6 +141,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { /* diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs index f217e28cb..9ba25d987 100644 --- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat128.Create64(); + SecT113Field.Sqrt(x, z); + return new SecT113FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs index 47f97078c..1b6697afe 100644 --- a/crypto/src/math/ec/custom/sec/SecT131Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs @@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M03 = ulong.MaxValue >> 61; private const ulong M44 = ulong.MaxValue >> 20; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x26BC4D789AF13523UL, 0x26BC4D789AF135E2UL, 0x6UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -109,6 +111,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 2] = z2 & M03; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat192.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL); + odd[1] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(5); @@ -138,6 +159,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 123, 129 + return (uint)(x[0] ^ (x[1] >> 59) ^ (x[2] >> 1)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5]; diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs index 0ea00ea07..e0ecc100f 100644 --- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat192.Create64(); + SecT131Field.Sqrt(x, z); + return new SecT131FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs index f921a5bc7..b1e9aa725 100644 --- a/crypto/src/math/ec/custom/sec/SecT163Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs @@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M35 = ulong.MaxValue >> 29; private const ulong M55 = ulong.MaxValue >> 9; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0xB6DB6DB6DB6DB6B0UL, 0x492492492492DB6DUL, 0x492492492UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -122,6 +124,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 2] = z2 & M35; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat192.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL); + odd[1] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat192.CreateExt64(); @@ -151,6 +172,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 157 + return (uint)(x[0] ^ (x[2] >> 29)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5]; diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs index c7a0b5639..8953fb529 100644 --- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat192.Create64(); + SecT163Field.Sqrt(x, z); + return new SecT163FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs index 5154f1e0a..41acb4f94 100644 --- a/crypto/src/math/ec/custom/sec/SecT193Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs @@ -132,6 +132,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M01; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) ^ (x[3] << 32); + ulong c1 = (u0 >> 32); + + z[0] = e0 ^ (c0 << 8); + z[1] = e1 ^ (c1 << 8) ^ (c0 >> 56) ^ (c0 << 33); + z[2] = (c1 >> 56) ^ (c1 << 33) ^ (c0 >> 31); + z[3] = (c1 >> 31); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -161,6 +178,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs index eba4d10e6..a1150b3f9 100644 --- a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT193Field.Sqrt(x, z); + return new SecT193FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs index a2f73fd5d..870dade50 100644 --- a/crypto/src/math/ec/custom/sec/SecT233Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs @@ -128,6 +128,41 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M41; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + ulong c2; + c2 = (c1 >> 27); + c1 ^= (c0 >> 27) | (c1 << 37); + c0 ^= (c0 << 37); + + ulong[] tt = Nat256.CreateExt64(); + + int[] shifts = { 32, 117, 191 }; + for (int i = 0; i < shifts.Length; ++i) + { + int w = shifts[i] >> 6, s = shifts[i] & 63; + Debug.Assert(s != 0); + tt[w ] ^= (c0 << s); + tt[w + 1] ^= (c1 << s) | (c0 >> -s); + tt[w + 2] ^= (c2 << s) | (c1 >> -s); + tt[w + 3] ^= (c2 >> -s); + } + + Reduce(tt, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -157,6 +192,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 159 + return (uint)(x[0] ^ (x[2] >> 31)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs index a9041efde..91b8e2f1c 100644 --- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT233Field.Sqrt(x, z); + return new SecT233FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs index 6b8ad696f..2e6ed2ad6 100644 --- a/crypto/src/math/ec/custom/sec/SecT239Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs @@ -136,6 +136,42 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M47; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + ulong c2, c3; + c3 = (c1 >> 49); + c2 = (c0 >> 49) | (c1 << 15); + c1 ^= (c0 << 15); + + ulong[] tt = Nat256.CreateExt64(); + + int[] shifts = { 39, 120 }; + for (int i = 0; i < shifts.Length; ++i) + { + int w = shifts[i] >> 6, s = shifts[i] & 63; + Debug.Assert(s != 0); + tt[w ] ^= (c0 << s); + tt[w + 1] ^= (c1 << s) | (c0 >> -s); + tt[w + 2] ^= (c2 << s) | (c1 >> -s); + tt[w + 3] ^= (c3 << s) | (c2 >> -s); + tt[w + 4] ^= (c3 >> -s); + } + + Reduce(tt, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -165,6 +201,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 81, 162 + return (uint)(x[0] ^ (x[1] >> 17) ^ (x[2] >> 34)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs index de074c55f..a32ffc5d2 100644 --- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT239Field.Sqrt(x, z); + return new SecT239FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs index 903ea02ff..22b7eaaab 100644 --- a/crypto/src/math/ec/custom/sec/SecT283Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs @@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M27 = ulong.MaxValue >> 37; private const ulong M57 = ulong.MaxValue >> 7; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x0C30C30C30C30808UL, 0x30C30C30C30C30C3UL, 0x820820820820830CUL, 0x0820820820820820UL, 0x2082082UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -129,6 +131,30 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 4] = z4 & M27; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat320.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[1] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[4]); + ulong e2 = (u0 & 0x00000000FFFFFFFFUL); + odd[2] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + z[2] ^= e2; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(9); @@ -158,6 +184,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 271 + return (uint)(x[0] ^ (x[4] >> 15)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4]; diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs index e02108f73..adfd4e0ed 100644 --- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat320.Create64(); + SecT283Field.Sqrt(x, z); + return new SecT283FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs index 84eada96e..861b77aa1 100644 --- a/crypto/src/math/ec/custom/sec/SecT409Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs @@ -165,6 +165,36 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 6] = z6 & M25; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[4]); u1 = Interleave.Unshuffle(x[5]); + ulong e2 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c2 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[6]); + ulong e3 = (u0 & 0x00000000FFFFFFFFUL); + ulong c3 = (u0 >> 32); + + z[0] = e0 ^ (c0 << 44); + z[1] = e1 ^ (c1 << 44) ^ (c0 >> 20); + z[2] = e2 ^ (c2 << 44) ^ (c1 >> 20); + z[3] = e3 ^ (c3 << 44) ^ (c2 >> 20) ^ (c0 << 13); + z[4] = (c3 >> 20) ^ (c1 << 13) ^ (c0 >> 51); + z[5] = (c2 << 13) ^ (c1 >> 51); + z[6] = (c3 << 13) ^ (c2 >> 51); + + Debug.Assert((c3 >> 51) == 0); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(13); @@ -194,6 +224,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z00 = zz[ 0], z01 = zz[ 1], z02 = zz[ 2], z03 = zz[ 3], z04 = zz[ 4], z05 = zz[ 5], z06 = zz[ 6]; diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs index 581ea73df..f954f46e7 100644 --- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat448.Create64(); + SecT409Field.Sqrt(x, z); + return new SecT409FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs index fc84e336b..98f4f7fc2 100644 --- a/crypto/src/math/ec/custom/sec/SecT571Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs @@ -11,6 +11,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong RM = 0xEF7BDEF7BDEF7BDEUL; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x2BE1195F08CAFB99UL, 0x95F08CAF84657C23UL, 0xCAF84657C232BE11UL, 0x657C232BE1195F08UL, + 0xF84657C2308CAF84UL, 0x7C232BE1195F08CAUL, 0xBE1195F08CAF8465UL, 0x5F08CAF84657C232UL, 0x784657C232BE119UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { for (int i = 0; i < 9; ++i) @@ -156,6 +159,28 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 8] = z8 & M59; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] evn = Nat576.Create64(), odd = Nat576.Create64(); + + int pos = 0; + for (int i = 0; i < 4; ++i) + { + ulong u0 = Interleave.Unshuffle(x[pos++]); + ulong u1 = Interleave.Unshuffle(x[pos++]); + evn[i] = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[i] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + } + { + ulong u0 = Interleave.Unshuffle(x[pos]); + evn[4] = (u0 & 0x00000000FFFFFFFFUL); + odd[4] = (u0 >> 32); + } + + Multiply(odd, ROOT_Z, z); + Add(z, evn, z); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat576.CreateExt64(); @@ -185,6 +210,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 561, 569 + return (uint)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1U; + } + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { //for (int i = 0; i < 9; ++i) diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs index 5d5458412..c43b8dc3a 100644 --- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs @@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat576.Create64(); + SecT571Field.Sqrt(x, z); + return new SecT571FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs index a45ee1e08..d21840644 100644 --- a/crypto/src/math/raw/Interleave.cs +++ b/crypto/src/math/raw/Interleave.cs @@ -91,5 +91,17 @@ namespace Org.BouncyCastle.Math.Raw z[zOff ] = (x ) & M64; z[zOff + 1] = (x >> 1) & M64; } + + internal static ulong Unshuffle(ulong x) + { + // "unshuffle" even bits to low half and odd bits to high half + ulong t; + t = (x ^ (x >> 1)) & 0x2222222222222222UL; x ^= (t ^ (t << 1)); + t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t << 2)); + t = (x ^ (x >> 4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t << 4)); + t = (x ^ (x >> 8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t << 8)); + t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16)); + return x; + } } } diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs index 3c10170f7..57f838f9f 100644 --- a/crypto/test/src/math/ec/test/ECPointTest.cs +++ b/crypto/test/src/math/ec/test/ECPointTest.cs @@ -437,6 +437,19 @@ namespace Org.BouncyCastle.Math.EC.Tests } } } + else if (ECAlgorithms.IsF2mCurve(c)) + { + int m = c.FieldSize; + BigInteger x = new BigInteger(m, secRand); + ECFieldElement fe = c.FromBigInteger(x); + for (int i = 0; i < 100; ++i) + { + ECFieldElement sq = fe.Square(); + ECFieldElement check = sq.Sqrt(); + Assert.AreEqual(fe, check); + fe = sq; + } + } } private void ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(X9ECParameters x9ECParameters) -- cgit 1.5.1 From 0684c4783deae5cf4862e78302844058e5433bce Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 28 Dec 2015 15:32:02 +0700 Subject: Clean up a few warnings --- crypto/src/AssemblyInfo.cs | 3 --- crypto/src/crypto/engines/SerpentEngineBase.cs | 9 +++++---- crypto/test/src/crypto/test/NaccacheSternTest.cs | 5 +---- crypto/test/src/crypto/test/PaddingTest.cs | 6 ++---- crypto/test/src/test/ECEncodingTest.cs | 11 +++++------ 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs index 05f1d8f63..6d6de3218 100644 --- a/crypto/src/AssemblyInfo.cs +++ b/crypto/src/AssemblyInfo.cs @@ -65,10 +65,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDelaySign(false)] #if STRONG_NAME [assembly: AssemblyKeyFile(@"../BouncyCastle.snk")] -#else -[assembly: AssemblyKeyFile("")] #endif -[assembly: AssemblyKeyName("")] [assembly: CLSCompliant(true)] #if !PORTABLE diff --git a/crypto/src/crypto/engines/SerpentEngineBase.cs b/crypto/src/crypto/engines/SerpentEngineBase.cs index a5d91b3be..9de552233 100644 --- a/crypto/src/crypto/engines/SerpentEngineBase.cs +++ b/crypto/src/crypto/engines/SerpentEngineBase.cs @@ -101,12 +101,13 @@ namespace Org.BouncyCastle.Crypto.Engines return ( (int)((uint)x >> bits) | (x << (32 - bits))); } - /** + /* * The sboxes below are based on the work of Brian Gladman and * Sam Simpson, whose original notice appears below. *

* For further details see: * http://fp.gladman.plus.com/cryptography_technology/serpent/ + *

*/ /* Partially optimised Serpent S Box boolean functions derived */ @@ -124,9 +125,9 @@ namespace Org.BouncyCastle.Crypto.Engines /* We hereby give permission for information in this file to be */ /* used freely subject only to acknowledgement of its origin. */ - /** - * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. - */ + /* + * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. + */ protected void Sb0(int a, int b, int c, int d) { int t1 = a ^ d; diff --git a/crypto/test/src/crypto/test/NaccacheSternTest.cs b/crypto/test/src/crypto/test/NaccacheSternTest.cs index 4fa256f12..9168adced 100644 --- a/crypto/test/src/crypto/test/NaccacheSternTest.cs +++ b/crypto/test/src/crypto/test/NaccacheSternTest.cs @@ -78,9 +78,6 @@ namespace Org.BouncyCastle.Crypto.Tests static NaccacheSternTest() { - cryptEng.Debug = debug; - decryptEng.Debug = debug; - // First the Parameters from the NaccacheStern Paper // (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf ) @@ -145,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Tests // specify key generation parameters NaccacheSternKeyGenerationParameters genParam - = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30, debug); + = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30); // Initialize Key generator and generate key pair NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator(); diff --git a/crypto/test/src/crypto/test/PaddingTest.cs b/crypto/test/src/crypto/test/PaddingTest.cs index 6f41d754c..ed53d9228 100644 --- a/crypto/test/src/crypto/test/PaddingTest.cs +++ b/crypto/test/src/crypto/test/PaddingTest.cs @@ -105,11 +105,9 @@ namespace Org.BouncyCastle.Crypto.Tests public override void PerformTest() { - SecureRandom rand = new SecureRandom(new byte[20]); + SecureRandom rand = SecureRandom.GetInstance("SHA1PRNG"); - rand.SetSeed(DateTime.Now.Ticks); - - doTestPadding(new Pkcs7Padding(), rand, + doTestPadding(new Pkcs7Padding(), rand, Hex.Decode("ffffff0505050505"), Hex.Decode("0000000004040404")); diff --git a/crypto/test/src/test/ECEncodingTest.cs b/crypto/test/src/test/ECEncodingTest.cs index f1a4d5e3a..8d993c15e 100644 --- a/crypto/test/src/test/ECEncodingTest.cs +++ b/crypto/test/src/test/ECEncodingTest.cs @@ -109,7 +109,7 @@ namespace Org.BouncyCastle.Tests if (!compress) { //pubKey.setPointFormat("UNCOMPRESSED"); - pubKey = SetPublicUncompressed(pubKey, false); + pubKey = SetPublicUncompressed(pubKey); } byte[] x = pubKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(); @@ -154,7 +154,7 @@ namespace Org.BouncyCastle.Tests // TODO Private key compression? //newKey.setPointFormat("UNCOMPRESSED"); //newPubKey.setPointFormat("UNCOMPRESSED"); - newPubKey = SetPublicUncompressed(newPubKey, false); + newPubKey = SetPublicUncompressed(newPubKey); } // string newPrivateKey = new string(Hex.encode(newKey.getEncoded())); @@ -201,7 +201,7 @@ namespace Org.BouncyCastle.Tests // TODO Private key compression? //privECKey.setPointFormat("UNCOMPRESSED"); //pubECKey.setPointFormat("UNCOMPRESSED"); - pubECKey = SetPublicUncompressed(pubECKey, false); + pubECKey = SetPublicUncompressed(pubECKey); } certGen.SetSignatureAlgorithm("ECDSAwithSHA1"); @@ -216,13 +216,12 @@ namespace Org.BouncyCastle.Tests } private ECPublicKeyParameters SetPublicUncompressed( - ECPublicKeyParameters key, - bool withCompression) + ECPublicKeyParameters key) { ECPoint p = key.Q.Normalize(); return new ECPublicKeyParameters( key.AlgorithmName, - p.Curve.CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), withCompression), + p.Curve.CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger()), key.Parameters); } -- cgit 1.5.1 From 5cf99df42f7ee75979a0d7243b79eff844fdbcfd Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 28 Dec 2015 17:50:36 +0700 Subject: Various ASN.1 updates from Java API --- crypto/BouncyCastle.Android.csproj | 4 +- crypto/BouncyCastle.csproj | 4 +- crypto/BouncyCastle.iOS.csproj | 4 +- crypto/crypto.csproj | 10 ++ crypto/src/asn1/Asn1InputStream.cs | 4 + crypto/src/asn1/Asn1TaggedObject.cs | 10 ++ crypto/src/asn1/DERExternal.cs | 15 +-- crypto/src/asn1/DerApplicationSpecific.cs | 2 +- crypto/src/asn1/DerGraphicString.cs | 103 +++++++++++++++++++++ crypto/src/asn1/DerVideotexString.cs | 103 +++++++++++++++++++++ crypto/src/asn1/util/Asn1Dump.cs | 8 ++ .../src/asn1/test/DERApplicationSpecificTest.cs | 67 +++++++++++++- crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs | 6 +- 13 files changed, 320 insertions(+), 20 deletions(-) create mode 100644 crypto/src/asn1/DerGraphicString.cs create mode 100644 crypto/src/asn1/DerVideotexString.cs diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 6ceeac8bd..70d09cc6e 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -1,4 +1,4 @@ - + Debug @@ -109,6 +109,7 @@ + @@ -125,6 +126,7 @@ + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index b3aefa8e9..f57dd2011 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -1,4 +1,4 @@ - + Debug @@ -103,6 +103,7 @@ + @@ -119,6 +120,7 @@ + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index f5bef5bb4..4c499db46 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -1,4 +1,4 @@ - + Debug @@ -104,6 +104,7 @@ + @@ -120,6 +121,7 @@ + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index e4bd2e036..73afed47e 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -383,6 +383,11 @@ SubType = "Code" BuildAction = "Compile" /> + + Date: Mon, 28 Dec 2015 19:25:35 +0700 Subject: Add IdRsaKem --- crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs index 0b2ffa0d1..609aa61ba 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -118,6 +118,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier Pkcs9AtSigningDescription = new DerObjectIdentifier(Pkcs9 + ".13"); public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest = new DerObjectIdentifier(Pkcs9 + ".14"); public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities = new DerObjectIdentifier(Pkcs9 + ".15"); + public static readonly DerObjectIdentifier IdSmime = new DerObjectIdentifier(Pkcs9 + ".16"); + public static readonly DerObjectIdentifier Pkcs9AtFriendlyName = new DerObjectIdentifier(Pkcs9 + ".20"); public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID = new DerObjectIdentifier(Pkcs9 + ".21"); @@ -131,19 +133,32 @@ namespace Org.BouncyCastle.Asn1.Pkcs public const string CrlTypes = Pkcs9 + ".23"; public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1"); - public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9"); + public static readonly DerObjectIdentifier IdAlg = IdSmime.Branch("3"); + public static readonly DerObjectIdentifier IdAlgPwriKek = IdAlg.Branch("9"); + + /* + *
+         * -- RSA-KEM Key Transport Algorithm
+         *
+         * id-rsa-kem OID ::= {
+         *      iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
+         *      pkcs-9(9) smime(16) alg(3) 14
+         *   }
+         * 
+ */ + public static readonly DerObjectIdentifier IdRsaKem = IdAlg.Branch("14"); // // SMIME capability sub oids. // - public static readonly DerObjectIdentifier PreferSignedData = new DerObjectIdentifier(Pkcs9 + ".15.1"); - public static readonly DerObjectIdentifier CannotDecryptAny = new DerObjectIdentifier(Pkcs9 + ".15.2"); - public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = new DerObjectIdentifier(Pkcs9 + ".15.3"); + public static readonly DerObjectIdentifier PreferSignedData = Pkcs9AtSmimeCapabilities.Branch("1"); + public static readonly DerObjectIdentifier CannotDecryptAny = Pkcs9AtSmimeCapabilities.Branch("2"); + public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = Pkcs9AtSmimeCapabilities.Branch("3"); // // other SMIME attributes // - public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1"); + public static readonly DerObjectIdentifier IdAAReceiptRequest = IdSmime.Branch("2.1"); // // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) @@ -252,5 +267,5 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6"); public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7"); - } + } } -- cgit 1.5.1 From 5439621aab0092fdf259911bc9cc7481f10bc943 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 28 Dec 2015 20:18:40 +0700 Subject: Add a couple more OIDs --- crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs index 609aa61ba..042911a06 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs @@ -133,8 +133,13 @@ namespace Org.BouncyCastle.Asn1.Pkcs public const string CrlTypes = Pkcs9 + ".23"; public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1"); - public static readonly DerObjectIdentifier IdAlg = IdSmime.Branch("3"); - public static readonly DerObjectIdentifier IdAlgPwriKek = IdAlg.Branch("9"); + public static readonly DerObjectIdentifier IdAlg = IdSmime.Branch("3"); + + public static readonly DerObjectIdentifier IdAlgEsdh = IdAlg.Branch("5"); + public static readonly DerObjectIdentifier IdAlgCms3DesWrap = IdAlg.Branch("6"); + public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = IdAlg.Branch("7"); + public static readonly DerObjectIdentifier IdAlgPwriKek = IdAlg.Branch("9"); + public static readonly DerObjectIdentifier IdAlgSsdh = IdAlg.Branch("10"); /* *
@@ -264,8 +269,5 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc	= new DerObjectIdentifier(Pkcs12PbeIds + ".4");
         public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc		= new DerObjectIdentifier(Pkcs12PbeIds + ".5");
         public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc			= new DerObjectIdentifier(Pkcs12PbeIds + ".6");
-
-		public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6");
-		public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7");
     }
 }
-- 
cgit 1.5.1


From 4a87b839681c95a5fbe43ed6ce65fa069a942586 Mon Sep 17 00:00:00 2001
From: Peter Dettman 
Date: Mon, 28 Dec 2015 21:34:07 +0700
Subject: Update versions and release notes for release 1.8.1

---
 crypto/NBuild.build        |  2 +-
 crypto/Readme.html         | 42 ++++++++++++++++++++++++++++++++++++------
 crypto/src/AssemblyInfo.cs |  6 +++---
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/crypto/NBuild.build b/crypto/NBuild.build
index 984fd6758..71096cbf0 100644
--- a/crypto/NBuild.build
+++ b/crypto/NBuild.build
@@ -16,7 +16,7 @@
   
 
   
-  
+  
   
 
   
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 67116c815..d5cda3032 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -30,6 +30,8 @@
 			
  • Notes:
      +
    1. + Release 1.8.1
    2. Release 1.8.0
    3. @@ -288,6 +290,38 @@ We state, where EC MQV has not otherwise been disabled or removed:

      Notes:

      +

      Release 1.8.1, Monday December 28, 2015

      + +
      Security Advisory
      +
        +
      • + (D)TLS 1.2: Motivated by CVE-2015-7575, we have added validation that + the signature algorithm received in DigitallySigned structures is actually one of those offered (in signature_algorithms extension + or CertificateRequest). With our default TLS configuration, we do not believe there is an exploitable vulnerability in any earlier + releases. Users that are customizing the signature_algorithms extension, or running a server supporting client authentication, are + advised to double-check that they are not offering any signature algorithms involving MD5. +
      • +
      +
      Additional Features and Functionality
      +
        +
      • Added support for ASN.1 GraphicString and VideotexString types.
      • +
      • + Problems with DTLS record-layer version handling were resolved via BJA-584, + making version negotiation work properly. +
      • +
      +
      Additional Notes
      + +

      Release 1.8.0, Sunday November 22, 2015

      IMPORTANT
      @@ -348,15 +382,11 @@ We state, where EC MQV has not otherwise been disabled or removed: diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs index 6d6de3218..bb9811d83 100644 --- a/crypto/src/AssemblyInfo.cs +++ b/crypto/src/AssemblyInfo.cs @@ -33,9 +33,9 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.8.0.0")] -[assembly: AssemblyFileVersion("1.8.15326.1")] -[assembly: AssemblyInformationalVersion("1.8.0")] +[assembly: AssemblyVersion("1.8.1.0")] +[assembly: AssemblyFileVersion("1.8.15362.1")] +[assembly: AssemblyInformationalVersion("1.8.1")] // // In order to sign your assembly you must specify a key to use. Refer to the -- cgit 1.5.1