From 0328a9c2006b894d70c943a1c59dd366bec7e07a Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Feb 2015 19:32:21 +0700 Subject: Fix parsing of implicit tagged object --- crypto/src/asn1/cms/EncryptedData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/cms/EncryptedData.cs b/crypto/src/asn1/cms/EncryptedData.cs index 5b8378282..cb109a640 100644 --- a/crypto/src/asn1/cms/EncryptedData.cs +++ b/crypto/src/asn1/cms/EncryptedData.cs @@ -52,8 +52,8 @@ namespace Org.BouncyCastle.Asn1.Cms if (seq.Count > 2) { - this.unprotectedAttrs = Asn1Set.GetInstance(seq[2]); - } + this.unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[2], false); + } } public virtual DerInteger Version -- cgit 1.4.1 From d547000f967e7c7df0447783d74aa511c108bfd2 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 6 Mar 2015 15:32:51 +0700 Subject: Improved handling for out-of-order Finished message --- crypto/src/crypto/tls/TlsProtocol.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 09838a717..08b39f2a6 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -270,15 +270,20 @@ namespace Org.BouncyCastle.Crypto.Tls break; case HandshakeType.finished: default: - if (type == HandshakeType.finished && this.mExpectedVerifyData == null) + { + TlsContext ctx = Context; + if (type == HandshakeType.finished + && this.mExpectedVerifyData == null + && ctx.SecurityParameters.MasterSecret != null) { - this.mExpectedVerifyData = CreateVerifyData(!Context.IsServer); + this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer); } mRecordStream.UpdateHandshakeData(beginning, 0, 4); mRecordStream.UpdateHandshakeData(buf, 0, len); break; } + } /* * Now, parse the message. @@ -612,6 +617,9 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ProcessFinishedMessage(MemoryStream buf) { + if (mExpectedVerifyData == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + byte[] verify_data = TlsUtilities.ReadFully(mExpectedVerifyData.Length, buf); AssertEmpty(buf); -- cgit 1.4.1 From e781400bd619176f9804cb75e2ee8bc6102c2e62 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 6 Mar 2015 16:45:13 +0700 Subject: Refuse client-initiated renegotiation gracefully --- crypto/src/crypto/tls/TlsClientProtocol.cs | 10 +--------- crypto/src/crypto/tls/TlsProtocol.cs | 12 ++++++++++++ crypto/src/crypto/tls/TlsServerProtocol.cs | 5 +++++ 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 19e7d71aa..0c35e62af 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -529,15 +529,7 @@ namespace Org.BouncyCastle.Crypto.Tls */ if (this.mConnectionState == CS_END) { - /* - * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal - * handshake_failure alert. - */ - if (TlsUtilities.IsSsl(Context)) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - - string message = "Renegotiation not supported"; - RaiseWarning(AlertDescription.no_renegotiation, message); + RefuseRenegotiation(); } break; } diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 08b39f2a6..8fd83aca2 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -759,6 +759,18 @@ namespace Org.BouncyCastle.Crypto.Tls return maxFragmentLength; } + protected virtual void RefuseRenegotiation() + { + /* + * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal + * handshake_failure alert. + */ + if (TlsUtilities.IsSsl(Context)) + throw new TlsFatalAlert(AlertDescription.handshake_failure); + + RaiseWarning(AlertDescription.no_renegotiation, "Renegotiation not supported"); + } + /** * Make sure the InputStream 'buf' now empty. Fail otherwise. * diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index b1fb830b6..d2959cfed 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -179,6 +179,11 @@ namespace Org.BouncyCastle.Crypto.Tls break; } + case CS_END: + { + RefuseRenegotiation(); + break; + } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } -- cgit 1.4.1 From 7032cb795cbd30b2a0cabf8152b52ff1ac6a54db Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 6 Mar 2015 19:23:30 +0700 Subject: Tighten ChangeCipherSpec ordering checks --- crypto/src/crypto/tls/TlsProtocol.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 8fd83aca2..1a6e7a3bc 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -99,6 +99,12 @@ namespace Org.BouncyCastle.Crypto.Tls { } + protected virtual void CheckReceivedChangeCipherSpec(bool expected) + { + if (expected != mReceivedChangeCipherSpec) + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + protected virtual void CleanupHandshake() { if (this.mExpectedVerifyData != null) @@ -259,6 +265,8 @@ namespace Org.BouncyCastle.Crypto.Tls */ byte[] buf = mHandshakeQueue.RemoveData(len, 4); + CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished); + /* * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages * starting at client hello up to, but not including, this finished message. -- cgit 1.4.1 From 476b6fdf325b34933a1cb39c6c75121de7a780fa Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 7 Mar 2015 21:11:22 +0700 Subject: Various updates from Java build --- crypto/crypto.csproj | 10 ++ crypto/src/crypto/BufferedBlockCipher.cs | 22 +-- crypto/src/crypto/Check.cs | 25 +++ crypto/src/crypto/OutputLengthException.cs | 28 ++++ crypto/src/crypto/engines/AesEngine.cs | 25 +-- crypto/src/crypto/engines/AesFastEngine.cs | 25 +-- crypto/src/crypto/engines/AesLightEngine.cs | 25 +-- crypto/src/crypto/engines/BlowfishEngine.cs | 15 +- crypto/src/crypto/engines/CamelliaEngine.cs | 21 ++- crypto/src/crypto/engines/CamelliaLightEngine.cs | 21 ++- crypto/src/crypto/engines/Cast5Engine.cs | 11 +- crypto/src/crypto/engines/ChaChaEngine.cs | 3 - crypto/src/crypto/engines/DesEdeEngine.cs | 7 +- crypto/src/crypto/engines/DesEdeWrapEngine.cs | 8 +- crypto/src/crypto/engines/DesEngine.cs | 11 +- crypto/src/crypto/engines/ElGamalEngine.cs | 10 +- crypto/src/crypto/engines/GOST28147Engine.cs | 27 ++-- crypto/src/crypto/engines/HC128Engine.cs | 19 ++- crypto/src/crypto/engines/HC256Engine.cs | 19 ++- crypto/src/crypto/engines/ISAACEngine.cs | 17 +- crypto/src/crypto/engines/IdeaEngine.cs | 26 ++-- crypto/src/crypto/engines/IesEngine.cs | 4 +- crypto/src/crypto/engines/NaccacheSternEngine.cs | 16 +- crypto/src/crypto/engines/NoekeonEngine.cs | 21 ++- crypto/src/crypto/engines/NullEngine.cs | 21 ++- crypto/src/crypto/engines/RC2Engine.cs | 22 ++- crypto/src/crypto/engines/RC2WrapEngine.cs | 8 +- crypto/src/crypto/engines/RC4Engine.cs | 25 +-- crypto/src/crypto/engines/RC532Engine.cs | 13 +- crypto/src/crypto/engines/RC564Engine.cs | 13 +- crypto/src/crypto/engines/RC6Engine.cs | 22 ++- crypto/src/crypto/engines/RFC3211WrapEngine.cs | 8 +- crypto/src/crypto/engines/RFC3394WrapEngine.cs | 8 +- crypto/src/crypto/engines/RSABlindedEngine.cs | 10 +- crypto/src/crypto/engines/RSABlindingEngine.cs | 10 +- crypto/src/crypto/engines/RSACoreEngine.cs | 12 +- crypto/src/crypto/engines/RijndaelEngine.cs | 30 ++-- crypto/src/crypto/engines/RsaEngine.cs | 10 +- crypto/src/crypto/engines/SEEDEngine.cs | 21 ++- crypto/src/crypto/engines/Salsa20Engine.cs | 27 +--- crypto/src/crypto/engines/SerpentEngine.cs | 22 ++- crypto/src/crypto/engines/SkipjackEngine.cs | 26 ++-- crypto/src/crypto/engines/TEAEngine.cs | 21 ++- crypto/src/crypto/engines/ThreefishEngine.cs | 12 +- crypto/src/crypto/engines/TwofishEngine.cs | 9 +- crypto/src/crypto/engines/VMPCEngine.cs | 11 +- crypto/src/crypto/engines/XSalsa20Engine.cs | 2 - crypto/src/crypto/engines/XTEAEngine.cs | 21 ++- .../src/crypto/generators/RsaKeyPairGenerator.cs | 173 +++++++++++---------- crypto/src/crypto/modes/CcmBlockCipher.cs | 127 ++++++++++----- crypto/src/crypto/modes/EAXBlockCipher.cs | 55 ++++--- crypto/src/crypto/modes/GCMBlockCipher.cs | 13 +- crypto/src/crypto/modes/OCBBlockCipher.cs | 5 + crypto/src/crypto/modes/gcm/GcmUtilities.cs | 23 +++ .../crypto/paddings/PaddedBufferedBlockCipher.cs | 7 +- crypto/test/src/crypto/test/CCMTest.cs | 47 +++++- 56 files changed, 666 insertions(+), 584 deletions(-) create mode 100644 crypto/src/crypto/Check.cs create mode 100644 crypto/src/crypto/OutputLengthException.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index fdd5c152b..3f713e1c0 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -2963,6 +2963,11 @@ SubType = "Code" BuildAction = "Compile" /> + + 0) { - if ((outOff + outLength) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.OutputLength(output, outOff, outLength, "output buffer too short"); } - int resultLen = 0; + int resultLen = 0; int gapLen = buf.Length - bufOff; if (length > gapLen) { @@ -339,17 +336,10 @@ namespace Org.BouncyCastle.Crypto { if (bufOff != 0) { - if (!cipher.IsPartialBlockOkay) - { - throw new DataLengthException("data not block size aligned"); - } - - if (outOff + bufOff > output.Length) - { - throw new DataLengthException("output buffer too short for DoFinal()"); - } - - // NB: Can't copy directly, or we may write too much output + Check.DataLength(!cipher.IsPartialBlockOkay, "data not block size aligned"); + Check.OutputLength(output, outOff, bufOff, "output buffer too short for DoFinal()"); + + // NB: Can't copy directly, or we may write too much output cipher.ProcessBlock(buf, 0, buf, 0); Array.Copy(buf, 0, output, outOff, bufOff); } diff --git a/crypto/src/crypto/Check.cs b/crypto/src/crypto/Check.cs new file mode 100644 index 000000000..96a05c64b --- /dev/null +++ b/crypto/src/crypto/Check.cs @@ -0,0 +1,25 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + internal class Check + { + internal static void DataLength(bool condition, string msg) + { + if (condition) + throw new DataLengthException(msg); + } + + internal static void DataLength(byte[] buf, int off, int len, string msg) + { + if (off + len > buf.Length) + throw new DataLengthException(msg); + } + + internal static void OutputLength(byte[] buf, int off, int len, string msg) + { + if (off + len > buf.Length) + throw new OutputLengthException(msg); + } + } +} diff --git a/crypto/src/crypto/OutputLengthException.cs b/crypto/src/crypto/OutputLengthException.cs new file mode 100644 index 000000000..e1cf44925 --- /dev/null +++ b/crypto/src/crypto/OutputLengthException.cs @@ -0,0 +1,28 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) + [Serializable] +#endif + public class OutputLengthException + : DataLengthException + { + public OutputLengthException() + { + } + + public OutputLengthException( + string message) + : base(message) + { + } + + public OutputLengthException( + string message, + Exception exception) + : base(message, exception) + { + } + } +} diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs index 0cdd868fa..9d7f76c05 100644 --- a/crypto/src/crypto/engines/AesEngine.cs +++ b/crypto/src/crypto/engines/AesEngine.cs @@ -363,7 +363,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -377,41 +377,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -429,7 +420,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs index 38d3a5841..a1b544568 100644 --- a/crypto/src/crypto/engines/AesFastEngine.cs +++ b/crypto/src/crypto/engines/AesFastEngine.cs @@ -695,7 +695,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -709,41 +709,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -761,7 +752,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/AesLightEngine.cs b/crypto/src/crypto/engines/AesLightEngine.cs index 54f2d2e88..a6b9e3bd4 100644 --- a/crypto/src/crypto/engines/AesLightEngine.cs +++ b/crypto/src/crypto/engines/AesLightEngine.cs @@ -258,7 +258,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -272,41 +272,32 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "AES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) - { throw new InvalidOperationException("AES engine not initialised"); - } - if ((inOff + (32 / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, 16, "input buffer too short"); + Check.OutputLength(output, outOff, 16, "output buffer too short"); UnPackBlock(input, inOff); @@ -324,7 +315,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/BlowfishEngine.cs b/crypto/src/crypto/engines/BlowfishEngine.cs index 8f80f712e..7b50e832f 100644 --- a/crypto/src/crypto/engines/BlowfishEngine.cs +++ b/crypto/src/crypto/engines/BlowfishEngine.cs @@ -296,7 +296,7 @@ namespace Org.BouncyCastle.Crypto.Engines //==================================== private static readonly int ROUNDS = 16; - private const int BLOCK_SIZE = 8; // bytes = 64 bits + private const int BLOCK_SIZE = 8; // bytes = 64 bits private static readonly int SBOX_SK = 256; private static readonly int P_SZ = ROUNDS+2; @@ -353,19 +353,10 @@ namespace Org.BouncyCastle.Crypto.Engines int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Blowfish not initialised"); - } - if ((inOff + BLOCK_SIZE) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + BLOCK_SIZE) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); if (encrypting) { diff --git a/crypto/src/crypto/engines/CamelliaEngine.cs b/crypto/src/crypto/engines/CamelliaEngine.cs index 8f4a442e9..71bd1b0dc 100644 --- a/crypto/src/crypto/engines/CamelliaEngine.cs +++ b/crypto/src/crypto/engines/CamelliaEngine.cs @@ -611,7 +611,7 @@ namespace Org.BouncyCastle.Crypto.Engines { } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -623,22 +623,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Camellia"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -646,12 +646,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Camellia engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (_keyIs128) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (_keyIs128) { return processBlock128(input, inOff, output, outOff); } @@ -661,7 +660,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { // nothing } diff --git a/crypto/src/crypto/engines/CamelliaLightEngine.cs b/crypto/src/crypto/engines/CamelliaLightEngine.cs index a301eb55e..a132227c5 100644 --- a/crypto/src/crypto/engines/CamelliaLightEngine.cs +++ b/crypto/src/crypto/engines/CamelliaLightEngine.cs @@ -524,22 +524,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Camellia"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -551,7 +551,7 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -559,12 +559,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Camellia engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (_keyis128) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (_keyis128) { return processBlock128(input, inOff, output, outOff); } @@ -574,7 +573,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { } } diff --git a/crypto/src/crypto/engines/Cast5Engine.cs b/crypto/src/crypto/engines/Cast5Engine.cs index 4c3f84a55..1af30a335 100644 --- a/crypto/src/crypto/engines/Cast5Engine.cs +++ b/crypto/src/crypto/engines/Cast5Engine.cs @@ -329,7 +329,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -360,12 +360,11 @@ namespace Org.BouncyCastle.Crypto.Engines int blockSize = GetBlockSize(); if (_workingKey == null) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + blockSize) > input.Length) - throw new DataLengthException("Input buffer too short"); - if ((outOff + blockSize) > output.Length) - throw new DataLengthException("Output buffer too short"); - if (_encrypting) + Check.DataLength(input, inOff, blockSize, "input buffer too short"); + Check.OutputLength(output, outOff, blockSize, "output buffer too short"); + + if (_encrypting) { return EncryptBlock(input, inOff, output, outOff); } diff --git a/crypto/src/crypto/engines/ChaChaEngine.cs b/crypto/src/crypto/engines/ChaChaEngine.cs index f4a7b8fe1..46b59ed2e 100644 --- a/crypto/src/crypto/engines/ChaChaEngine.cs +++ b/crypto/src/crypto/engines/ChaChaEngine.cs @@ -162,7 +162,6 @@ namespace Org.BouncyCastle.Crypto.Engines x09 += x14; x04 = R(x04 ^ x09, 12); x03 += x04; x14 = R(x14 ^ x03, 8); x09 += x14; x04 = R(x04 ^ x09, 7); - } x[ 0] = x00 + input[ 0]; @@ -182,8 +181,6 @@ namespace Org.BouncyCastle.Crypto.Engines x[14] = x14 + input[14]; x[15] = x15 + input[15]; } - } - } diff --git a/crypto/src/crypto/engines/DesEdeEngine.cs b/crypto/src/crypto/engines/DesEdeEngine.cs index eec4ec59d..bc40b56a8 100644 --- a/crypto/src/crypto/engines/DesEdeEngine.cs +++ b/crypto/src/crypto/engines/DesEdeEngine.cs @@ -70,10 +70,9 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey1 == null) throw new InvalidOperationException("DESede engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); + + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); byte[] temp = new byte[BLOCK_SIZE]; diff --git a/crypto/src/crypto/engines/DesEdeWrapEngine.cs b/crypto/src/crypto/engines/DesEdeWrapEngine.cs index fdc71687f..43100a9bd 100644 --- a/crypto/src/crypto/engines/DesEdeWrapEngine.cs +++ b/crypto/src/crypto/engines/DesEdeWrapEngine.cs @@ -52,7 +52,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forWrapping * @param param */ - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return */ - public string AlgorithmName + public virtual string AlgorithmName { get { return "DESede"; } } @@ -116,7 +116,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param inLen * @return */ - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int length) @@ -185,7 +185,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @throws InvalidCipherTextException */ - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/DesEngine.cs b/crypto/src/crypto/engines/DesEngine.cs index 067cf45e3..a6d580bb6 100644 --- a/crypto/src/crypto/engines/DesEngine.cs +++ b/crypto/src/crypto/engines/DesEngine.cs @@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Engines get { return "DES"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } @@ -59,12 +59,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("DES engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - DesFunc(workingKey, input, inOff, output, outOff); + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + DesFunc(workingKey, input, inOff, output, outOff); return BLOCK_SIZE; } diff --git a/crypto/src/crypto/engines/ElGamalEngine.cs b/crypto/src/crypto/engines/ElGamalEngine.cs index 3d256a087..197d7bc15 100644 --- a/crypto/src/crypto/engines/ElGamalEngine.cs +++ b/crypto/src/crypto/engines/ElGamalEngine.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Engines private bool forEncryption; private int bitSize; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ElGamal"; } } @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary ElGamal key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the ElGamal process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/GOST28147Engine.cs b/crypto/src/crypto/engines/GOST28147Engine.cs index 8eb6f36b5..e37ddaefd 100644 --- a/crypto/src/crypto/engines/GOST28147Engine.cs +++ b/crypto/src/crypto/engines/GOST28147Engine.cs @@ -150,7 +150,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param parameters the parameters required to set up the cipher. * @exception ArgumentException if the parameters argument is inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -187,48 +187,39 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Gost28147"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Gost28147 engine not initialised"); - } - if ((inOff + BlockSize) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + BlockSize) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(output, outOff, BlockSize, "output buffer too short"); - Gost28147Func(workingKey, input, inOff, output, outOff); + Gost28147Func(workingKey, input, inOff, output, outOff); return BlockSize; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs index a2d099f87..40c7a4e17 100644 --- a/crypto/src/crypto/engines/HC128Engine.cs +++ b/crypto/src/crypto/engines/HC128Engine.cs @@ -142,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Engines cnt = 0; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "HC-128"; } } @@ -156,7 +156,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @throws ArgumentException if the params argument is * inappropriate (ie. the key is not 128 bit long). */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -201,7 +201,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ret; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -210,24 +210,23 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < len; i++) + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); + + for (int i = 0; i < len; i++) { output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); } } - public void Reset() + public virtual void Reset() { idx = 0; Init(); } - public byte ReturnByte(byte input) + public virtual byte ReturnByte(byte input) { return (byte)(input ^ GetByte()); } diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs index da717dab7..6eb360711 100644 --- a/crypto/src/crypto/engines/HC256Engine.cs +++ b/crypto/src/crypto/engines/HC256Engine.cs @@ -126,7 +126,7 @@ namespace Org.BouncyCastle.Crypto.Engines cnt = 0; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "HC-256"; } } @@ -140,7 +140,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @throws ArgumentException if the params argument is * inappropriate (ie. the key is not 256 bit long). */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -185,7 +185,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ret; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -194,24 +194,23 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < len; i++) + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); + + for (int i = 0; i < len; i++) { output[outOff + i] = (byte)(input[inOff + i] ^ GetByte()); } } - public void Reset() + public virtual void Reset() { idx = 0; Init(); } - public byte ReturnByte(byte input) + public virtual byte ReturnByte(byte input) { return (byte)(input ^ GetByte()); } diff --git a/crypto/src/crypto/engines/ISAACEngine.cs b/crypto/src/crypto/engines/ISAACEngine.cs index 9c58678a0..f25577130 100644 --- a/crypto/src/crypto/engines/ISAACEngine.cs +++ b/crypto/src/crypto/engines/ISAACEngine.cs @@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { if (index == 0) @@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Engines return output; } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int len, @@ -77,10 +77,9 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + len) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + len) > output.Length) - throw new DataLengthException("output buffer too short"); + + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); for (int i = 0; i < len; i++) { @@ -94,12 +93,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "ISAAC"; } } - public void Reset() + public virtual void Reset() { setKey(workingKey); } diff --git a/crypto/src/crypto/engines/IdeaEngine.cs b/crypto/src/crypto/engines/IdeaEngine.cs index 46b5a787c..4909510ac 100644 --- a/crypto/src/crypto/engines/IdeaEngine.cs +++ b/crypto/src/crypto/engines/IdeaEngine.cs @@ -47,7 +47,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -58,43 +58,37 @@ namespace Org.BouncyCastle.Crypto.Engines ((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "IDEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("IDEA engine not initialised"); - } - if ((inOff + BLOCK_SIZE) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - if ((outOff + BLOCK_SIZE) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + IdeaFunc(workingKey, input, inOff, output, outOff); return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } private static readonly int MASK = 0xffff; diff --git a/crypto/src/crypto/engines/IesEngine.cs b/crypto/src/crypto/engines/IesEngine.cs index 70df3077c..961e3b038 100644 --- a/crypto/src/crypto/engines/IesEngine.cs +++ b/crypto/src/crypto/engines/IesEngine.cs @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param pubParam the recipient's/sender's public key parameters * @param param encoding and derivation parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters privParameters, ICipherParameters pubParameters, @@ -213,7 +213,7 @@ namespace Org.BouncyCastle.Crypto.Engines return buf; } - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] input, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/NaccacheSternEngine.cs b/crypto/src/crypto/engines/NaccacheSternEngine.cs index 9ca092351..e547e0caf 100644 --- a/crypto/src/crypto/engines/NaccacheSternEngine.cs +++ b/crypto/src/crypto/engines/NaccacheSternEngine.cs @@ -33,7 +33,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool, * org.bouncycastle.crypto.CipherParameters) */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public bool Debug + public virtual bool Debug { set { this.debug = value; } } @@ -93,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetInputBlockSize() */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetOutputBlockSize() */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @see org.bouncycastle.crypto.AsymmetricBlockCipher#ProcessBlock(byte[], * int, int) */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBytes, int inOff, int length) @@ -245,7 +245,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return The byte[] representation of the encrypted BigInteger (i.e. * crypted.toByteArray()) */ - public byte[] Encrypt( + public virtual byte[] Encrypt( BigInteger plain) { // Always return modulus size values 0-padded at the beginning @@ -273,7 +273,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return encrypt((block1 + block2) mod sigma) * @throws InvalidCipherTextException */ - public byte[] AddCryptedBlocks( + public virtual byte[] AddCryptedBlocks( byte[] block1, byte[] block2) { @@ -329,7 +329,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the data after it went through the NaccacheSternEngine. * @throws InvalidCipherTextException */ - public byte[] ProcessData( + public virtual byte[] ProcessData( byte[] data) { if (debug) diff --git a/crypto/src/crypto/engines/NoekeonEngine.cs b/crypto/src/crypto/engines/NoekeonEngine.cs index b73e696a9..dd78a4ea5 100644 --- a/crypto/src/crypto/engines/NoekeonEngine.cs +++ b/crypto/src/crypto/engines/NoekeonEngine.cs @@ -42,17 +42,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Noekeon"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return GenericSize; } @@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -88,17 +88,16 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + GenericSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + GenericSize) > output.Length) - throw new DataLengthException("output buffer too short"); - return _forEncryption + Check.DataLength(input, inOff, GenericSize, "input buffer too short"); + Check.OutputLength(output, outOff, GenericSize, "output buffer too short"); + + return _forEncryption ? encryptBlock(input, inOff, output, outOff) : decryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { // TODO This should do something in case the encryption is aborted } diff --git a/crypto/src/crypto/engines/NullEngine.cs b/crypto/src/crypto/engines/NullEngine.cs index 407b8ccc6..f883b7c29 100644 --- a/crypto/src/crypto/engines/NullEngine.cs +++ b/crypto/src/crypto/engines/NullEngine.cs @@ -18,7 +18,7 @@ namespace Org.BouncyCastle.Crypto.Engines { } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -26,22 +26,22 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = true; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Null"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return true; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -49,12 +49,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (!initialised) throw new InvalidOperationException("Null engine not initialised"); - if ((inOff + BlockSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BlockSize) > output.Length) - throw new DataLengthException("output buffer too short"); - for (int i = 0; i < BlockSize; ++i) + Check.DataLength(input, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(output, outOff, BlockSize, "output buffer too short"); + + for (int i = 0; i < BlockSize; ++i) { output[outOff + i] = input[inOff + i]; } @@ -62,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BlockSize; } - public void Reset() + public virtual void Reset() { // nothing needs to be done } diff --git a/crypto/src/crypto/engines/RC2Engine.cs b/crypto/src/crypto/engines/RC2Engine.cs index aaf8c714c..b56953de5 100644 --- a/crypto/src/crypto/engines/RC2Engine.cs +++ b/crypto/src/crypto/engines/RC2Engine.cs @@ -114,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -139,26 +139,26 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC2"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -166,12 +166,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("RC2 engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -308,5 +307,4 @@ namespace Org.BouncyCastle.Crypto.Engines outBytes[outOff + 7] = (byte)(x76 >> 8); } } - } diff --git a/crypto/src/crypto/engines/RC2WrapEngine.cs b/crypto/src/crypto/engines/RC2WrapEngine.cs index 238c9f76a..5742aa8b7 100644 --- a/crypto/src/crypto/engines/RC2WrapEngine.cs +++ b/crypto/src/crypto/engines/RC2WrapEngine.cs @@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forWrapping * @param param */ - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -101,7 +101,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return */ - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC2"; } } @@ -114,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param inLen * @return */ - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int length) @@ -215,7 +215,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @throws InvalidCipherTextException */ - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/engines/RC4Engine.cs b/crypto/src/crypto/engines/RC4Engine.cs index c65468d93..fd84b7d23 100644 --- a/crypto/src/crypto/engines/RC4Engine.cs +++ b/crypto/src/crypto/engines/RC4Engine.cs @@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -47,12 +47,12 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("invalid parameter passed to RC4 init - " + parameters.GetType().ToString()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC4"; } } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { x = (x + 1) & 0xff; @@ -67,23 +67,15 @@ namespace Org.BouncyCastle.Crypto.Engines return (byte)(input ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] input, int inOff, int length, byte[] output, - int outOff - ) + int outOff) { - if ((inOff + length) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + length) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, length, "input buffer too short"); + Check.OutputLength(output, outOff, length, "output buffer too short"); for (int i = 0; i < length ; i++) { @@ -101,7 +93,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { SetKey(workingKey); } @@ -143,5 +135,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RC532Engine.cs b/crypto/src/crypto/engines/RC532Engine.cs index 1661707ef..169a60b98 100644 --- a/crypto/src/crypto/engines/RC532Engine.cs +++ b/crypto/src/crypto/engines/RC532Engine.cs @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC5-32"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 2 * 4; } @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -97,7 +97,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.forEncryption = forEncryption; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -108,7 +108,7 @@ namespace Org.BouncyCastle.Crypto.Engines : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -290,5 +290,4 @@ namespace Org.BouncyCastle.Crypto.Engines dst[dstOff + 3] = (byte)(word >> 24); } } - } diff --git a/crypto/src/crypto/engines/RC564Engine.cs b/crypto/src/crypto/engines/RC564Engine.cs index 5c69d40ff..ddcce0fa8 100644 --- a/crypto/src/crypto/engines/RC564Engine.cs +++ b/crypto/src/crypto/engines/RC564Engine.cs @@ -51,17 +51,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC5-64"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 2 * bytesPerWord; } @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Engines SetKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -102,7 +102,7 @@ namespace Org.BouncyCastle.Crypto.Engines : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -291,5 +291,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RC6Engine.cs b/crypto/src/crypto/engines/RC6Engine.cs index d72cc2f7b..196bd8394 100644 --- a/crypto/src/crypto/engines/RC6Engine.cs +++ b/crypto/src/crypto/engines/RC6Engine.cs @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines // _S = null; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "RC6"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return 4 * bytesPerWord; } @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -84,7 +84,7 @@ namespace Org.BouncyCastle.Crypto.Engines SetKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -93,17 +93,16 @@ namespace Org.BouncyCastle.Crypto.Engines int blockSize = GetBlockSize(); if (_S == null) throw new InvalidOperationException("RC6 engine not initialised"); - if ((inOff + blockSize) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + blockSize) > output.Length) - throw new DataLengthException("output buffer too short"); - return (forEncryption) + Check.DataLength(input, inOff, blockSize, "input buffer too short"); + Check.OutputLength(output, outOff, blockSize, "output buffer too short"); + + return (forEncryption) ? EncryptBlock(input, inOff, output, outOff) : DecryptBlock(input, inOff, output, outOff); } - public void Reset() + public virtual void Reset() { } @@ -358,5 +357,4 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - } diff --git a/crypto/src/crypto/engines/RFC3211WrapEngine.cs b/crypto/src/crypto/engines/RFC3211WrapEngine.cs index e520075f9..4e3af5227 100644 --- a/crypto/src/crypto/engines/RFC3211WrapEngine.cs +++ b/crypto/src/crypto/engines/RFC3211WrapEngine.cs @@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.engine = new CbcBlockCipher(engine); } - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters param) { @@ -48,12 +48,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return engine.GetUnderlyingCipher().AlgorithmName + "/RFC3211Wrap"; } } - public byte[] Wrap( + public virtual byte[] Wrap( byte[] inBytes, int inOff, int inLen) @@ -99,7 +99,7 @@ namespace Org.BouncyCastle.Crypto.Engines return cekBlock; } - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] inBytes, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RFC3394WrapEngine.cs b/crypto/src/crypto/engines/RFC3394WrapEngine.cs index 5615a63e5..4bb0e2114 100644 --- a/crypto/src/crypto/engines/RFC3394WrapEngine.cs +++ b/crypto/src/crypto/engines/RFC3394WrapEngine.cs @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.engine = engine; } - public void Init( + public virtual void Init( bool forWrapping, ICipherParameters parameters) { @@ -64,12 +64,12 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return engine.AlgorithmName; } } - public byte[] Wrap( + public virtual byte[] Wrap( byte[] input, int inOff, int inLen) @@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Crypto.Engines return block; } - public byte[] Unwrap( + public virtual byte[] Unwrap( byte[] input, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs index cdf69ddda..037abf7e9 100644 --- a/crypto/src/crypto/engines/RSABlindedEngine.cs +++ b/crypto/src/crypto/engines/RSABlindedEngine.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Crypto.Engines private RsaKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters param) { @@ -55,7 +55,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -81,7 +81,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSABlindingEngine.cs b/crypto/src/crypto/engines/RSABlindingEngine.cs index 76b57a3f7..c636627bf 100644 --- a/crypto/src/crypto/engines/RSABlindingEngine.cs +++ b/crypto/src/crypto/engines/RSABlindingEngine.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines private bool forEncryption; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting (blinding), false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters param) { @@ -63,7 +63,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -89,7 +89,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @throws DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/RSACoreEngine.cs b/crypto/src/crypto/engines/RSACoreEngine.cs index 4e64d25d6..38326371f 100644 --- a/crypto/src/crypto/engines/RSACoreEngine.cs +++ b/crypto/src/crypto/engines/RSACoreEngine.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { if (forEncryption) { @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { if (forEncryption) { @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Crypto.Engines return (bitSize - 1) / 8; } - public BigInteger ConvertInput( + public virtual BigInteger ConvertInput( byte[] inBuf, int inOff, int inLen) @@ -90,7 +90,7 @@ namespace Org.BouncyCastle.Crypto.Engines return input; } - public byte[] ConvertOutput( + public virtual byte[] ConvertOutput( BigInteger result) { byte[] output = result.ToByteArrayUnsigned(); @@ -112,7 +112,7 @@ namespace Org.BouncyCastle.Crypto.Engines return output; } - public BigInteger ProcessBlock( + public virtual BigInteger ProcessBlock( BigInteger input) { if (key is RsaPrivateCrtKeyParameters) diff --git a/crypto/src/crypto/engines/RijndaelEngine.cs b/crypto/src/crypto/engines/RijndaelEngine.cs index df2e5baea..80f522353 100644 --- a/crypto/src/crypto/engines/RijndaelEngine.cs +++ b/crypto/src/crypto/engines/RijndaelEngine.cs @@ -571,7 +571,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -585,43 +585,34 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("invalid parameter passed to Rijndael init - " + parameters.GetType().ToString()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Rijndael"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BC / 2; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, int outOff) { if (workingKey == null) - { throw new InvalidOperationException("Rijndael engine not initialised"); - } - - if ((inOff + (BC / 2)) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - if ((outOff + (BC / 2)) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, (BC / 2), "input buffer too short"); + Check.OutputLength(output, outOff, (BC / 2), "output buffer too short"); - UnPackBlock(input, inOff); + UnPackBlock(input, inOff); if (forEncryption) { @@ -637,11 +628,11 @@ namespace Org.BouncyCastle.Crypto.Engines return BC / 2; } - public void Reset() + public virtual void Reset() { } - private void UnPackBlock( + private void UnPackBlock( byte[] bytes, int off) { @@ -743,5 +734,4 @@ namespace Org.BouncyCastle.Crypto.Engines KeyAddition(rk[0]); } } - } diff --git a/crypto/src/crypto/engines/RsaEngine.cs b/crypto/src/crypto/engines/RsaEngine.cs index 7e6dfb163..4399b4409 100644 --- a/crypto/src/crypto/engines/RsaEngine.cs +++ b/crypto/src/crypto/engines/RsaEngine.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Engines { private RsaCoreEngine core; - public string AlgorithmName + public virtual string AlgorithmName { get { return "RSA"; } } @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @param forEncryption true if we are encrypting, false otherwise. * @param param the necessary RSA key parameters. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -38,7 +38,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an input block. */ - public int GetInputBlockSize() + public virtual int GetInputBlockSize() { return core.GetInputBlockSize(); } @@ -50,7 +50,7 @@ namespace Org.BouncyCastle.Crypto.Engines * * @return maximum size for an output block. */ - public int GetOutputBlockSize() + public virtual int GetOutputBlockSize() { return core.GetOutputBlockSize(); } @@ -64,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @return the result of the RSA process. * @exception DataLengthException the input block is too large. */ - public byte[] ProcessBlock( + public virtual byte[] ProcessBlock( byte[] inBuf, int inOff, int inLen) diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs index efea0f1fe..f615b8476 100644 --- a/crypto/src/crypto/engines/SEEDEngine.cs +++ b/crypto/src/crypto/engines/SEEDEngine.cs @@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Crypto.Engines private int[] wKey; private bool forEncryption; - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -176,22 +176,22 @@ namespace Org.BouncyCastle.Crypto.Engines wKey = createWorkingKey(((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "SEED"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BlockSize; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBuf, int inOff, byte[] outBuf, @@ -199,12 +199,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (wKey == null) throw new InvalidOperationException("SEED engine not initialised"); - if (inOff + BlockSize > inBuf.Length) - throw new DataLengthException("input buffer too short"); - if (outOff + BlockSize > outBuf.Length) - throw new DataLengthException("output buffer too short"); - long l = bytesToLong(inBuf, inOff + 0); + Check.DataLength(inBuf, inOff, BlockSize, "input buffer too short"); + Check.OutputLength(outBuf, outOff, BlockSize, "output buffer too short"); + + long l = bytesToLong(inBuf, inOff + 0); long r = bytesToLong(inBuf, inOff + 8); if (forEncryption) @@ -234,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BlockSize; } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/Salsa20Engine.cs b/crypto/src/crypto/engines/Salsa20Engine.cs index 81884d603..9b27dc7b4 100644 --- a/crypto/src/crypto/engines/Salsa20Engine.cs +++ b/crypto/src/crypto/engines/Salsa20Engine.cs @@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Engines this.rounds = rounds; } - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -108,7 +108,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public byte ReturnByte( + public virtual byte ReturnByte( byte input) { if (LimitExceeded()) @@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void ProcessBytes( + public virtual void ProcessBytes( byte[] inBytes, int inOff, int len, @@ -144,26 +144,15 @@ namespace Org.BouncyCastle.Crypto.Engines int outOff) { if (!initialised) - { throw new InvalidOperationException(AlgorithmName + " not initialised"); - } - if ((inOff + len) > inBytes.Length) - { - throw new DataLengthException("input buffer too short"); - } + Check.DataLength(inBytes, inOff, len, "input buffer too short"); + Check.OutputLength(outBytes, outOff, len, "output buffer too short"); - if ((outOff + len) > outBytes.Length) - { - throw new DataLengthException("output buffer too short"); - } - - if (LimitExceeded((uint)len)) - { + if (LimitExceeded((uint)len)) throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV"); - } - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { if (index == 0) { @@ -175,7 +164,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public void Reset() + public virtual void Reset() { index = 0; ResetLimitCounter(); diff --git a/crypto/src/crypto/engines/SerpentEngine.cs b/crypto/src/crypto/engines/SerpentEngine.cs index 92b25acc6..255c204ab 100644 --- a/crypto/src/crypto/engines/SerpentEngine.cs +++ b/crypto/src/crypto/engines/SerpentEngine.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -48,17 +48,17 @@ namespace Org.BouncyCastle.Crypto.Engines this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey()); } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Serpent"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } @@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception InvalidOperationException if the cipher isn't initialised. * @return the number of bytes processed and produced. */ - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -84,12 +84,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (wKey == null) throw new InvalidOperationException("Serpent not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -101,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } @@ -775,5 +774,4 @@ namespace Org.BouncyCastle.Crypto.Engines X0 = RotateRight(x0, 13); } } - } diff --git a/crypto/src/crypto/engines/SkipjackEngine.cs b/crypto/src/crypto/engines/SkipjackEngine.cs index 3d2a781e6..a45dc9b24 100644 --- a/crypto/src/crypto/engines/SkipjackEngine.cs +++ b/crypto/src/crypto/engines/SkipjackEngine.cs @@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the parameters argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -71,22 +71,22 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public string AlgorithmName + public virtual string AlgorithmName { get { return "SKIPJACK"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return BLOCK_SIZE; } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] input, int inOff, byte[] output, @@ -94,12 +94,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (key1 == null) throw new InvalidOperationException("SKIPJACK engine not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } @@ -111,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public void Reset() + public virtual void Reset() { } @@ -135,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ((g5 << 8) + g6); } - public int EncryptBlock( + public virtual int EncryptBlock( byte[] input, int inOff, byte[] outBytes, @@ -203,7 +202,7 @@ namespace Org.BouncyCastle.Crypto.Engines return ((h6 << 8) + h5); } - public int DecryptBlock( + public virtual int DecryptBlock( byte[] input, int inOff, byte[] outBytes, @@ -251,5 +250,4 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } } - } diff --git a/crypto/src/crypto/engines/TEAEngine.cs b/crypto/src/crypto/engines/TEAEngine.cs index 582dd0f73..2e1a7002b 100644 --- a/crypto/src/crypto/engines/TEAEngine.cs +++ b/crypto/src/crypto/engines/TEAEngine.cs @@ -36,17 +36,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "TEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return block_size; } @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -77,7 +77,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBytes, int inOff, byte[] outBytes, @@ -86,18 +86,15 @@ namespace Org.BouncyCastle.Crypto.Engines if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + block_size) > inBytes.Length) - throw new DataLengthException("input buffer too short"); + Check.DataLength(inBytes, inOff, block_size, "input buffer too short"); + Check.OutputLength(outBytes, outOff, block_size, "output buffer too short"); - if ((outOff + block_size) > outBytes.Length) - throw new DataLengthException("output buffer too short"); - - return _forEncryption + return _forEncryption ? encryptBlock(inBytes, inOff, outBytes, outOff) : decryptBlock(inBytes, inOff, outBytes, outOff); } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/engines/ThreefishEngine.cs b/crypto/src/crypto/engines/ThreefishEngine.cs index 954470345..33ff3a421 100644 --- a/crypto/src/crypto/engines/ThreefishEngine.cs +++ b/crypto/src/crypto/engines/ThreefishEngine.cs @@ -155,7 +155,7 @@ namespace Org.BouncyCastle.Crypto.Engines /// Initialise for encryption if true, for decryption if false. /// an instance of or (to /// use a 0 tweak) - public void Init(bool forEncryption, ICipherParameters parameters) + public virtual void Init(bool forEncryption, ICipherParameters parameters) { byte[] keyBytes; byte[] tweakBytes; @@ -266,26 +266,26 @@ namespace Org.BouncyCastle.Crypto.Engines t[4] = t[1]; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Threefish-" + (blocksizeBytes * 8); } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return blocksizeBytes; } - public void Reset() + public virtual void Reset() { } - public int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff) + public virtual int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff) { if ((outOff + blocksizeBytes) > outBytes.Length) { diff --git a/crypto/src/crypto/engines/TwofishEngine.cs b/crypto/src/crypto/engines/TwofishEngine.cs index b983d9d31..04a579ced 100644 --- a/crypto/src/crypto/engines/TwofishEngine.cs +++ b/crypto/src/crypto/engines/TwofishEngine.cs @@ -293,12 +293,11 @@ namespace Org.BouncyCastle.Crypto.Engines { if (workingKey == null) throw new InvalidOperationException("Twofish not initialised"); - if ((inOff + BLOCK_SIZE) > input.Length) - throw new DataLengthException("input buffer too short"); - if ((outOff + BLOCK_SIZE) > output.Length) - throw new DataLengthException("output buffer too short"); - if (encrypting) + Check.DataLength(input, inOff, BLOCK_SIZE, "input buffer too short"); + Check.OutputLength(output, outOff, BLOCK_SIZE, "output buffer too short"); + + if (encrypting) { EncryptBlock(input, inOff, output, outOff); } diff --git a/crypto/src/crypto/engines/VMPCEngine.cs b/crypto/src/crypto/engines/VMPCEngine.cs index 1c2802a80..852901e36 100644 --- a/crypto/src/crypto/engines/VMPCEngine.cs +++ b/crypto/src/crypto/engines/VMPCEngine.cs @@ -92,15 +92,8 @@ namespace Org.BouncyCastle.Crypto.Engines byte[] output, int outOff) { - if ((inOff + len) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + len) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.DataLength(input, inOff, len, "input buffer too short"); + Check.OutputLength(output, outOff, len, "output buffer too short"); for (int i = 0; i < len; i++) { diff --git a/crypto/src/crypto/engines/XSalsa20Engine.cs b/crypto/src/crypto/engines/XSalsa20Engine.cs index fc6630905..2898b46c8 100644 --- a/crypto/src/crypto/engines/XSalsa20Engine.cs +++ b/crypto/src/crypto/engines/XSalsa20Engine.cs @@ -13,7 +13,6 @@ namespace Org.BouncyCastle.Crypto.Engines public class XSalsa20Engine : Salsa20Engine { - public override string AlgorithmName { get { return "XSalsa20"; } @@ -65,7 +64,6 @@ namespace Org.BouncyCastle.Crypto.Engines // Counter reset ResetCounter(); } - } } diff --git a/crypto/src/crypto/engines/XTEAEngine.cs b/crypto/src/crypto/engines/XTEAEngine.cs index eb9291775..40d81fbe6 100644 --- a/crypto/src/crypto/engines/XTEAEngine.cs +++ b/crypto/src/crypto/engines/XTEAEngine.cs @@ -34,17 +34,17 @@ namespace Org.BouncyCastle.Crypto.Engines _initialised = false; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "XTEA"; } } - public bool IsPartialBlockOkay + public virtual bool IsPartialBlockOkay { get { return false; } } - public int GetBlockSize() + public virtual int GetBlockSize() { return block_size; } @@ -57,7 +57,7 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public void Init( + public virtual void Init( bool forEncryption, ICipherParameters parameters) { @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Engines setKey(p.GetKey()); } - public int ProcessBlock( + public virtual int ProcessBlock( byte[] inBytes, int inOff, byte[] outBytes, @@ -84,18 +84,15 @@ namespace Org.BouncyCastle.Crypto.Engines if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - if ((inOff + block_size) > inBytes.Length) - throw new DataLengthException("input buffer too short"); + Check.DataLength(inBytes, inOff, block_size, "input buffer too short"); + Check.OutputLength(outBytes, outOff, block_size, "output buffer too short"); - if ((outOff + block_size) > outBytes.Length) - throw new DataLengthException("output buffer too short"); - - return _forEncryption + return _forEncryption ? encryptBlock(inBytes, inOff, outBytes, outOff) : decryptBlock(inBytes, inOff, outBytes, outOff); } - public void Reset() + public virtual void Reset() { } diff --git a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs index e870f1c08..c46865991 100644 --- a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs +++ b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs @@ -11,117 +11,130 @@ namespace Org.BouncyCastle.Crypto.Generators * an RSA key pair generator. */ public class RsaKeyPairGenerator - : IAsymmetricCipherKeyPairGenerator + : IAsymmetricCipherKeyPairGenerator { - private static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); - private const int DefaultTests = 12; + protected static readonly BigInteger One = BigInteger.One; + protected static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); + protected const int DefaultTests = 100; - private RsaKeyGenerationParameters param; + protected RsaKeyGenerationParameters parameters; - public void Init( + public virtual void Init( KeyGenerationParameters parameters) { if (parameters is RsaKeyGenerationParameters) { - this.param = (RsaKeyGenerationParameters)parameters; + this.parameters = (RsaKeyGenerationParameters)parameters; } else { - this.param = new RsaKeyGenerationParameters( + this.parameters = new RsaKeyGenerationParameters( DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests); } } - public AsymmetricCipherKeyPair GenerateKeyPair() + public virtual AsymmetricCipherKeyPair GenerateKeyPair() { - BigInteger p, q, n, d, e, pSub1, qSub1, phi; - - // - // p and q values should have a length of half the strength in bits - // - int strength = param.Strength; - int qBitlength = strength >> 1; - int pBitlength = strength - qBitlength; - int mindiffbits = strength / 3; - int minWeight = strength >> 2; - - e = param.PublicExponent; + for (;;) + { + // + // p and q values should have a length of half the strength in bits + // + int strength = parameters.Strength; + int pbitlength = (strength + 1) / 2; + int qbitlength = strength - pbitlength; + int mindiffbits = strength / 3; + int minWeight = strength >> 2; - // TODO Consider generating safe primes for p, q (see DHParametersHelper.GenerateSafePrimes) - // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") + //// d lower bound is 2^(strength / 2) + //BigInteger dLowerBound = BigInteger.Two.Pow(strength / 2); - p = ChooseRandomPrime(pBitlength, e); + BigInteger e = parameters.PublicExponent; - // - // Generate a modulus of the required length - // - for (;;) - { - q = ChooseRandomPrime(qBitlength, e); + // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) + // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") - // p and q should not be too close together (or equal!) - BigInteger diff = q.Subtract(p).Abs(); - if (diff.BitLength < mindiffbits) - continue; + BigInteger p = ChooseRandomPrime(pbitlength, e); + BigInteger q, n; // - // calculate the modulus + // generate a modulus of the required length // - n = p.Multiply(q); - - if (n.BitLength != strength) + for (;;) { + q = ChooseRandomPrime(qbitlength, e); + + // p and q should not be too close together (or equal!) + BigInteger diff = q.Subtract(p).Abs(); + if (diff.BitLength < mindiffbits) + continue; + // - // if we get here our primes aren't big enough, make the largest - // of the two p and try again + // calculate the modulus // - p = p.Max(q); - continue; + n = p.Multiply(q); + + if (n.BitLength != strength) + { + // + // if we get here our primes aren't big enough, make the largest + // of the two p and try again + // + p = p.Max(q); + continue; + } + + /* + * Require a minimum weight of the NAF representation, since low-weight composites may + * be weak against a version of the number-field-sieve for factoring. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtilities.GetNafWeight(n) < minWeight) + { + p = ChooseRandomPrime(pbitlength, e); + continue; + } + + break; } - /* - * Require a minimum weight of the NAF representation, since low-weight composites may - * be weak against a version of the number-field-sieve for factoring. - * - * See "The number field sieve for integers of low weight", Oliver Schirokauer. - */ - if (WNafUtilities.GetNafWeight(n) < minWeight) + if (p.CompareTo(q) < 0) { - p = ChooseRandomPrime(pBitlength, e); - continue; + BigInteger tmp = p; + p = q; + q = tmp; } - break; - } - - if (p.CompareTo(q) < 0) - { - phi = p; - p = q; - q = phi; - } + BigInteger pSub1 = p.Subtract(One); + BigInteger qSub1 = q.Subtract(One); + BigInteger phi = pSub1.Multiply(qSub1); + //BigInteger lcm = phi.Divide(pSub1.Gcd(qSub1)); - pSub1 = p.Subtract(BigInteger.One); - qSub1 = q.Subtract(BigInteger.One); - phi = pSub1.Multiply(qSub1); + // + // calculate the private exponent + // + //BigInteger d = e.ModInverse(lcm); + BigInteger d = e.ModInverse(phi); - // - // calculate the private exponent - // - d = e.ModInverse(phi); + // if d is less than or equal to dLowerBound, we need to start over + // also, for backward compatibility, if d is not the same as + // e.modInverse(phi), we need to start over - // - // calculate the CRT factors - // - BigInteger dP, dQ, qInv; + if (d.BitLength <= qbitlength)// || !d.Multiply(e).Mod(phi).Equals(One)) + continue; - dP = d.Remainder(pSub1); - dQ = d.Remainder(qSub1); - qInv = q.ModInverse(p); + // + // calculate the CRT factors + // + BigInteger dP = d.Remainder(pSub1); + BigInteger dQ = d.Remainder(qSub1); + BigInteger qInv = q.ModInverse(p); - return new AsymmetricCipherKeyPair( - new RsaKeyParameters(false, n, e), - new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + return new AsymmetricCipherKeyPair( + new RsaKeyParameters(false, n, e), + new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + } } /// Choose a random prime value for use with RSA @@ -132,15 +145,15 @@ namespace Org.BouncyCastle.Crypto.Generators { for (;;) { - BigInteger p = new BigInteger(bitlength, 1, param.Random); + BigInteger p = new BigInteger(bitlength, 1, parameters.Random); - if (p.Mod(e).Equals(BigInteger.One)) + if (p.Mod(e).Equals(One)) continue; - if (!p.IsProbablePrime(param.Certainty)) + if (!p.IsProbablePrime(parameters.Certainty)) continue; - if (!e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One)) + if (!e.Gcd(p.Subtract(One)).Equals(One)) continue; return p; diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs index 653d75cb9..e0b1e6b54 100644 --- a/crypto/src/crypto/modes/CcmBlockCipher.cs +++ b/crypto/src/crypto/modes/CcmBlockCipher.cs @@ -61,6 +61,7 @@ namespace Org.BouncyCastle.Crypto.Modes { this.forEncryption = forEncryption; + ICipherParameters cipherParameters; if (parameters is AeadParameters) { AeadParameters param = (AeadParameters) parameters; @@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Modes nonce = param.GetNonce(); initialAssociatedText = param.GetAssociatedText(); macSize = param.MacSize / 8; - keyParam = param.Key; + cipherParameters = param.Key; } else if (parameters is ParametersWithIV) { @@ -77,17 +78,25 @@ namespace Org.BouncyCastle.Crypto.Modes nonce = param.GetIV(); initialAssociatedText = null; macSize = macBlock.Length / 2; - keyParam = param.Parameters; + cipherParameters = param.Parameters; } else { throw new ArgumentException("invalid parameters passed to CCM"); } + // NOTE: Very basic support for key re-use, but no performance gain from it + if (cipherParameters != null) + { + keyParam = cipherParameters; + } + if (nonce == null || nonce.Length < 7 || nonce.Length > 13) { throw new ArgumentException("nonce must have length from 7 to 13 octets"); } + + Reset(); } public virtual string AlgorithmName @@ -128,6 +137,8 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] outBytes, int outOff) { + Check.DataLength(inBytes, inOff, inLen, "Input buffer too short"); + data.Write(inBytes, inOff, inLen); return 0; @@ -137,13 +148,11 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] outBytes, int outOff) { - byte[] enc = ProcessPacket(data.GetBuffer(), 0, (int)data.Position); - - Array.Copy(enc, 0, outBytes, outOff, enc.Length); + int len = ProcessPacket(data.GetBuffer(), 0, (int)data.Position, outBytes, outOff); Reset(); - return enc.Length; + return len; } public virtual void Reset() @@ -161,11 +170,7 @@ namespace Org.BouncyCastle.Crypto.Modes */ public virtual byte[] GetMac() { - byte[] mac = new byte[macSize]; - - Array.Copy(macBlock, 0, mac, 0, mac.Length); - - return mac; + return Arrays.CopyOfRange(macBlock, 0, macSize); } public virtual int GetUpdateOutputSize( @@ -174,7 +179,7 @@ namespace Org.BouncyCastle.Crypto.Modes return 0; } - public int GetOutputSize( + public virtual int GetOutputSize( int len) { int totalData = (int)data.Length + len; @@ -187,10 +192,51 @@ namespace Org.BouncyCastle.Crypto.Modes return totalData < macSize ? 0 : totalData - macSize; } - public byte[] ProcessPacket( - byte[] input, - int inOff, - int inLen) + /** + * Process a packet of data for either CCM decryption or encryption. + * + * @param in data for processing. + * @param inOff offset at which data starts in the input array. + * @param inLen length of the data in the input array. + * @return a byte array containing the processed input.. + * @throws IllegalStateException if the cipher is not appropriately set up. + * @throws InvalidCipherTextException if the input data is truncated or the mac check fails. + */ + public virtual byte[] ProcessPacket(byte[] input, int inOff, int inLen) + { + byte[] output; + + if (forEncryption) + { + output = new byte[inLen + macSize]; + } + else + { + if (inLen < macSize) + throw new InvalidCipherTextException("data too short"); + + output = new byte[inLen - macSize]; + } + + ProcessPacket(input, inOff, inLen, output, 0); + + return output; + } + + /** + * Process a packet of data for either CCM decryption or encryption. + * + * @param in data for processing. + * @param inOff offset at which data starts in the input array. + * @param inLen length of the data in the input array. + * @param output output array. + * @param outOff offset into output array to start putting processed bytes. + * @return the number of bytes added to output. + * @throws IllegalStateException if the cipher is not appropriately set up. + * @throws InvalidCipherTextException if the input data is truncated or the mac check fails. + * @throws DataLengthException if output buffer too short. + */ + public virtual int ProcessPacket(byte[] input, int inOff, int inLen, byte[] output, int outOff) { // TODO: handle null keyParam (e.g. via RepeatedKeySpec) // Need to keep the CTR and CBC Mac parts around and reset @@ -213,42 +259,45 @@ namespace Org.BouncyCastle.Crypto.Modes IBlockCipher ctrCipher = new SicBlockCipher(cipher); ctrCipher.Init(forEncryption, new ParametersWithIV(keyParam, iv)); - int index = inOff; - int outOff = 0; - byte[] output; + int outputLen; + int inIndex = inOff; + int outIndex = outOff; if (forEncryption) { - output = new byte[inLen + macSize]; + outputLen = inLen + macSize; + Check.OutputLength(output, outOff, outputLen, "Output buffer too short."); calculateMac(input, inOff, inLen, macBlock); ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); // S0 - while (index < inLen - BlockSize) // S1... + while (inIndex < (inOff + inLen - BlockSize)) // S1... { - ctrCipher.ProcessBlock(input, index, output, outOff); - outOff += BlockSize; - index += BlockSize; + ctrCipher.ProcessBlock(input, inIndex, output, outIndex); + outIndex += BlockSize; + inIndex += BlockSize; } byte[] block = new byte[BlockSize]; - Array.Copy(input, index, block, 0, inLen - index); + Array.Copy(input, inIndex, block, 0, inLen + inOff - inIndex); ctrCipher.ProcessBlock(block, 0, block, 0); - Array.Copy(block, 0, output, outOff, inLen - index); + Array.Copy(block, 0, output, outIndex, inLen + inOff - inIndex); - outOff += inLen - index; - - Array.Copy(macBlock, 0, output, outOff, output.Length - outOff); + Array.Copy(macBlock, 0, output, outOff + inLen, macSize); } else { - output = new byte[inLen - macSize]; + if (inLen < macSize) + throw new InvalidCipherTextException("data too short"); - Array.Copy(input, inOff + inLen - macSize, macBlock, 0, macSize); + outputLen = inLen - macSize; + Check.OutputLength(output, outOff, outputLen, "Output buffer too short."); + + Array.Copy(input, inOff + outputLen, macBlock, 0, macSize); ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0); @@ -257,30 +306,30 @@ namespace Org.BouncyCastle.Crypto.Modes macBlock[i] = 0; } - while (outOff < output.Length - BlockSize) + while (inIndex < (inOff + outputLen - BlockSize)) { - ctrCipher.ProcessBlock(input, index, output, outOff); - outOff += BlockSize; - index += BlockSize; + ctrCipher.ProcessBlock(input, inIndex, output, outIndex); + outIndex += BlockSize; + inIndex += BlockSize; } byte[] block = new byte[BlockSize]; - Array.Copy(input, index, block, 0, output.Length - outOff); + Array.Copy(input, inIndex, block, 0, outputLen - (inIndex - inOff)); ctrCipher.ProcessBlock(block, 0, block, 0); - Array.Copy(block, 0, output, outOff, output.Length - outOff); + Array.Copy(block, 0, output, outIndex, outputLen - (inIndex - inOff)); byte[] calculatedMacBlock = new byte[BlockSize]; - calculateMac(output, 0, output.Length, calculatedMacBlock); + calculateMac(output, outOff, outputLen, calculatedMacBlock); if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock)) throw new InvalidCipherTextException("mac check in CCM failed"); } - return output; + return outputLen; } private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock) diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs index 5ccc69b66..624f385b5 100644 --- a/crypto/src/crypto/modes/EAXBlockCipher.cs +++ b/crypto/src/crypto/modes/EAXBlockCipher.cs @@ -54,7 +54,6 @@ namespace Org.BouncyCastle.Crypto.Modes blockSize = cipher.GetBlockSize(); mac = new CMac(cipher); macBlock = new byte[blockSize]; - bufBlock = new byte[blockSize * 2]; associatedTextMac = new byte[mac.GetMacSize()]; nonceMac = new byte[mac.GetMacSize()]; this.cipher = new SicBlockCipher(cipher); @@ -65,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Modes get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; } } - public IBlockCipher GetUnderlyingCipher() + public virtual IBlockCipher GetUnderlyingCipher() { return cipher; } @@ -107,6 +106,8 @@ namespace Org.BouncyCastle.Crypto.Modes throw new ArgumentException("invalid parameters passed to EAX"); } + bufBlock = new byte[forEncryption ? blockSize : (blockSize + macSize)]; + byte[] tag = new byte[blockSize]; // Key reuse implemented in CBC mode of underlying CMac @@ -117,16 +118,10 @@ namespace Org.BouncyCastle.Crypto.Modes mac.BlockUpdate(nonce, 0, nonce.Length); mac.DoFinal(nonceMac, 0); - tag[blockSize - 1] = (byte)Tag.H; - mac.BlockUpdate(tag, 0, blockSize); - - if (initialAssociatedText != null) - { - ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length); - } - - // Same BlockCipher underlies this and the mac, so reuse last key on cipher + // Same BlockCipher underlies this and the mac, so reuse last key on cipher cipher.Init(true, new ParametersWithIV(null, nonceMac)); + + Reset(); } private void InitCipher() @@ -191,16 +186,16 @@ namespace Org.BouncyCastle.Crypto.Modes { if (cipherInitialized) { - throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); } mac.Update(input); } - public void ProcessAadBytes(byte[] inBytes, int inOff, int len) + public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) { if (cipherInitialized) { - throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun."); + throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); } mac.BlockUpdate(inBytes, inOff, len); } @@ -247,10 +242,11 @@ namespace Org.BouncyCastle.Crypto.Modes if (forEncryption) { - cipher.ProcessBlock(bufBlock, 0, tmp, 0); - cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); + Check.OutputLength(outBytes, outOff, extra + macSize, "Output buffer too short"); + + cipher.ProcessBlock(bufBlock, 0, tmp, 0); - Array.Copy(tmp, 0, outBytes, outOff, extra); + Array.Copy(tmp, 0, outBytes, outOff, extra); mac.BlockUpdate(tmp, 0, extra); @@ -264,14 +260,18 @@ namespace Org.BouncyCastle.Crypto.Modes } else { - if (extra > macSize) + if (extra < macSize) + throw new InvalidCipherTextException("data too short"); + + Check.OutputLength(outBytes, outOff, extra - macSize, "Output buffer too short"); + + if (extra > macSize) { mac.BlockUpdate(bufBlock, 0, extra - macSize); cipher.ProcessBlock(bufBlock, 0, tmp, 0); - cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize); - Array.Copy(tmp, 0, outBytes, outOff, extra - macSize); + Array.Copy(tmp, 0, outBytes, outOff, extra - macSize); } CalculateMac(); @@ -331,6 +331,11 @@ namespace Org.BouncyCastle.Crypto.Modes if (bufOff == bufBlock.Length) { + Check.OutputLength(outBytes, outOff, blockSize, "Output buffer is too short"); + + // TODO Could move the ProcessByte(s) calls to here +// InitCipher(); + int size; if (forEncryption) @@ -346,10 +351,14 @@ namespace Org.BouncyCastle.Crypto.Modes size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff); } - bufOff = blockSize; - Array.Copy(bufBlock, blockSize, bufBlock, 0, blockSize); + bufOff = 0; + if (!forEncryption) + { + Array.Copy(bufBlock, blockSize, bufBlock, 0, macSize); + bufOff = macSize; + } - return size; + return size; } return 0; diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs index 2e2ac2eca..8e6120eef 100644 --- a/crypto/src/crypto/modes/GCMBlockCipher.cs +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -284,6 +284,9 @@ namespace Org.BouncyCastle.Crypto.Modes byte[] output, int outOff) { + if (input.Length < (inOff + len)) + throw new DataLengthException("Input buffer too short"); + int resultLen = 0; for (int i = 0; i < len; ++i) @@ -301,6 +304,7 @@ namespace Org.BouncyCastle.Crypto.Modes private void OutputBlock(byte[] output, int offset) { + Check.OutputLength(output, offset, BlockSize, "Output buffer too short"); if (totalLength == 0) { InitCipher(); @@ -325,12 +329,19 @@ namespace Org.BouncyCastle.Crypto.Modes } int extra = bufOff; - if (!forEncryption) + + if (forEncryption) + { + Check.OutputLength(output, outOff, extra + macSize, "Output buffer too short"); + } + else { if (extra < macSize) throw new InvalidCipherTextException("data too short"); extra -= macSize; + + Check.OutputLength(output, outOff, extra, "Output buffer too short"); } if (extra > 0) diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs index 54359dfe8..e7dc466e6 100644 --- a/crypto/src/crypto/modes/OCBBlockCipher.cs +++ b/crypto/src/crypto/modes/OCBBlockCipher.cs @@ -355,6 +355,7 @@ namespace Org.BouncyCastle.Crypto.Modes Xor(mainBlock, Pad); + Check.OutputLength(output, outOff, mainBlockPos, "Output buffer too short"); Array.Copy(mainBlock, 0, output, outOff, mainBlockPos); if (!forEncryption) @@ -382,6 +383,8 @@ namespace Org.BouncyCastle.Crypto.Modes if (forEncryption) { + Check.OutputLength(output, outOff, resultLen + macSize, "Output buffer too short"); + // Append tag to the message Array.Copy(macBlock, 0, output, outOff + resultLen, macSize); resultLen += macSize; @@ -431,6 +434,8 @@ namespace Org.BouncyCastle.Crypto.Modes protected virtual void ProcessMainBlock(byte[] output, int outOff) { + Check.DataLength(output, outOff, BLOCK_SIZE, "Output buffer too short"); + /* * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks */ diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs index 0f241035f..de41d88f4 100644 --- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -106,6 +106,29 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm x[3] = r13; } + internal static void Multiply(ulong[] x, ulong[] y) + { + ulong r00 = x[0], r01 = x[1], r10 = 0, r11 = 0; + + for (int i = 0; i < 2; ++i) + { + long bits = (long)y[i]; + for (int j = 0; j < 64; ++j) + { + ulong m1 = (ulong)(bits >> 63); bits <<= 1; + r10 ^= (r00 & m1); + r11 ^= (r01 & m1); + + ulong m2 = (r01 << 63) >> 8; + r01 = (r01 >> 1) | (r00 << 63); + r00 = (r00 >> 1) ^ (m2 & E1L); + } + } + + x[0] = r10; + x[1] = r11; + } + // P is the value with only bit i=1 set internal static void MultiplyP(uint[] x) { diff --git a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs index fb8a92ba3..c291e4814 100644 --- a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs +++ b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs @@ -178,10 +178,7 @@ namespace Org.BouncyCastle.Crypto.Paddings if (outLength > 0) { - if ((outOff + outLength) > output.Length) - { - throw new DataLengthException("output buffer too short"); - } + Check.OutputLength(output, outOff, outLength, "output buffer too short"); } int resultLen = 0; @@ -242,7 +239,7 @@ namespace Org.BouncyCastle.Crypto.Paddings { Reset(); - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } resultLen = cipher.ProcessBlock(buf, 0, output, outOff); diff --git a/crypto/test/src/crypto/test/CCMTest.cs b/crypto/test/src/crypto/test/CCMTest.cs index 4a54fb4f9..8c46e11e7 100644 --- a/crypto/test/src/crypto/test/CCMTest.cs +++ b/crypto/test/src/crypto/test/CCMTest.cs @@ -81,7 +81,38 @@ namespace Org.BouncyCastle.Crypto.Tests // checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5); - // + // decryption with output specified, non-zero offset. + ccm.Init(false, new AeadParameters(new KeyParameter(K2), 48, N2, A2)); + + byte[] inBuf = new byte[C2.Length + 10]; + byte[] outBuf = new byte[ccm.GetOutputSize(C2.Length) + 10]; + + Array.Copy(C2, 0, inBuf, 10, C2.Length); + + int len = ccm.ProcessPacket(inBuf, 10, C2.Length, outBuf, 10); + byte[] output = ccm.ProcessPacket(C2, 0, C2.Length); + + if (len != output.Length || !isEqual(output, outBuf, 10)) + { + Fail("decryption output incorrect"); + } + + // encryption with output specified, non-zero offset. + ccm.Init(true, new AeadParameters(new KeyParameter(K2), 48, N2, A2)); + + int inLen = len; + inBuf = outBuf; + outBuf = new byte[ccm.GetOutputSize(inLen) + 10]; + + len = ccm.ProcessPacket(inBuf, 10, inLen, outBuf, 10); + output = ccm.ProcessPacket(inBuf, 10, inLen); + + if (len != output.Length || !isEqual(output, outBuf, 10)) + { + Fail("encryption output incorrect"); + } + + // // exception tests // @@ -121,6 +152,17 @@ namespace Org.BouncyCastle.Crypto.Tests } } + private bool isEqual(byte[] exp, byte[] other, int off) + { + for (int i = 0; i != exp.Length; i++) + { + if (exp[i] != other[off + i]) + return false; + } + + return true; + } + private void checkVectors( int count, CcmBlockCipher ccm, @@ -203,7 +245,8 @@ namespace Org.BouncyCastle.Crypto.Tests if (!AreEqual(p, dec)) { - Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType); + Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType, + Hex.ToHexString(p), Hex.ToHexString(dec)); } if (!AreEqual(t, ccm.GetMac())) -- cgit 1.4.1 From cc3e0bb5dc165f33eabfe3f1d1f88aaff4471c5f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sat, 7 Mar 2015 23:18:28 +0700 Subject: Port of some of the TLS tests from Java --- crypto/crypto.csproj | 15 +++ crypto/test/src/crypto/tls/test/PipedStream.cs | 134 +++++++++++++++++++++ crypto/test/src/crypto/tls/test/TlsProtocolTest.cs | 80 ++++++++++++ .../test/src/crypto/tls/test/TlsTestUtilities.cs | 29 +++++ .../crypto/tls/test/UnreliableDatagramTransport.cs | 84 +++++++++++++ 5 files changed, 342 insertions(+) create mode 100644 crypto/test/src/crypto/tls/test/PipedStream.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsProtocolTest.cs create mode 100644 crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 3f713e1c0..7b3dde612 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11010,11 +11010,21 @@ SubType = "Code" BuildAction = "Compile" /> + + + = mOther.mBuf.Position); + return eof ? -1 : mOther.mBuf.GetBuffer()[mReadPos++]; + } + } + + public override void Write(byte[] buf, int off, int len) + { + lock (this) + { + CheckOpen(); + mBuf.Write(buf, off, len); + Monitor.PulseAll(this); + } + } + + public override void WriteByte(byte value) + { + lock (this) + { + CheckOpen(); + mBuf.WriteByte(value); + Monitor.PulseAll(mBuf); + } + } + + private void CheckOpen() + { + if (mClosed) + throw new ObjectDisposedException(this.GetType().Name); + } + + private void WaitForData() + { + while (mReadPos >= mOther.mBuf.Position && !mOther.mClosed) + { + Monitor.Wait(mOther); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs new file mode 100644 index 000000000..4c49420c6 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(server.Run); + serverThread.Start(); + + MockTlsClient client = new MockTlsClient(null); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockTlsServer server = new MockTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs index 272dfd4fd..a76858ce6 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestUtilities.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Globalization; using System.IO; using System.Text; @@ -89,6 +90,34 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm); } + internal static TlsSignerCredentials LoadSignerCredentials(TlsContext context, IList supportedSignatureAlgorithms, + byte signatureAlgorithm, string certResource, string keyResource) + { + /* + * TODO Note that this code fails to provide default value for the client supported + * algorithms if it wasn't sent. + */ + + SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; + if (supportedSignatureAlgorithms != null) + { + foreach (SignatureAndHashAlgorithm alg in supportedSignatureAlgorithms) + { + if (alg.Signature == signatureAlgorithm) + { + signatureAndHashAlgorithm = alg; + break; + } + } + + if (signatureAndHashAlgorithm == null) + return null; + } + + return LoadSignerCredentials(context, new String[]{ certResource, "x509-ca.pem" }, + keyResource, signatureAndHashAlgorithm); + } + internal static Certificate LoadCertificateChain(string[] resources) { X509CertificateStructure[] chain = new X509CertificateStructure[resources.Length]; diff --git a/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs new file mode 100644 index 000000000..b771ab7cf --- /dev/null +++ b/crypto/test/src/crypto/tls/test/UnreliableDatagramTransport.cs @@ -0,0 +1,84 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Utilities.Date; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class UnreliableDatagramTransport + : DatagramTransport + { + private readonly DatagramTransport transport; + private readonly Random random; + private readonly int percentPacketLossReceiving, percentPacketLossSending; + + public UnreliableDatagramTransport(DatagramTransport transport, Random random, + int percentPacketLossReceiving, int percentPacketLossSending) + { + if (percentPacketLossReceiving < 0 || percentPacketLossReceiving > 100) + throw new ArgumentException("out of range", "percentPacketLossReceiving"); + if (percentPacketLossSending < 0 || percentPacketLossSending > 100) + throw new ArgumentException("out of range", "percentPacketLossSending"); + + this.transport = transport; + this.random = random; + this.percentPacketLossReceiving = percentPacketLossReceiving; + this.percentPacketLossSending = percentPacketLossSending; + } + + public virtual int GetReceiveLimit() + { + return transport.GetReceiveLimit(); + } + + public virtual int GetSendLimit() + { + return transport.GetSendLimit(); + } + + public virtual int Receive(byte[] buf, int off, int len, int waitMillis) + { + long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis; + for (;;) + { + int length = transport.Receive(buf, off, len, waitMillis); + if (length < 0 || !LostPacket(percentPacketLossReceiving)) + { + return length; + } + + Console.WriteLine("PACKET LOSS (" + length + " byte packet not received)"); + + long now = DateTimeUtilities.CurrentUnixMs(); + if (now >= endMillis) + { + return -1; + } + + waitMillis = (int)(endMillis - now); + } + } + + public virtual void Send(byte[] buf, int off, int len) + { + if (LostPacket(percentPacketLossSending)) + { + Console.WriteLine("PACKET LOSS (" + len + " byte packet not sent)"); + } + else + { + transport.Send(buf, off, len); + } + } + + public virtual void Close() + { + transport.Close(); + } + + private bool LostPacket(int percentPacketLoss) + { + return percentPacketLoss > 0 && random.Next(100) < percentPacketLoss; + } + } +} -- cgit 1.4.1 From a09bc4ee9aacb569834c18ef81c476dfa70049f9 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 19:35:03 +0700 Subject: Add explicit delegate type to keep .NET 1.1 happy --- crypto/test/src/crypto/tls/test/TlsProtocolTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs index 4c49420c6..ba5b90c75 100644 --- a/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs +++ b/crypto/test/src/crypto/tls/test/TlsProtocolTest.cs @@ -26,7 +26,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests Server server = new Server(serverProtocol); - Thread serverThread = new Thread(server.Run); + Thread serverThread = new Thread(new ThreadStart(server.Run)); serverThread.Start(); MockTlsClient client = new MockTlsClient(null); -- cgit 1.4.1 From 3f4ec01397a4d07b884e2ad48a4fd3c7e56ecf33 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 19:35:54 +0700 Subject: Guard against small private keys, and optimize for common public exponents --- .../src/crypto/generators/RsaKeyPairGenerator.cs | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs index c46865991..2613b902b 100644 --- a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs +++ b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs @@ -4,6 +4,7 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Generators { @@ -13,6 +14,10 @@ namespace Org.BouncyCastle.Crypto.Generators public class RsaKeyPairGenerator : IAsymmetricCipherKeyPairGenerator { + private static readonly int[] SPECIAL_E_VALUES = new int[]{ 3, 5, 17, 257, 65537 }; + private static readonly int SPECIAL_E_HIGHEST = SPECIAL_E_VALUES[SPECIAL_E_VALUES.Length - 1]; + private static readonly int SPECIAL_E_BITS = BigInteger.ValueOf(SPECIAL_E_HIGHEST).BitLength; + protected static readonly BigInteger One = BigInteger.One; protected static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001); protected const int DefaultTests = 100; @@ -41,20 +46,17 @@ namespace Org.BouncyCastle.Crypto.Generators // p and q values should have a length of half the strength in bits // int strength = parameters.Strength; - int pbitlength = (strength + 1) / 2; - int qbitlength = strength - pbitlength; + int pBitlength = (strength + 1) / 2; + int qBitlength = strength - pBitlength; int mindiffbits = strength / 3; int minWeight = strength >> 2; - //// d lower bound is 2^(strength / 2) - //BigInteger dLowerBound = BigInteger.Two.Pow(strength / 2); - BigInteger e = parameters.PublicExponent; // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") - BigInteger p = ChooseRandomPrime(pbitlength, e); + BigInteger p = ChooseRandomPrime(pBitlength, e); BigInteger q, n; // @@ -62,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Generators // for (;;) { - q = ChooseRandomPrime(qbitlength, e); + q = ChooseRandomPrime(qBitlength, e); // p and q should not be too close together (or equal!) BigInteger diff = q.Subtract(p).Abs(); @@ -92,7 +94,7 @@ namespace Org.BouncyCastle.Crypto.Generators */ if (WNafUtilities.GetNafWeight(n) < minWeight) { - p = ChooseRandomPrime(pbitlength, e); + p = ChooseRandomPrime(pBitlength, e); continue; } @@ -108,20 +110,16 @@ namespace Org.BouncyCastle.Crypto.Generators BigInteger pSub1 = p.Subtract(One); BigInteger qSub1 = q.Subtract(One); - BigInteger phi = pSub1.Multiply(qSub1); - //BigInteger lcm = phi.Divide(pSub1.Gcd(qSub1)); + //BigInteger phi = pSub1.Multiply(qSub1); + BigInteger gcd = pSub1.Gcd(qSub1); + BigInteger lcm = pSub1.Divide(gcd).Multiply(qSub1); // // calculate the private exponent // - //BigInteger d = e.ModInverse(lcm); - BigInteger d = e.ModInverse(phi); + BigInteger d = e.ModInverse(lcm); - // if d is less than or equal to dLowerBound, we need to start over - // also, for backward compatibility, if d is not the same as - // e.modInverse(phi), we need to start over - - if (d.BitLength <= qbitlength)// || !d.Multiply(e).Mod(phi).Equals(One)) + if (d.BitLength <= qBitlength) continue; // @@ -143,6 +141,8 @@ namespace Org.BouncyCastle.Crypto.Generators /// a prime p, with (p-1) relatively prime to e protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e) { + bool eIsKnownOddPrime = (e.BitLength <= SPECIAL_E_BITS) && Arrays.Contains(SPECIAL_E_VALUES, e.IntValue); + for (;;) { BigInteger p = new BigInteger(bitlength, 1, parameters.Random); @@ -153,7 +153,7 @@ namespace Org.BouncyCastle.Crypto.Generators if (!p.IsProbablePrime(parameters.Certainty)) continue; - if (!e.Gcd(p.Subtract(One)).Equals(One)) + if (!eIsKnownOddPrime && !e.Gcd(p.Subtract(One)).Equals(One)) continue; return p; -- cgit 1.4.1 From 8f81c8ef78ee6ba47d883ba1f0b6f25912503af0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 19:49:32 +0700 Subject: Add newer TLS test data from Java build --- .gitattributes | 1 + crypto/crypto.csproj | 38 ++++++++++++++++++++++++-- crypto/test/data/tls/x509-client-dsa.pem | 32 ++++++++++++++++++++++ crypto/test/data/tls/x509-client-ecdsa.pem | 17 ++++++++++++ crypto/test/data/tls/x509-client-key-dsa.pem | 15 ++++++++++ crypto/test/data/tls/x509-client-key-ecdsa.pem | 6 ++++ crypto/test/data/tls/x509-server-dsa.pem | 32 ++++++++++++++++++++++ crypto/test/data/tls/x509-server-ecdsa.pem | 17 ++++++++++++ crypto/test/data/tls/x509-server-key-dsa.pem | 15 ++++++++++ crypto/test/data/tls/x509-server-key-ecdsa.pem | 6 ++++ 10 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 crypto/test/data/tls/x509-client-dsa.pem create mode 100644 crypto/test/data/tls/x509-client-ecdsa.pem create mode 100644 crypto/test/data/tls/x509-client-key-dsa.pem create mode 100644 crypto/test/data/tls/x509-client-key-ecdsa.pem create mode 100644 crypto/test/data/tls/x509-server-dsa.pem create mode 100644 crypto/test/data/tls/x509-server-ecdsa.pem create mode 100644 crypto/test/data/tls/x509-server-key-dsa.pem create mode 100644 crypto/test/data/tls/x509-server-key-ecdsa.pem (limited to 'crypto') diff --git a/.gitattributes b/.gitattributes index ba5445104..14f495692 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,6 +14,7 @@ *.pem text *.README text *.sln text +*.tmpl text *.txt text *.xml text diff=xml diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 7b3dde612..66a50bb39 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -9913,12 +9913,24 @@ RelPath = "test\data\scrypt\TestVectors.txt" BuildAction = "EmbeddedResource" /> + + + + + + + + Date: Sun, 8 Mar 2015 20:05:10 +0700 Subject: Clear the shared secret after use --- crypto/src/crypto/engines/IesEngine.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/engines/IesEngine.cs b/crypto/src/crypto/engines/IesEngine.cs index 961e3b038..a2004a9d6 100644 --- a/crypto/src/crypto/engines/IesEngine.cs +++ b/crypto/src/crypto/engines/IesEngine.cs @@ -224,10 +224,16 @@ namespace Org.BouncyCastle.Crypto.Engines byte[] zBytes = BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z); - return forEncryption - ? EncryptBlock(input, inOff, inLen, zBytes) - : DecryptBlock(input, inOff, inLen, zBytes); + try + { + return forEncryption + ? EncryptBlock(input, inOff, inLen, zBytes) + : DecryptBlock(input, inOff, inLen, zBytes); + } + finally + { + Array.Clear(zBytes, 0, zBytes.Length); + } } } - } -- cgit 1.4.1 From 84c6bf45757b9ede4158ec1226b2eecc4eacdd1a Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 20:07:42 +0700 Subject: Spelling fixes --- crypto/src/crypto/BufferedAeadBlockCipher.cs | 2 +- crypto/src/crypto/BufferedBlockCipher.cs | 2 +- crypto/src/crypto/modes/CtsBlockCipher.cs | 2 +- crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs | 2 +- crypto/src/pkix/PkixParameters.cs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/BufferedAeadBlockCipher.cs b/crypto/src/crypto/BufferedAeadBlockCipher.cs index 04bcb88ed..7ba41090f 100644 --- a/crypto/src/crypto/BufferedAeadBlockCipher.cs +++ b/crypto/src/crypto/BufferedAeadBlockCipher.cs @@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/crypto/BufferedBlockCipher.cs b/crypto/src/crypto/BufferedBlockCipher.cs index 9684ed93e..c87d2daf9 100644 --- a/crypto/src/crypto/BufferedBlockCipher.cs +++ b/crypto/src/crypto/BufferedBlockCipher.cs @@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/crypto/modes/CtsBlockCipher.cs b/crypto/src/crypto/modes/CtsBlockCipher.cs index a32b49675..ff37844ab 100644 --- a/crypto/src/crypto/modes/CtsBlockCipher.cs +++ b/crypto/src/crypto/modes/CtsBlockCipher.cs @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Modes } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs index c291e4814..5d2f8cf15 100644 --- a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs +++ b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Paddings } /** - * process a single byte, producing an output block if neccessary. + * process a single byte, producing an output block if necessary. * * @param in the input byte. * @param out the space for any output that might be produced. diff --git a/crypto/src/pkix/PkixParameters.cs b/crypto/src/pkix/PkixParameters.cs index 6df1b646f..47d3b5e37 100644 --- a/crypto/src/pkix/PkixParameters.cs +++ b/crypto/src/pkix/PkixParameters.cs @@ -745,7 +745,7 @@ namespace Org.BouncyCastle.Pkix } /** - * Returns the neccessary attributes which must be contained in an attribute + * Returns the necessary attributes which must be contained in an attribute * certificate. *

* The returned ISet is immutable and contains @@ -760,7 +760,7 @@ namespace Org.BouncyCastle.Pkix } /** - * Sets the neccessary which must be contained in an attribute certificate. + * Sets the necessary which must be contained in an attribute certificate. *

* The ISet must contain Strings with the * OIDs. -- cgit 1.4.1 From 640f5d3ef1f690c3ddae474ec267dc05ff245667 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 20:44:40 +0700 Subject: Don't override default ciphersuites in test --- crypto/test/src/crypto/tls/test/MockTlsClient.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'crypto') diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index a458e32e6..803989f59 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -45,18 +45,18 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests + ", " + AlertDescription.GetText(alertDescription)); } - public override int[] GetCipherSuites() - { - return Arrays.Concatenate(base.GetCipherSuites(), - new int[] - { - CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, - CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, - CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, - CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, - }); - } + //public override int[] GetCipherSuites() + //{ + // return Arrays.Concatenate(base.GetCipherSuites(), + // new int[] + // { + // CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + // CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + // }); + //} public override IDictionary GetClientExtensions() { -- cgit 1.4.1 From ddb8893eaf2e71e3aeb8bbd9e5cec846050744ac Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 8 Mar 2015 20:46:41 +0700 Subject: Port TLS-PSK tests from Java --- crypto/crypto.csproj | 15 +++ .../test/src/crypto/tls/test/MockPskTlsClient.cs | 132 +++++++++++++++++++++ .../test/src/crypto/tls/test/MockPskTlsServer.cs | 105 ++++++++++++++++ .../test/src/crypto/tls/test/TlsPskProtocolTest.cs | 80 +++++++++++++ 4 files changed, 332 insertions(+) create mode 100644 crypto/test/src/crypto/tls/test/MockPskTlsClient.cs create mode 100644 crypto/test/src/crypto/tls/test/MockPskTlsServer.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 66a50bb39..84844e827 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11032,6 +11032,16 @@ SubType = "Code" BuildAction = "Compile" /> + + + " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + public override int[] GetCipherSuites() + { + return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA }; + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("TLS-PSK client negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + internal class MyTlsAuthentication + : ServerOnlyTlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public override void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("TLS-PSK client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create Fingerprint based on certificate signature algorithm digest + Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs new file mode 100644 index 000000000..7394a2077 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockPskTlsServer.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockPskTlsServer + : PskTlsServer + { + internal MockPskTlsServer() + : base(new MyIdentityManager()) + { + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-PSK server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + byte[] pskIdentity = mContext.SecurityParameters.PskIdentity; + if (pskIdentity != null) + { + string name = Strings.FromUtf8ByteArray(pskIdentity); + Console.WriteLine("TLS-PSK server completed handshake for PSK identity: " + name); + } + } + + protected override int[] GetCipherSuites() + { + return new int[]{ CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA }; + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + Console.WriteLine("TLS-PSK server negotiated " + serverVersion); + + return serverVersion; + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, + "x509-server-key.pem"); + } + + internal class MyIdentityManager + : TlsPskIdentityManager + { + public virtual byte[] GetHint() + { + return Strings.ToUtf8ByteArray("hint"); + } + + public virtual byte[] GetPsk(byte[] identity) + { + if (identity != null) + { + string name = Strings.FromUtf8ByteArray(identity); + if (name.Equals("client")) + { + return new byte[16]; + } + } + return null; + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs new file mode 100644 index 000000000..b059bb2cb --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsPskProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsPskProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + MockPskTlsClient client = new MockPskTlsClient(null); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockPskTlsServer server = new MockPskTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} -- cgit 1.4.1 From f7a9c0a501b6af92d3e729e08c73b5499a500c24 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 01:44:59 +0700 Subject: Porting from Java build - SRP6 evidence messages and standard groups - TLS_SRP server-side support added - TLS_DHE server-side fixes - Improved support for DSA/ECDSA signing in TLS --- crypto/crypto.csproj | 60 ++++++++ crypto/src/crypto/agreement/srp/SRP6Client.cs | 73 ++++++++- crypto/src/crypto/agreement/srp/SRP6Server.cs | 75 +++++++++- .../src/crypto/agreement/srp/SRP6StandardGroups.cs | 159 ++++++++++++++++++++ crypto/src/crypto/agreement/srp/SRP6Utilities.cs | 70 ++++++++- .../crypto/agreement/srp/SRP6VerifierGenerator.cs | 8 +- .../src/crypto/parameters/Srp6GroupParameters.cs | 27 ++++ crypto/src/crypto/tls/AbstractTlsClient.cs | 22 +-- crypto/src/crypto/tls/AbstractTlsKeyExchange.cs | 4 +- crypto/src/crypto/tls/DefaultTlsClient.cs | 9 ++ crypto/src/crypto/tls/DefaultTlsServer.cs | 86 +++++++++++ .../src/crypto/tls/DefaultTlsSrpGroupVerifier.cs | 70 +++++++++ crypto/src/crypto/tls/DtlsClientProtocol.cs | 19 +-- crypto/src/crypto/tls/PskTlsServer.cs | 2 +- crypto/src/crypto/tls/SecurityParameters.cs | 6 + crypto/src/crypto/tls/ServerSrpParams.cs | 75 ++++++++++ crypto/src/crypto/tls/SessionParameters.cs | 20 ++- .../crypto/tls/SimulatedTlsSrpIdentityManager.cs | 69 +++++++++ crypto/src/crypto/tls/SrpTlsClient.cs | 24 ++- crypto/src/crypto/tls/SrpTlsServer.cs | 162 ++++++++++++++++++++ crypto/src/crypto/tls/TlsClientProtocol.cs | 16 +- crypto/src/crypto/tls/TlsDHKeyExchange.cs | 41 ++++-- crypto/src/crypto/tls/TlsDheKeyExchange.cs | 33 ++--- crypto/src/crypto/tls/TlsDsaSigner.cs | 3 +- crypto/src/crypto/tls/TlsECDHKeyExchange.cs | 2 +- crypto/src/crypto/tls/TlsECDheKeyExchange.cs | 26 +--- crypto/src/crypto/tls/TlsProtocol.cs | 2 + crypto/src/crypto/tls/TlsPskKeyExchange.cs | 19 +-- crypto/src/crypto/tls/TlsRsaKeyExchange.cs | 28 ++-- crypto/src/crypto/tls/TlsSrpGroupVerifier.cs | 17 +++ crypto/src/crypto/tls/TlsSrpIdentityManager.cs | 21 +++ crypto/src/crypto/tls/TlsSrpKeyExchange.cs | 164 ++++++++++++++++----- crypto/src/crypto/tls/TlsSrpLoginParameters.cs | 36 +++++ crypto/src/crypto/tls/TlsSrpUtilities.cs | 33 +++++ crypto/src/crypto/tls/TlsUtilities.cs | 41 ++++++ crypto/test/src/crypto/test/SRP6Test.cs | 49 +++--- .../test/src/crypto/tls/test/MockSrpTlsClient.cs | 120 +++++++++++++++ .../test/src/crypto/tls/test/MockSrpTlsServer.cs | 113 ++++++++++++++ crypto/test/src/crypto/tls/test/MockTlsClient.cs | 23 +-- crypto/test/src/crypto/tls/test/MockTlsServer.cs | 49 +----- .../test/src/crypto/tls/test/TlsSrpProtocolTest.cs | 80 ++++++++++ 41 files changed, 1693 insertions(+), 263 deletions(-) create mode 100644 crypto/src/crypto/agreement/srp/SRP6StandardGroups.cs create mode 100644 crypto/src/crypto/parameters/Srp6GroupParameters.cs create mode 100644 crypto/src/crypto/tls/DefaultTlsSrpGroupVerifier.cs create mode 100644 crypto/src/crypto/tls/ServerSrpParams.cs create mode 100644 crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs create mode 100644 crypto/src/crypto/tls/SrpTlsServer.cs create mode 100644 crypto/src/crypto/tls/TlsSrpGroupVerifier.cs create mode 100644 crypto/src/crypto/tls/TlsSrpIdentityManager.cs create mode 100644 crypto/src/crypto/tls/TlsSrpLoginParameters.cs create mode 100644 crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs create mode 100644 crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 84844e827..26af5666f 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -3153,6 +3153,11 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + + + + + + + = 0, "compressionAlgorithm"); Validate(this.mMasterSecret != null, "masterSecret"); return new SessionParameters(mCipherSuite, (byte)mCompressionAlgorithm, mMasterSecret, mPeerCertificate, - mPskIdentity, mEncodedServerExtensions); + mPskIdentity, mSrpIdentity, mEncodedServerExtensions); } public Builder SetCipherSuite(int cipherSuite) @@ -60,6 +61,12 @@ namespace Org.BouncyCastle.Crypto.Tls return this; } + public Builder SetSrpIdentity(byte[] srpIdentity) + { + this.mSrpIdentity = srpIdentity; + return this; + } + public Builder SetServerExtensions(IDictionary serverExtensions) { if (serverExtensions == null) @@ -87,16 +94,18 @@ namespace Org.BouncyCastle.Crypto.Tls private byte[] mMasterSecret; private Certificate mPeerCertificate; private byte[] mPskIdentity; + private byte[] mSrpIdentity; private byte[] mEncodedServerExtensions; private SessionParameters(int cipherSuite, byte compressionAlgorithm, byte[] masterSecret, - Certificate peerCertificate, byte[] pskIdentity, byte[] encodedServerExtensions) + Certificate peerCertificate, byte[] pskIdentity, byte[] srpIdentity, byte[] encodedServerExtensions) { this.mCipherSuite = cipherSuite; this.mCompressionAlgorithm = compressionAlgorithm; this.mMasterSecret = Arrays.Clone(masterSecret); this.mPeerCertificate = peerCertificate; this.mPskIdentity = Arrays.Clone(pskIdentity); + this.mSrpIdentity = Arrays.Clone(srpIdentity); this.mEncodedServerExtensions = encodedServerExtensions; } @@ -111,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Tls public SessionParameters Copy() { return new SessionParameters(mCipherSuite, mCompressionAlgorithm, mMasterSecret, mPeerCertificate, - mPskIdentity, mEncodedServerExtensions); + mPskIdentity, mSrpIdentity, mEncodedServerExtensions); } public int CipherSuite @@ -139,6 +148,11 @@ namespace Org.BouncyCastle.Crypto.Tls get { return mPskIdentity; } } + public byte[] SrpIdentity + { + get { return mSrpIdentity; } + } + public IDictionary ReadServerExtensions() { if (mEncodedServerExtensions == null) diff --git a/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs b/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs new file mode 100644 index 000000000..3e9737cd7 --- /dev/null +++ b/crypto/src/crypto/tls/SimulatedTlsSrpIdentityManager.cs @@ -0,0 +1,69 @@ +using System; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls +{ + /** + * An implementation of {@link TlsSRPIdentityManager} that simulates the existence of "unknown" identities + * to obscure the fact that there is no verifier for them. + */ + public class SimulatedTlsSrpIdentityManager + : TlsSrpIdentityManager + { + private static readonly byte[] PREFIX_PASSWORD = Strings.ToByteArray("password"); + private static readonly byte[] PREFIX_SALT = Strings.ToByteArray("salt"); + + /** + * Create a {@link SimulatedTlsSRPIdentityManager} that implements the algorithm from RFC 5054 2.5.1.3 + * + * @param group the {@link SRP6GroupParameters} defining the group that SRP is operating in + * @param seedKey the secret "seed key" referred to in RFC 5054 2.5.1.3 + * @return an instance of {@link SimulatedTlsSRPIdentityManager} + */ + public static SimulatedTlsSrpIdentityManager GetRfc5054Default(Srp6GroupParameters group, byte[] seedKey) + { + Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator(); + verifierGenerator.Init(group, TlsUtilities.CreateHash(HashAlgorithm.sha1)); + + HMac mac = new HMac(TlsUtilities.CreateHash(HashAlgorithm.sha1)); + mac.Init(new KeyParameter(seedKey)); + + return new SimulatedTlsSrpIdentityManager(group, verifierGenerator, mac); + } + + protected readonly Srp6GroupParameters mGroup; + protected readonly Srp6VerifierGenerator mVerifierGenerator; + protected readonly IMac mMac; + + public SimulatedTlsSrpIdentityManager(Srp6GroupParameters group, Srp6VerifierGenerator verifierGenerator, IMac mac) + { + this.mGroup = group; + this.mVerifierGenerator = verifierGenerator; + this.mMac = mac; + } + + public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity) + { + mMac.BlockUpdate(PREFIX_SALT, 0, PREFIX_SALT.Length); + mMac.BlockUpdate(identity, 0, identity.Length); + + byte[] salt = new byte[mMac.GetMacSize()]; + mMac.DoFinal(salt, 0); + + mMac.BlockUpdate(PREFIX_PASSWORD, 0, PREFIX_PASSWORD.Length); + mMac.BlockUpdate(identity, 0, identity.Length); + + byte[] password = new byte[mMac.GetMacSize()]; + mMac.DoFinal(password, 0); + + BigInteger verifier = mVerifierGenerator.GenerateVerifier(salt, identity, password); + + return new TlsSrpLoginParameters(mGroup, verifier, salt); + } + } +} diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs index 5d82ed470..bed6a8f0c 100644 --- a/crypto/src/crypto/tls/SrpTlsClient.cs +++ b/crypto/src/crypto/tls/SrpTlsClient.cs @@ -6,20 +6,29 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Tls { - public abstract class SrpTlsClient + public class SrpTlsClient : AbstractTlsClient { + protected TlsSrpGroupVerifier mGroupVerifier; + protected byte[] mIdentity; protected byte[] mPassword; public SrpTlsClient(byte[] identity, byte[] password) - : this(new DefaultTlsCipherFactory(), identity, password) + : this(new DefaultTlsCipherFactory(), new DefaultTlsSrpGroupVerifier(), identity, password) { } public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password) + : this(cipherFactory, new DefaultTlsSrpGroupVerifier(), identity, password) + { + } + + public SrpTlsClient(TlsCipherFactory cipherFactory, TlsSrpGroupVerifier groupVerifier, + byte[] identity, byte[] password) : base(cipherFactory) { + this.mGroupVerifier = groupVerifier; this.mIdentity = Arrays.Clone(identity); this.mPassword = Arrays.Clone(password); } @@ -86,6 +95,15 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public override TlsAuthentication GetAuthentication() + { + /* + * Note: This method is not called unless a server certificate is sent, which may be the + * case e.g. for SRP_DSS or SRP_RSA key exchange. + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + public override TlsCipher GetCipher() { switch (mSelectedCipherSuite) @@ -117,7 +135,7 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) { - return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mIdentity, mPassword); + return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mGroupVerifier, mIdentity, mPassword); } } } diff --git a/crypto/src/crypto/tls/SrpTlsServer.cs b/crypto/src/crypto/tls/SrpTlsServer.cs new file mode 100644 index 000000000..1bd6b3af4 --- /dev/null +++ b/crypto/src/crypto/tls/SrpTlsServer.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class SrpTlsServer + : AbstractTlsServer + { + protected TlsSrpIdentityManager mSrpIdentityManager; + + protected byte[] mSrpIdentity = null; + protected TlsSrpLoginParameters mLoginParameters = null; + + public SrpTlsServer(TlsSrpIdentityManager srpIdentityManager) + : this(new DefaultTlsCipherFactory(), srpIdentityManager) + { + } + + public SrpTlsServer(TlsCipherFactory cipherFactory, TlsSrpIdentityManager srpIdentityManager) + : base(cipherFactory) + { + this.mSrpIdentityManager = srpIdentityManager; + } + + protected virtual TlsSignerCredentials GetDsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + protected virtual TlsSignerCredentials GetRsaSignerCredentials() + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + protected override int[] GetCipherSuites() + { + return new int[] + { + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA + }; + } + + public override void ProcessClientExtensions(IDictionary clientExtensions) + { + base.ProcessClientExtensions(clientExtensions); + + this.mSrpIdentity = TlsSrpUtilities.GetSrpExtension(clientExtensions); + } + + public override int GetSelectedCipherSuite() + { + int cipherSuite = base.GetSelectedCipherSuite(); + + if (TlsSrpUtilities.IsSrpCipherSuite(cipherSuite)) + { + if (mSrpIdentity != null) + { + this.mLoginParameters = mSrpIdentityManager.GetLoginParameters(mSrpIdentity); + } + + if (mLoginParameters == null) + throw new TlsFatalAlert(AlertDescription.unknown_psk_identity); + } + + return cipherSuite; + } + + public override TlsCredentials GetCredentials() + { + switch (mSelectedCipherSuite) + { + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return null; + + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + return GetDsaSignerCredentials(); + + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + return GetRsaSignerCredentials(); + + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public override TlsKeyExchange GetKeyExchange() + { + switch (mSelectedCipherSuite) + { + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP); + + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA); + + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS); + + default: + /* + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public override TlsCipher GetCipher() + { + switch (mSelectedCipherSuite) + { + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); + + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); + + default: + /* + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) + { + return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mSrpIdentity, mLoginParameters); + } + } +} diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 0c35e62af..1bd0653a6 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -373,21 +373,17 @@ namespace Org.BouncyCastle.Crypto.Tls /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - byte[] hash; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + Context, signerCredentials); - if (TlsUtilities.IsTlsV12(Context)) + byte[] hash; + if (signatureAndHashAlgorithm == null) { - signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); + hash = mSecurityParameters.SessionHash; } else { - signatureAndHashAlgorithm = null; - hash = mSecurityParameters.SessionHash; + hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index b831249a6..211249fcc 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -4,6 +4,7 @@ using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Tls @@ -16,12 +17,10 @@ namespace Org.BouncyCastle.Crypto.Tls protected DHParameters mDHParameters; protected AsymmetricKeyParameter mServerPublicKey; - protected DHPublicKeyParameters mDHAgreeServerPublicKey; protected TlsAgreementCredentials mAgreementCredentials; - protected DHPrivateKeyParameters mDHAgreeClientPrivateKey; - protected DHPrivateKeyParameters mDHAgreeServerPrivateKey; - protected DHPublicKeyParameters mDHAgreeClientPublicKey; + protected DHPrivateKeyParameters mDHAgreePrivateKey; + protected DHPublicKeyParameters mDHAgreePublicKey; public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) : base(keyExchange, supportedSignatureAlgorithms) @@ -81,7 +80,7 @@ namespace Org.BouncyCastle.Crypto.Tls { try { - this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey); } catch (InvalidCastException e) { @@ -165,26 +164,40 @@ namespace Org.BouncyCastle.Crypto.Tls */ if (mAgreementCredentials == null) { - this.mDHAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, - mDHAgreeServerPublicKey.Parameters, output); + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, + mDHParameters, output); } } - public override byte[] GeneratePremasterSecret() + public override void ProcessClientCertificate(Certificate clientCertificate) { - if (mAgreementCredentials != null) + // TODO Extract the public key + // TODO If the certificate is 'fixed', take the public key as dhAgreeClientPublicKey + } + + public override void ProcessClientKeyExchange(Stream input) + { + if (mDHAgreePublicKey != null) { - return mAgreementCredentials.GenerateAgreement(mDHAgreeServerPublicKey); + // For dss_fixed_dh and rsa_fixed_dh, the key arrived in the client certificate + return; } - if (mDHAgreeServerPrivateKey != null) + BigInteger Yc = TlsDHUtilities.ReadDHParameter(input); + + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters)); + } + + public override byte[] GeneratePremasterSecret() + { + if (mAgreementCredentials != null) { - return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeClientPublicKey, mDHAgreeServerPrivateKey); + return mAgreementCredentials.GenerateAgreement(mDHAgreePublicKey); } - if (mDHAgreeClientPrivateKey != null) + if (mDHAgreePrivateKey != null) { - return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeServerPublicKey, mDHAgreeClientPrivateKey); + return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey); } throw new TlsFatalAlert(AlertDescription.internal_error); diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index 3c05bb6f0..419d4e442 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -36,30 +36,18 @@ namespace Org.BouncyCastle.Crypto.Tls DigestInputBuffer buf = new DigestInputBuffer(); - this.mDHAgreeServerPrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, this.mDHParameters, buf); /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - IDigest d; - - if (TlsUtilities.IsTlsV12(context)) - { - signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); - } - else - { - signatureAndHashAlgorithm = null; - d = new CombinedHash(); - } - - SecurityParameters securityParameters = context.SecurityParameters; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); + + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); + + SecurityParameters securityParameters = mContext.SecurityParameters; d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); buf.UpdateDigest(d); @@ -76,21 +64,22 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); ServerDHParams dhParams = ServerDHParams.Parse(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); if (!signer.VerifySignature(signed_params.Signature)) throw new TlsFatalAlert(AlertDescription.decrypt_error); - this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); + this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey); + this.mDHParameters = mDHAgreePublicKey.Parameters; } protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm, diff --git a/crypto/src/crypto/tls/TlsDsaSigner.cs b/crypto/src/crypto/tls/TlsDsaSigner.cs index a5ac55974..f0c1e9451 100644 --- a/crypto/src/crypto/tls/TlsDsaSigner.cs +++ b/crypto/src/crypto/tls/TlsDsaSigner.cs @@ -64,8 +64,7 @@ namespace Org.BouncyCastle.Crypto.Tls if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext)) throw new InvalidOperationException(); - // TODO For TLS 1.2+, lift the SHA-1 restriction here - if (algorithm != null && (algorithm.Hash != HashAlgorithm.sha1 || algorithm.Signature != SignatureAlgorithm)) + if (algorithm != null && algorithm.Signature != SignatureAlgorithm) throw new InvalidOperationException(); byte hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.Hash; diff --git a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs index 42dc2f2ef..992be4aca 100644 --- a/crypto/src/crypto/tls/TlsECDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDHKeyExchange.cs @@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Tls { if (mAgreementCredentials == null) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, mServerECPointFormats, mECAgreePublicKey.Parameters, output); } } diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs index b99db0c18..b681aada3 100644 --- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs @@ -36,30 +36,18 @@ namespace Org.BouncyCastle.Crypto.Tls { DigestInputBuffer buf = new DigestInputBuffer(); - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, mNamedCurves, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, mNamedCurves, mClientECPointFormats, buf); /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm; - IDigest d; + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); - if (TlsUtilities.IsTlsV12(context)) - { - signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm; - if (signatureAndHashAlgorithm == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash); - } - else - { - signatureAndHashAlgorithm = null; - d = new CombinedHash(); - } + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); buf.UpdateDigest(d); @@ -76,7 +64,7 @@ namespace Org.BouncyCastle.Crypto.Tls public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = new SignerInputBuffer(); Stream teeIn = new TeeInputStream(input, buf); @@ -85,7 +73,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] point = TlsUtilities.ReadOpaque8(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 1a6e7a3bc..4ea72cd57 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -168,6 +168,8 @@ namespace Org.BouncyCastle.Crypto.Tls .SetCompressionAlgorithm(this.mSecurityParameters.compressionAlgorithm) .SetMasterSecret(this.mSecurityParameters.masterSecret) .SetPeerCertificate(this.mPeerCertificate) + .SetPskIdentity(this.mSecurityParameters.pskIdentity) + .SetSrpIdentity(this.mSecurityParameters.srpIdentity) // TODO Consider filtering extensions that aren't relevant to resumed sessions .SetServerExtensions(this.mServerExtensions) .Build(); diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs index a8d0867ef..0af7f7a69 100644 --- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -99,12 +99,12 @@ namespace Org.BouncyCastle.Crypto.Tls if (this.mDHParameters == null) throw new TlsFatalAlert(AlertDescription.internal_error); - this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, this.mDHParameters, buf); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralServerKeyExchange(mContext.SecureRandom, mNamedCurves, mClientECPointFormats, buf); } @@ -165,6 +165,7 @@ namespace Org.BouncyCastle.Crypto.Tls ServerDHParams serverDHParams = ServerDHParams.Parse(input); this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey); + this.mDHParameters = mDHAgreePublicKey.Parameters; } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { @@ -208,21 +209,21 @@ namespace Org.BouncyCastle.Crypto.Tls TlsUtilities.WriteOpaque16(psk_identity, output); - context.SecurityParameters.pskIdentity = psk_identity; + mContext.SecurityParameters.pskIdentity = psk_identity; if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { - this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, - mDHAgreePublicKey.Parameters, output); + this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, + mDHParameters, output); } else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK) { - this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom, + this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(mContext.SecureRandom, mServerECPointFormats, mECAgreePublicKey.Parameters, output); } else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { - this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, + this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(mContext, this.mRsaServerPublicKey, output); } } @@ -235,7 +236,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (mPsk == null) throw new TlsFatalAlert(AlertDescription.unknown_psk_identity); - context.SecurityParameters.pskIdentity = psk_identity; + mContext.SecurityParameters.pskIdentity = psk_identity; if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK) { @@ -255,7 +256,7 @@ namespace Org.BouncyCastle.Crypto.Tls else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK) { byte[] encryptedPreMasterSecret; - if (TlsUtilities.IsSsl(context)) + if (TlsUtilities.IsSsl(mContext)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.ReadAll(input); diff --git a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs index 3a0a49154..b02d56486 100644 --- a/crypto/src/crypto/tls/TlsRsaKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsRsaKeyExchange.cs @@ -16,13 +16,13 @@ namespace Org.BouncyCastle.Crypto.Tls public class TlsRsaKeyExchange : AbstractTlsKeyExchange { - protected AsymmetricKeyParameter serverPublicKey = null; + protected AsymmetricKeyParameter mServerPublicKey = null; - protected RsaKeyParameters rsaServerPublicKey = null; + protected RsaKeyParameters mRsaServerPublicKey = null; - protected TlsEncryptionCredentials serverCredentials = null; + protected TlsEncryptionCredentials mServerCredentials = null; - protected byte[] premasterSecret; + protected byte[] mPremasterSecret; public TlsRsaKeyExchange(IList supportedSignatureAlgorithms) : base(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms) @@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Tls ProcessServerCertificate(serverCredentials.Certificate); - this.serverCredentials = (TlsEncryptionCredentials)serverCredentials; + this.mServerCredentials = (TlsEncryptionCredentials)serverCredentials; } public override void ProcessServerCertificate(Certificate serverCertificate) @@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo; try { - this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo); + this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo); } catch (Exception e) { @@ -62,10 +62,10 @@ namespace Org.BouncyCastle.Crypto.Tls } // Sanity check the PublicKeyFactory - if (this.serverPublicKey.IsPrivate) + if (this.mServerPublicKey.IsPrivate) throw new TlsFatalAlert(AlertDescription.internal_error); - this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey); + this.mRsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.mServerPublicKey); TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment); @@ -97,13 +97,13 @@ namespace Org.BouncyCastle.Crypto.Tls public override void GenerateClientKeyExchange(Stream output) { - this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, rsaServerPublicKey, output); + this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(mContext, mRsaServerPublicKey, output); } public override void ProcessClientKeyExchange(Stream input) { byte[] encryptedPreMasterSecret; - if (TlsUtilities.IsSsl(context)) + if (TlsUtilities.IsSsl(mContext)) { // TODO Do any SSLv3 clients actually include the length? encryptedPreMasterSecret = Streams.ReadAll(input); @@ -113,16 +113,16 @@ namespace Org.BouncyCastle.Crypto.Tls encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input); } - this.premasterSecret = serverCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); + this.mPremasterSecret = mServerCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret); } public override byte[] GeneratePremasterSecret() { - if (this.premasterSecret == null) + if (this.mPremasterSecret == null) throw new TlsFatalAlert(AlertDescription.internal_error); - byte[] tmp = this.premasterSecret; - this.premasterSecret = null; + byte[] tmp = this.mPremasterSecret; + this.mPremasterSecret = null; return tmp; } diff --git a/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs b/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs new file mode 100644 index 000000000..185f2f50a --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpGroupVerifier.cs @@ -0,0 +1,17 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSrpGroupVerifier + { + /** + * Check whether the given SRP group parameters are acceptable for use. + * + * @param group the {@link SRP6GroupParameters} to check + * @return true if (and only if) the specified group parameters are acceptable + */ + bool Accept(Srp6GroupParameters group); + } +} diff --git a/crypto/src/crypto/tls/TlsSrpIdentityManager.cs b/crypto/src/crypto/tls/TlsSrpIdentityManager.cs new file mode 100644 index 000000000..080a0dc16 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpIdentityManager.cs @@ -0,0 +1,21 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public interface TlsSrpIdentityManager + { + /** + * Lookup the {@link TlsSRPLoginParameters} corresponding to the specified identity. + * + * NOTE: To avoid "identity probing", unknown identities SHOULD be handled as recommended in RFC + * 5054 2.5.1.3. {@link SimulatedTlsSRPIdentityManager} is provided for this purpose. + * + * @param identity + * the SRP identity sent by the connecting client + * @return the {@link TlsSRPLoginParameters} for the specified identity, or else 'simulated' + * parameters if the identity is not recognized. A null value is also allowed, but not + * recommended. + */ + TlsSrpLoginParameters GetLoginParameters(byte[] identity); + } +} diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs index f42f7456d..ce8e4834a 100644 --- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs @@ -16,36 +16,64 @@ namespace Org.BouncyCastle.Crypto.Tls public class TlsSrpKeyExchange : AbstractTlsKeyExchange { + protected static TlsSigner CreateSigner(int keyExchange) + { + switch (keyExchange) + { + case KeyExchangeAlgorithm.SRP: + return null; + case KeyExchangeAlgorithm.SRP_RSA: + return new TlsRsaSigner(); + case KeyExchangeAlgorithm.SRP_DSS: + return new TlsDssSigner(); + default: + throw new ArgumentException("unsupported key exchange algorithm"); + } + } + protected TlsSigner mTlsSigner; + protected TlsSrpGroupVerifier mGroupVerifier; protected byte[] mIdentity; protected byte[] mPassword; protected AsymmetricKeyParameter mServerPublicKey = null; - protected byte[] mS = null; - protected BigInteger mB = null; - protected Srp6Client mSrpClient = new Srp6Client(); + protected Srp6GroupParameters mSrpGroup = null; + protected Srp6Client mSrpClient = null; + protected Srp6Server mSrpServer = null; + protected BigInteger mSrpPeerCredentials = null; + protected BigInteger mSrpVerifier = null; + protected byte[] mSrpSalt = null; + + protected TlsSignerCredentials mServerCredentials = null; + [Obsolete("Use constructor taking an explicit 'groupVerifier' argument")] public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, byte[] password) - : base(keyExchange, supportedSignatureAlgorithms) + : this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsSrpGroupVerifier(), identity, password) { - switch (keyExchange) - { - case KeyExchangeAlgorithm.SRP: - this.mTlsSigner = null; - break; - case KeyExchangeAlgorithm.SRP_RSA: - this.mTlsSigner = new TlsRsaSigner(); - break; - case KeyExchangeAlgorithm.SRP_DSS: - this.mTlsSigner = new TlsDssSigner(); - break; - default: - throw new InvalidOperationException("unsupported key exchange algorithm"); - } + } + public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsSrpGroupVerifier groupVerifier, + byte[] identity, byte[] password) + : base(keyExchange, supportedSignatureAlgorithms) + { + this.mTlsSigner = CreateSigner(keyExchange); + this.mGroupVerifier = groupVerifier; this.mIdentity = identity; this.mPassword = password; + this.mSrpClient = new Srp6Client(); + } + + public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, + TlsSrpLoginParameters loginParameters) + : base(keyExchange, supportedSignatureAlgorithms) + { + this.mTlsSigner = CreateSigner(keyExchange); + this.mIdentity = identity; + this.mSrpServer = new Srp6Server(); + this.mSrpGroup = loginParameters.Group; + this.mSrpVerifier = loginParameters.Verifier; + this.mSrpSalt = loginParameters.Salt; } public override void Init(TlsContext context) @@ -91,14 +119,62 @@ namespace Org.BouncyCastle.Crypto.Tls base.ProcessServerCertificate(serverCertificate); } + public override void ProcessServerCredentials(TlsCredentials serverCredentials) + { + if ((mKeyExchange == KeyExchangeAlgorithm.SRP) || !(serverCredentials is TlsSignerCredentials)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + ProcessServerCertificate(serverCredentials.Certificate); + + this.mServerCredentials = (TlsSignerCredentials)serverCredentials; + } + public override bool RequiresServerKeyExchange { get { return true; } } + public override byte[] GenerateServerKeyExchange() + { + mSrpServer.Init(mSrpGroup, mSrpVerifier, TlsUtilities.CreateHash(HashAlgorithm.sha1), mContext.SecureRandom); + BigInteger B = mSrpServer.GenerateServerCredentials(); + + ServerSrpParams srpParams = new ServerSrpParams(mSrpGroup.N, mSrpGroup.G, mSrpSalt, B); + + DigestInputBuffer buf = new DigestInputBuffer(); + + srpParams.Encode(buf); + + if (mServerCredentials != null) + { + /* + * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 + */ + SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( + mContext, mServerCredentials); + + IDigest d = TlsUtilities.CreateHash(signatureAndHashAlgorithm); + + SecurityParameters securityParameters = mContext.SecurityParameters; + d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length); + d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length); + buf.UpdateDigest(d); + + byte[] hash = new byte[d.GetDigestSize()]; + d.DoFinal(hash, 0); + + byte[] signature = mServerCredentials.GenerateCertificateSignature(hash); + + DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature); + signed_params.Encode(buf); + } + + return buf.ToArray(); + } + public override void ProcessServerKeyExchange(Stream input) { - SecurityParameters securityParameters = context.SecurityParameters; + SecurityParameters securityParameters = mContext.SecurityParameters; SignerInputBuffer buf = null; Stream teeIn = input; @@ -109,14 +185,11 @@ namespace Org.BouncyCastle.Crypto.Tls teeIn = new TeeInputStream(input, buf); } - byte[] NBytes = TlsUtilities.ReadOpaque16(teeIn); - byte[] gBytes = TlsUtilities.ReadOpaque16(teeIn); - byte[] sBytes = TlsUtilities.ReadOpaque8(teeIn); - byte[] BBytes = TlsUtilities.ReadOpaque16(teeIn); + ServerSrpParams srpParams = ServerSrpParams.Parse(teeIn); if (buf != null) { - DigitallySigned signed_params = DigitallySigned.Parse(context, input); + DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); @@ -124,13 +197,12 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.decrypt_error); } - BigInteger N = new BigInteger(1, NBytes); - BigInteger g = new BigInteger(1, gBytes); + this.mSrpGroup = new Srp6GroupParameters(srpParams.N, srpParams.G); - // TODO Validate group parameters (see RFC 5054) - // throw new TlsFatalAlert(AlertDescription.insufficient_security); + if (!mGroupVerifier.Accept(mSrpGroup)) + throw new TlsFatalAlert(AlertDescription.insufficient_security); - this.mS = sBytes; + this.mSrpSalt = srpParams.S; /* * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if @@ -138,14 +210,14 @@ namespace Org.BouncyCastle.Crypto.Tls */ try { - this.mB = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes)); + this.mSrpPeerCredentials = Srp6Utilities.ValidatePublicValue(mSrpGroup.N, srpParams.B); } catch (CryptoException e) { throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); } - this.mSrpClient.Init(N, g, TlsUtilities.CreateHash(HashAlgorithm.sha1), context.SecureRandom); + this.mSrpClient.Init(mSrpGroup, TlsUtilities.CreateHash(HashAlgorithm.sha1), mContext.SecureRandom); } public override void ValidateCertificateRequest(CertificateRequest certificateRequest) @@ -160,16 +232,40 @@ namespace Org.BouncyCastle.Crypto.Tls public override void GenerateClientKeyExchange(Stream output) { - BigInteger A = mSrpClient.GenerateClientCredentials(mS, this.mIdentity, this.mPassword); - TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(A), output); + BigInteger A = mSrpClient.GenerateClientCredentials(mSrpSalt, mIdentity, mPassword); + TlsSrpUtilities.WriteSrpParameter(A, output); + + mContext.SecurityParameters.srpIdentity = Arrays.Clone(mIdentity); + } + + public override void ProcessClientKeyExchange(Stream input) + { + /* + * RFC 5054 2.5.4: The server MUST abort the handshake with an "illegal_parameter" alert if + * A % N = 0. + */ + try + { + this.mSrpPeerCredentials = Srp6Utilities.ValidatePublicValue(mSrpGroup.N, TlsSrpUtilities.ReadSrpParameter(input)); + } + catch (CryptoException e) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter, e); + } + + mContext.SecurityParameters.srpIdentity = Arrays.Clone(mIdentity); } public override byte[] GeneratePremasterSecret() { try { + BigInteger S = mSrpServer != null + ? mSrpServer.CalculateSecret(mSrpPeerCredentials) + : mSrpClient.CalculateSecret(mSrpPeerCredentials); + // TODO Check if this needs to be a fixed size - return BigIntegers.AsUnsignedByteArray(mSrpClient.CalculateSecret(mB)); + return BigIntegers.AsUnsignedByteArray(S); } catch (CryptoException e) { diff --git a/crypto/src/crypto/tls/TlsSrpLoginParameters.cs b/crypto/src/crypto/tls/TlsSrpLoginParameters.cs new file mode 100644 index 000000000..5ae4641f6 --- /dev/null +++ b/crypto/src/crypto/tls/TlsSrpLoginParameters.cs @@ -0,0 +1,36 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto.Tls +{ + public class TlsSrpLoginParameters + { + protected readonly Srp6GroupParameters mGroup; + protected readonly BigInteger mVerifier; + protected readonly byte[] mSalt; + + public TlsSrpLoginParameters(Srp6GroupParameters group, BigInteger verifier, byte[] salt) + { + this.mGroup = group; + this.mVerifier = verifier; + this.mSalt = salt; + } + + public virtual Srp6GroupParameters Group + { + get { return mGroup; } + } + + public virtual byte[] Salt + { + get { return mSalt; } + } + + public virtual BigInteger Verifier + { + get { return mVerifier; } + } + } +} diff --git a/crypto/src/crypto/tls/TlsSrpUtilities.cs b/crypto/src/crypto/tls/TlsSrpUtilities.cs index bbb6ac280..873189dc6 100644 --- a/crypto/src/crypto/tls/TlsSrpUtilities.cs +++ b/crypto/src/crypto/tls/TlsSrpUtilities.cs @@ -2,6 +2,9 @@ using System.Collections; using System.IO; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + namespace Org.BouncyCastle.Crypto.Tls { public abstract class TlsSrpUtilities @@ -37,5 +40,35 @@ namespace Org.BouncyCastle.Crypto.Tls return identity; } + + public static BigInteger ReadSrpParameter(Stream input) + { + return new BigInteger(1, TlsUtilities.ReadOpaque16(input)); + } + + public static void WriteSrpParameter(BigInteger x, Stream output) + { + TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output); + } + + public static bool IsSrpCipherSuite(int cipherSuite) + { + switch (cipherSuite) + { + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return true; + + default: + return false; + } + } } } diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index 485ecb760..be91e6c4b 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -21,6 +21,9 @@ namespace Org.BouncyCastle.Crypto.Tls public abstract class TlsUtilities { public static readonly byte[] EmptyBytes = new byte[0]; + public static readonly short[] EmptyShorts = new short[0]; + public static readonly int[] EmptyInts = new int[0]; + public static readonly long[] EmptyLongs = new long[0]; public static void CheckUint8(int i) { @@ -589,6 +592,37 @@ namespace Org.BouncyCastle.Crypto.Tls return extensions == null ? null : (byte[])extensions[extensionType]; } + public static IList GetDefaultSupportedSignatureAlgorithms() + { + byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha1, HashAlgorithm.sha224, HashAlgorithm.sha256, + HashAlgorithm.sha384, HashAlgorithm.sha512 }; + byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa, SignatureAlgorithm.dsa, + SignatureAlgorithm.ecdsa }; + + IList result = Platform.CreateArrayList(); + for (int i = 0; i < signatureAlgorithms.Length; ++i) + { + for (int j = 0; j < hashAlgorithms.Length; ++j) + { + result.Add(new SignatureAndHashAlgorithm(hashAlgorithms[j], signatureAlgorithms[i])); + } + } + return result; + } + + public static SignatureAndHashAlgorithm GetSignatureAndHashAlgorithm(TlsContext context, + TlsSignerCredentials signerCredentials) + { + SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; + if (IsTlsV12(context)) + { + signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; + if (signatureAndHashAlgorithm == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + } + return signatureAndHashAlgorithm; + } + public static bool HasExpectedEmptyExtensionData(IDictionary extensions, int extensionType, byte alertDescription) { @@ -941,6 +975,13 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public static IDigest CreateHash(SignatureAndHashAlgorithm signatureAndHashAlgorithm) + { + return signatureAndHashAlgorithm == null + ? new CombinedHash() + : CreateHash(signatureAndHashAlgorithm.Hash); + } + public static IDigest CloneHash(byte hashAlgorithm, IDigest hash) { switch (hashAlgorithm) diff --git a/crypto/test/src/crypto/test/SRP6Test.cs b/crypto/test/src/crypto/test/SRP6Test.cs index 3b80e2c16..6b64df924 100644 --- a/crypto/test/src/crypto/test/SRP6Test.cs +++ b/crypto/test/src/crypto/test/SRP6Test.cs @@ -23,15 +23,7 @@ namespace Org.BouncyCastle.Crypto.Tests return new BigInteger(1, Hex.Decode(hex)); } - // 1024 bit example prime from RFC5054 and corresponding generator - private static readonly BigInteger N_1024 = FromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" - + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" - + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" - + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" - + "FD5138FE8376435B9FC61D2FC0EB06E3"); - private static readonly BigInteger g_1024 = BigInteger.Two; - - private readonly SecureRandom random = new SecureRandom(); + private readonly SecureRandom random = new SecureRandom(); public override string Name { @@ -42,9 +34,9 @@ namespace Org.BouncyCastle.Crypto.Tests { rfc5054AppendixBTestVectors(); - testMutualVerification(N_1024, g_1024); - testClientCatchesBadB(N_1024, g_1024); - testServerCatchesBadA(N_1024, g_1024); + testMutualVerification(Srp6StandardGroups.rfc5054_1024); + testClientCatchesBadB(Srp6StandardGroups.rfc5054_1024); + testServerCatchesBadA(Srp6StandardGroups.rfc5054_1024); testWithRandomParams(256); testWithRandomParams(384); @@ -56,8 +48,8 @@ namespace Org.BouncyCastle.Crypto.Tests byte[] I = Encoding.UTF8.GetBytes("alice"); byte[] P = Encoding.UTF8.GetBytes("password123"); byte[] s = Hex.Decode("BEB25379D1A8581EB5A727673A2441EE"); - BigInteger N = N_1024; - BigInteger g = g_1024; + BigInteger N = Srp6StandardGroups.rfc5054_1024.N; + BigInteger g = Srp6StandardGroups.rfc5054_1024.G; BigInteger a = FromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393"); BigInteger b = FromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20"); @@ -148,13 +140,10 @@ namespace Org.BouncyCastle.Crypto.Tests paramGen.Init(bits, 25, random); DHParameters parameters = paramGen.GenerateParameters(); - BigInteger g = parameters.G; - BigInteger p = parameters.P; - - testMutualVerification(p, g); + testMutualVerification(new Srp6GroupParameters(parameters.P, parameters.G)); } - private void testMutualVerification(BigInteger N, BigInteger g) + private void testMutualVerification(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -162,16 +151,16 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6VerifierGenerator gen = new Srp6VerifierGenerator(); - gen.Init(N, g, new Sha256Digest()); + gen.Init(group, new Sha256Digest()); BigInteger v = gen.GenerateVerifier(s, I, P); Srp6Client client = new Srp6Client(); - client.Init(N, g, new Sha256Digest(), random); + client.Init(group, new Sha256Digest(), random); Srp6Server server = new Srp6Server(); - server.Init(N, g, v, new Sha256Digest(), random); + server.Init(group, v, new Sha256Digest(), random); - BigInteger A = client.GenerateClientCredentials(s, I, P); + BigInteger A = client.GenerateClientCredentials(s, I, P); BigInteger B = server.GenerateServerCredentials(); BigInteger clientS = client.CalculateSecret(B); @@ -183,7 +172,7 @@ namespace Org.BouncyCastle.Crypto.Tests } } - private void testClientCatchesBadB(BigInteger N, BigInteger g) + private void testClientCatchesBadB(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -191,7 +180,7 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6Client client = new Srp6Client(); - client.Init(N, g, new Sha256Digest(), random); + client.Init(group, new Sha256Digest(), random); client.GenerateClientCredentials(s, I, P); @@ -207,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - client.CalculateSecret(N); + client.CalculateSecret(group.N); Fail("Client failed to detect invalid value for 'B'"); } catch (CryptoException) @@ -216,7 +205,7 @@ namespace Org.BouncyCastle.Crypto.Tests } } - private void testServerCatchesBadA(BigInteger N, BigInteger g) + private void testServerCatchesBadA(Srp6GroupParameters group) { byte[] I = Encoding.UTF8.GetBytes("username"); byte[] P = Encoding.UTF8.GetBytes("password"); @@ -224,11 +213,11 @@ namespace Org.BouncyCastle.Crypto.Tests random.NextBytes(s); Srp6VerifierGenerator gen = new Srp6VerifierGenerator(); - gen.Init(N, g, new Sha256Digest()); + gen.Init(group, new Sha256Digest()); BigInteger v = gen.GenerateVerifier(s, I, P); Srp6Server server = new Srp6Server(); - server.Init(N, g, v, new Sha256Digest(), random); + server.Init(group, v, new Sha256Digest(), random); server.GenerateServerCredentials(); @@ -244,7 +233,7 @@ namespace Org.BouncyCastle.Crypto.Tests try { - server.CalculateSecret(N); + server.CalculateSecret(group.N); Fail("Client failed to detect invalid value for 'A'"); } catch (CryptoException) diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs new file mode 100644 index 000000000..7225d84ce --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockSrpTlsClient + : SrpTlsClient + { + internal TlsSession mSession; + + internal MockSrpTlsClient(TlsSession session, byte[] identity, byte[] password) + : base(identity, password) + { + this.mSession = session; + } + + public override TlsSession GetSessionToResume() + { + return this.mSession; + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("TLS-SRP client negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + internal class MyTlsAuthentication + : ServerOnlyTlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public override void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("TLS-SRP client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create Fingerprint based on certificate signature algorithm digest + Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs new file mode 100644 index 000000000..c15f63e0b --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsServer.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Crypto.Agreement.Srp; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class MockSrpTlsServer + : SrpTlsServer + { + internal static readonly Srp6GroupParameters TEST_GROUP = Srp6StandardGroups.rfc5054_1024; + internal static readonly byte[] TEST_IDENTITY = Strings.ToUtf8ByteArray("client"); + internal static readonly byte[] TEST_PASSWORD = Strings.ToUtf8ByteArray("password"); + internal static readonly byte[] TEST_SALT = Strings.ToUtf8ByteArray("salt"); + internal static readonly byte[] TEST_SEED_KEY = Strings.ToUtf8ByteArray("seed_key"); + + internal MockSrpTlsServer() + : base(new MyIdentityManager()) + { + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS-SRP server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + byte[] srpIdentity = mContext.SecurityParameters.SrpIdentity; + if (srpIdentity != null) + { + string name = Strings.FromUtf8ByteArray(srpIdentity); + Console.WriteLine("TLS-SRP server completed handshake for SRP identity: " + name); + } + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.TLSv12; } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + Console.WriteLine("TLS-SRP server negotiated " + serverVersion); + + return serverVersion; + } + + protected override TlsSignerCredentials GetDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa, + "x509-server-dsa.pem", "x509-server-key-dsa.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + + internal class MyIdentityManager + : TlsSrpIdentityManager + { + protected SimulatedTlsSrpIdentityManager unknownIdentityManager = SimulatedTlsSrpIdentityManager.GetRfc5054Default( + TEST_GROUP, TEST_SEED_KEY); + + public virtual TlsSrpLoginParameters GetLoginParameters(byte[] identity) + { + if (Arrays.AreEqual(TEST_IDENTITY, identity)) + { + Srp6VerifierGenerator verifierGenerator = new Srp6VerifierGenerator(); + verifierGenerator.Init(TEST_GROUP, TlsUtilities.CreateHash(HashAlgorithm.sha1)); + + BigInteger verifier = verifierGenerator.GenerateVerifier(TEST_SALT, identity, TEST_PASSWORD); + + return new TlsSrpLoginParameters(TEST_GROUP, verifier, TEST_SALT); + } + + return unknownIdentityManager.GetLoginParameters(identity); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index 803989f59..fd673c3b9 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -133,27 +133,8 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) return null; - SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; - IList sigAlgs = certificateRequest.SupportedSignatureAlgorithms; - if (sigAlgs != null) - { - foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs) - { - if (sigAlg.Signature == SignatureAlgorithm.rsa) - { - signatureAndHashAlgorithm = sigAlg; - break; - } - } - - if (signatureAndHashAlgorithm == null) - { - return null; - } - } - - return TlsTestUtilities.LoadSignerCredentials(mContext, new string[] { "x509-client.pem", "x509-ca.pem" }, - "x509-client-key.pem", signatureAndHashAlgorithm); + return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms, + SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem"); } }; } diff --git a/crypto/test/src/crypto/tls/test/MockTlsServer.cs b/crypto/test/src/crypto/tls/test/MockTlsServer.cs index 14d6b9839..8fce95d63 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsServer.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsServer.cs @@ -61,29 +61,19 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests public override CertificateRequest GetCertificateRequest() { - IList serverSigAlgs = null; + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + IList serverSigAlgs = null; if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) { - byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256, - HashAlgorithm.sha224, HashAlgorithm.sha1 }; - byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa }; - - serverSigAlgs = new ArrayList(); - for (int i = 0; i < hashAlgorithms.Length; ++i) - { - for (int j = 0; j < signatureAlgorithms.Length; ++j) - { - serverSigAlgs.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i], - signatureAlgorithms[j])); - } - } + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); } IList certificateAuthorities = new ArrayList(); certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); - return new CertificateRequest(new byte[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities); + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); } public override void NotifyClientCertificate(Certificate clientCertificate) @@ -101,37 +91,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() { - return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" }, "x509-server-key.pem"); } protected override TlsSignerCredentials GetRsaSignerCredentials() { - /* - * TODO Note that this code fails to provide default value for the client supported - * algorithms if it wasn't sent. - */ - SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; - IList sigAlgs = mSupportedSignatureAlgorithms; - if (sigAlgs != null) - { - foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs) - { - if (sigAlg.Signature == SignatureAlgorithm.rsa) - { - signatureAndHashAlgorithm = sigAlg; - break; - } - } - - if (signatureAndHashAlgorithm == null) - { - return null; - } - } - - return TlsTestUtilities.LoadSignerCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"}, - "x509-server-key.pem", signatureAndHashAlgorithm); + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); } } } diff --git a/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs new file mode 100644 index 000000000..32e126ff2 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsSrpProtocolTest.cs @@ -0,0 +1,80 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsSrpProtocolTest + { + [Test] + public void TestClientServer() + { + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientPipe, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverPipe, secureRandom); + + Server server = new Server(serverProtocol); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + MockSrpTlsClient client = new MockSrpTlsClient(null, MockSrpTlsServer.TEST_IDENTITY, MockSrpTlsServer.TEST_PASSWORD); + clientProtocol.Connect(client); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + + serverThread.Join(); + } + + internal class Server + { + private readonly TlsServerProtocol mServerProtocol; + + internal Server(TlsServerProtocol serverProtocol) + { + this.mServerProtocol = serverProtocol; + } + + public void Run() + { + try + { + MockSrpTlsServer server = new MockSrpTlsServer(); + mServerProtocol.Accept(server); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception) + { + //throw new RuntimeException(e); + } + } + } + } +} -- cgit 1.4.1 From e772fefc00c6d2649ebf1be0c6b48bd78ebbb427 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 13:55:26 +0700 Subject: Refactor TLS ciphersuite processing --- crypto/src/crypto/tls/AbstractTlsClient.cs | 8 + crypto/src/crypto/tls/AbstractTlsServer.cs | 8 + crypto/src/crypto/tls/DefaultTlsClient.cs | 399 +-------------------- crypto/src/crypto/tls/DefaultTlsServer.cs | 556 ++--------------------------- crypto/src/crypto/tls/PskTlsClient.cs | 216 +---------- crypto/src/crypto/tls/PskTlsServer.cs | 308 ++-------------- crypto/src/crypto/tls/SrpTlsClient.cs | 51 +-- crypto/src/crypto/tls/SrpTlsServer.cs | 77 +--- crypto/src/crypto/tls/TlsUtilities.cs | 522 +++++++++++++++++++++++++++ 9 files changed, 652 insertions(+), 1493 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs index 569979288..046feb78c 100644 --- a/crypto/src/crypto/tls/AbstractTlsClient.cs +++ b/crypto/src/crypto/tls/AbstractTlsClient.cs @@ -243,6 +243,14 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public override TlsCipher GetCipher() + { + int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite); + int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite); + + return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm); + } + public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket) { } diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs index b0a5f0d52..7fe3fcbe5 100644 --- a/crypto/src/crypto/tls/AbstractTlsServer.cs +++ b/crypto/src/crypto/tls/AbstractTlsServer.cs @@ -320,6 +320,14 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public override TlsCipher GetCipher() + { + int encryptionAlgorithm = TlsUtilities.GetEncryptionAlgorithm(mSelectedCipherSuite); + int macAlgorithm = TlsUtilities.GetMacAlgorithm(mSelectedCipherSuite); + + return mCipherFactory.CreateCipher(mContext, encryptionAlgorithm, macAlgorithm); + } + public virtual NewSessionTicket GetNewSessionTicket() { /* diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs index f07080cbd..ff7e6da85 100644 --- a/crypto/src/crypto/tls/DefaultTlsClient.cs +++ b/crypto/src/crypto/tls/DefaultTlsClient.cs @@ -48,395 +48,28 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); - - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); - - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS); - - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); - - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); - - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); - - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return CreateRsaKeyExchange(); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DH_RSA: + return CreateDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.DHE_RSA: + return CreateDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDH_RSA: + return CreateECDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); + case KeyExchangeAlgorithm.ECDHE_ECDSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return CreateECDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.RSA: + return CreateRsaKeyExchange(); default: /* diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs index 156eff8af..b12c43e1c 100644 --- a/crypto/src/crypto/tls/DefaultTlsServer.cs +++ b/crypto/src/crypto/tls/DefaultTlsServer.cs @@ -72,542 +72,62 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsCredentials GetCredentials() { - switch (mSelectedCipherSuite) + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); + + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return GetDsaSignerCredentials(); + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DHE_DSS: + return GetDsaSignerCredentials(); - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - return GetECDsaSignerCredentials(); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDHE_ECDSA: + return GetECDsaSignerCredentials(); - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return GetRsaEncryptionCredentials(); + case KeyExchangeAlgorithm.DHE_RSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return GetRsaSignerCredentials(); - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return GetRsaSignerCredentials(); + case KeyExchangeAlgorithm.RSA: + return GetRsaEncryptionCredentials(); - default: - /* - * Note: internal error here; selected a key exchange we don't implement! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); - - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); - - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS); - - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); - - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); - - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); - - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return createRSAKeyExchange(); - - default: - /* - * Note: internal error here; selected a key exchange we don't implement! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5); - - case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_RSA_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); + case KeyExchangeAlgorithm.DH_DSS: + case KeyExchangeAlgorithm.DH_RSA: + return CreateDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5); + case KeyExchangeAlgorithm.DHE_DSS: + case KeyExchangeAlgorithm.DHE_RSA: + return CreateDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.ECDH_ECDSA: + case KeyExchangeAlgorithm.ECDH_RSA: + return CreateECDHKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.ECDHE_ECDSA: + case KeyExchangeAlgorithm.ECDHE_RSA: + return CreateECDheKeyExchange(keyExchangeAlgorithm); - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: - case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.RSA: + return CreateRsaKeyExchange(); default: /* - * Note: internal error here; selected a cipher suite we don't implement! - */ + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ throw new TlsFatalAlert(AlertDescription.internal_error); } } @@ -634,7 +154,7 @@ namespace Org.BouncyCastle.Crypto.Tls mServerECPointFormats); } - protected virtual TlsKeyExchange createRSAKeyExchange() + protected virtual TlsKeyExchange CreateRsaKeyExchange() { return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms); } diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs index 1f4b0865c..2ef80dcfd 100644 --- a/crypto/src/crypto/tls/PskTlsClient.cs +++ b/crypto/src/crypto/tls/PskTlsClient.cs @@ -32,87 +32,15 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); - - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + return CreatePskKeyExchange(keyExchangeAlgorithm); default: /* @@ -133,134 +61,6 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.internal_error); } - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange) { return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves, diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs index 335c9de86..27d2b8119 100644 --- a/crypto/src/crypto/tls/PskTlsServer.cs +++ b/crypto/src/crypto/tls/PskTlsServer.cs @@ -44,297 +44,43 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsCredentials GetCredentials() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return null; + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + return null; - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return GetRsaEncryptionCredentials(); + case KeyExchangeAlgorithm.RSA_PSK: + return GetRsaEncryptionCredentials(); - default: - /* Note: internal error here; selected a key exchange we don't implement! */ - throw new TlsFatalAlert(AlertDescription.internal_error); + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK); - - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); - - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK); - - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: - case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null); - - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_PSK_WITH_NULL_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_PSK_WITH_NULL_SHA256: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256); - - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_PSK_WITH_NULL_SHA384: - case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384); - - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); + case KeyExchangeAlgorithm.DHE_PSK: + case KeyExchangeAlgorithm.ECDHE_PSK: + case KeyExchangeAlgorithm.PSK: + case KeyExchangeAlgorithm.RSA_PSK: + return CreatePskKeyExchange(keyExchangeAlgorithm); + + default: + /* + * Note: internal error here; the TlsProtocol implementation verifies that the + * server-selected cipher suite was in the list of client-offered cipher suites, so if + * we now can't produce an implementation, we shouldn't have offered it! + */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } diff --git a/crypto/src/crypto/tls/SrpTlsClient.cs b/crypto/src/crypto/tls/SrpTlsClient.cs index bed6a8f0c..df1607751 100644 --- a/crypto/src/crypto/tls/SrpTlsClient.cs +++ b/crypto/src/crypto/tls/SrpTlsClient.cs @@ -68,22 +68,14 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP); - - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS); + switch (keyExchangeAlgorithm) + { + case KeyExchangeAlgorithm.SRP: + case KeyExchangeAlgorithm.SRP_DSS: + case KeyExchangeAlgorithm.SRP_RSA: + return CreateSrpKeyExchange(keyExchangeAlgorithm); default: /* @@ -104,35 +96,6 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.internal_error); } - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange) { return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mGroupVerifier, mIdentity, mPassword); diff --git a/crypto/src/crypto/tls/SrpTlsServer.cs b/crypto/src/crypto/tls/SrpTlsServer.cs index 1bd6b3af4..f97878380 100644 --- a/crypto/src/crypto/tls/SrpTlsServer.cs +++ b/crypto/src/crypto/tls/SrpTlsServer.cs @@ -73,76 +73,35 @@ namespace Org.BouncyCastle.Crypto.Tls public override TlsCredentials GetCredentials() { - switch (mSelectedCipherSuite) + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); + + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - return null; + case KeyExchangeAlgorithm.SRP: + return null; - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return GetDsaSignerCredentials(); + case KeyExchangeAlgorithm.SRP_DSS: + return GetDsaSignerCredentials(); - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - return GetRsaSignerCredentials(); + case KeyExchangeAlgorithm.SRP_RSA: + return GetRsaSignerCredentials(); - default: - /* Note: internal error here; selected a key exchange we don't implement! */ - throw new TlsFatalAlert(AlertDescription.internal_error); + default: + /* Note: internal error here; selected a key exchange we don't implement! */ + throw new TlsFatalAlert(AlertDescription.internal_error); } } public override TlsKeyExchange GetKeyExchange() { - switch (mSelectedCipherSuite) - { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP); - - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA); + int keyExchangeAlgorithm = TlsUtilities.GetKeyExchangeAlgorithm(mSelectedCipherSuite); - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS); - - default: - /* - * Note: internal error here; the TlsProtocol implementation verifies that the - * server-selected cipher suite was in the list of client-offered cipher suites, so if - * we now can't produce an implementation, we shouldn't have offered it! - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - } - - public override TlsCipher GetCipher() - { - switch (mSelectedCipherSuite) + switch (keyExchangeAlgorithm) { - case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1); - - case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: - case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: - return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1); + case KeyExchangeAlgorithm.SRP: + case KeyExchangeAlgorithm.SRP_DSS: + case KeyExchangeAlgorithm.SRP_RSA: + return CreateSrpKeyExchange(keyExchangeAlgorithm); default: /* diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs index be91e6c4b..a8c8a2b28 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs @@ -1531,6 +1531,528 @@ namespace Org.BouncyCastle.Crypto.Tls } } + public static int GetKeyExchangeAlgorithm(int ciphersuite) + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DH_DSS; + + case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DH_RSA; + + case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DHE_DSS; + + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + return KeyExchangeAlgorithm.DHE_PSK; + + case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.DHE_RSA; + + case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + return KeyExchangeAlgorithm.ECDH_ECDSA; + + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + return KeyExchangeAlgorithm.ECDH_RSA; + + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_ECDSA; + + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_PSK; + + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.ECDHE_RSA; + + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.PSK; + + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + return KeyExchangeAlgorithm.RSA; + + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + return KeyExchangeAlgorithm.RSA_PSK; + + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP; + + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP_DSS; + + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + return KeyExchangeAlgorithm.SRP_RSA; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public static int GetMacAlgorithm(int ciphersuite) + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return MacAlgorithm.cls_null; + + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + return MacAlgorithm.hmac_md5; + + case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return MacAlgorithm.hmac_sha1; + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + return MacAlgorithm.hmac_sha256; + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + return MacAlgorithm.hmac_sha384; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + public static ProtocolVersion GetMinimumVersion(int ciphersuite) { switch (ciphersuite) -- cgit 1.4.1 From ec1991b40df8748b6c436807ce9d9ea5f146b13c Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 16:05:24 +0700 Subject: Port X931Signer and tests from Java --- crypto/crypto.csproj | 10 + crypto/src/crypto/signers/DsaDigestSigner.cs | 14 +- crypto/src/crypto/signers/ECGOST3410Signer.cs | 8 +- crypto/src/crypto/signers/ECNRSigner.cs | 8 +- crypto/src/crypto/signers/GOST3410DigestSigner.cs | 14 +- crypto/src/crypto/signers/GOST3410Signer.cs | 8 +- crypto/src/crypto/signers/GenericSigner.cs | 14 +- crypto/src/crypto/signers/Iso9796d2PssSigner.cs | 4 +- crypto/src/crypto/signers/Iso9796d2Signer.cs | 6 +- crypto/src/crypto/signers/PssSigner.cs | 2 +- crypto/src/crypto/signers/RsaDigestSigner.cs | 15 +- crypto/src/crypto/signers/X931Signer.cs | 235 ++++++++++++++++++++++ crypto/test/src/crypto/test/RegressionTest.cs | 3 +- crypto/test/src/crypto/test/X931SignerTest.cs | 145 +++++++++++++ 14 files changed, 438 insertions(+), 48 deletions(-) create mode 100644 crypto/src/crypto/signers/X931Signer.cs create mode 100644 crypto/test/src/crypto/test/X931SignerTest.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 26af5666f..ded3d6025 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -4293,6 +4293,11 @@ SubType = "Code" BuildAction = "Compile" /> + + true if the internal state represents the signature described in the passed in array. - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto.Signers } ///

Reset the internal state - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs index 6027aa9b9..28ab79c1c 100644 --- a/crypto/src/crypto/signers/ECGOST3410Signer.cs +++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs @@ -18,12 +18,12 @@ namespace Org.BouncyCastle.Crypto.Signers private ECKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ECGOST3410"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers * * @param message the message that will be verified later. */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { byte[] mRev = new byte[message.Length]; // conversion is little-endian @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Signers * the passed in message (for standard GOST3410 the message should be * a GOST3411 hash of the real message to be verified). */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/ECNRSigner.cs b/crypto/src/crypto/signers/ECNRSigner.cs index cae15bdbf..bb21a4994 100644 --- a/crypto/src/crypto/signers/ECNRSigner.cs +++ b/crypto/src/crypto/signers/ECNRSigner.cs @@ -19,12 +19,12 @@ namespace Org.BouncyCastle.Crypto.Signers private ECKeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "ECNR"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param digest the digest to be signed. * @exception DataLengthException if the digest is longer than the key allows */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { if (!this.forSigning) @@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param s the s value of the signature. * @exception DataLengthException if the digest is longer than the key allows */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/GOST3410DigestSigner.cs b/crypto/src/crypto/signers/GOST3410DigestSigner.cs index 58aefa368..bc32808df 100644 --- a/crypto/src/crypto/signers/GOST3410DigestSigner.cs +++ b/crypto/src/crypto/signers/GOST3410DigestSigner.cs @@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Crypto.Signers this.digest = digest; } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) @@ -86,7 +86,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using * the key we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation."); @@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// true if the internal state represents the signature described in the passed in array. - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -137,7 +137,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// Reset the internal state - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs index 375eeb5cc..f1832ae37 100644 --- a/crypto/src/crypto/signers/GOST3410Signer.cs +++ b/crypto/src/crypto/signers/GOST3410Signer.cs @@ -15,12 +15,12 @@ namespace Org.BouncyCastle.Crypto.Signers private Gost3410KeyParameters key; private SecureRandom random; - public string AlgorithmName + public virtual string AlgorithmName { get { return "GOST3410"; } } - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers * * @param message the message that will be verified later. */ - public BigInteger[] GenerateSignature( + public virtual BigInteger[] GenerateSignature( byte[] message) { byte[] mRev = new byte[message.Length]; // conversion is little-endian @@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Signers * the passed in message for standard Gost3410 the message should be a * Gost3411 hash of the real message to be verified. */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] message, BigInteger r, BigInteger s) diff --git a/crypto/src/crypto/signers/GenericSigner.cs b/crypto/src/crypto/signers/GenericSigner.cs index 5035b454d..a5512176f 100644 --- a/crypto/src/crypto/signers/GenericSigner.cs +++ b/crypto/src/crypto/signers/GenericSigner.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.digest = digest; } - public string AlgorithmName + public virtual string AlgorithmName { get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; } } @@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param parameters * necessary parameters. */ - public void Init(bool forSigning, ICipherParameters parameters) + public virtual void Init(bool forSigning, ICipherParameters parameters) { this.forSigning = forSigning; @@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update(byte input) + public virtual void Update(byte input) { digest.Update(input); } @@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate(byte[] input, int inOff, int length) + public virtual void BlockUpdate(byte[] input, int inOff, int length) { digest.BlockUpdate(input, inOff, length); } @@ -79,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using the key * we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("GenericSigner not initialised for signature generation."); @@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Crypto.Signers * return true if the internal state represents the signature described in * the passed in array. */ - public bool VerifySignature(byte[] signature) + public virtual bool VerifySignature(byte[] signature) { if (forSigning) throw new InvalidOperationException("GenericSigner not initialised for verification"); @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Signers } } - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs index d4f6c5522..1486656bd 100644 --- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs @@ -120,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + "ISO9796-2S2"; } } @@ -365,7 +365,7 @@ namespace Org.BouncyCastle.Crypto.Signers /// Generate a signature for the loaded message using the key we were /// initialised with. /// - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { int digSize = digest.GetDigestSize(); byte[] m2Hash = new byte[digSize]; diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs index cfb8942e6..4bb4d17a6 100644 --- a/crypto/src/crypto/signers/Iso9796d2Signer.cs +++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs @@ -105,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "with" + "ISO9796-2S1"; } } @@ -252,7 +252,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// update the internal digest with the byte b - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -266,7 +266,7 @@ namespace Org.BouncyCastle.Crypto.Signers } /// update the internal digest with the byte array in - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs index 6900224f3..03890902b 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs @@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.trailer = trailer; } - public string AlgorithmName + public virtual string AlgorithmName { get { return mgfDigest.AlgorithmName + "withRSAandMGF1"; } } diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs index 9af4e7145..d9b19cf6b 100644 --- a/crypto/src/crypto/signers/RsaDigestSigner.cs +++ b/crypto/src/crypto/signers/RsaDigestSigner.cs @@ -64,8 +64,7 @@ namespace Org.BouncyCastle.Crypto.Signers this.algId = algId; } - [Obsolete] - public string AlgorithmName + public virtual string AlgorithmName { get { return digest.AlgorithmName + "withRSA"; } } @@ -76,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Signers * @param forSigning true if for signing, false otherwise * @param param necessary parameters. */ - public void Init( + public virtual void Init( bool forSigning, ICipherParameters parameters) { @@ -106,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte b */ - public void Update( + public virtual void Update( byte input) { digest.Update(input); @@ -115,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Signers /** * update the internal digest with the byte array in */ - public void BlockUpdate( + public virtual void BlockUpdate( byte[] input, int inOff, int length) @@ -127,7 +126,7 @@ namespace Org.BouncyCastle.Crypto.Signers * Generate a signature for the message we've been loaded with using * the key we were initialised with. */ - public byte[] GenerateSignature() + public virtual byte[] GenerateSignature() { if (!forSigning) throw new InvalidOperationException("RsaDigestSigner not initialised for signature generation."); @@ -143,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Signers * return true if the internal state represents the signature described * in the passed in array. */ - public bool VerifySignature( + public virtual bool VerifySignature( byte[] signature) { if (forSigning) @@ -197,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Signers } } - public void Reset() + public virtual void Reset() { digest.Reset(); } diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs new file mode 100644 index 000000000..cc3292159 --- /dev/null +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + /** + * X9.31-1998 - signing using a hash. + *

+ * The message digest hash, H, is encapsulated to form a byte string as follows + *

+ *
+     * EB = 06 || PS || 0xBA || H || TRAILER
+     * 
+ * where PS is a string of bytes all of value 0xBB of length such that |EB|=|n|, and TRAILER is the ISO/IEC 10118 part number† for the digest. The byte string, EB, is converted to an integer value, the message representative, f. + */ + public class X931Signer + : ISigner + { + public const int TRAILER_IMPLICIT = 0xBC; + public const int TRAILER_RIPEMD160 = 0x31CC; + public const int TRAILER_RIPEMD128 = 0x32CC; + public const int TRAILER_SHA1 = 0x33CC; + public const int TRAILER_SHA256 = 0x34CC; + public const int TRAILER_SHA512 = 0x35CC; + public const int TRAILER_SHA384 = 0x36CC; + public const int TRAILER_WHIRLPOOL = 0x37CC; + public const int TRAILER_SHA224 = 0x38CC; + + private static readonly IDictionary trailerMap = Platform.CreateHashtable(); + + static X931Signer() + { + trailerMap.Add("RIPEMD128", TRAILER_RIPEMD128); + trailerMap.Add("RIPEMD160", TRAILER_RIPEMD160); + + trailerMap.Add("SHA-1", TRAILER_SHA1); + trailerMap.Add("SHA-224", TRAILER_SHA224); + trailerMap.Add("SHA-256", TRAILER_SHA256); + trailerMap.Add("SHA-384", TRAILER_SHA384); + trailerMap.Add("SHA-512", TRAILER_SHA512); + + trailerMap.Add("Whirlpool", TRAILER_WHIRLPOOL); + } + + private IDigest digest; + private IAsymmetricBlockCipher cipher; + private RsaKeyParameters kParam; + + private int trailer; + private int keyBits; + private byte[] block; + + /** + * Generate a signer for the with either implicit or explicit trailers + * for ISO9796-2. + * + * @param cipher base cipher to use for signature creation/verification + * @param digest digest to use. + * @param implicit whether or not the trailer is implicit or gives the hash. + */ + public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit) + { + this.cipher = cipher; + this.digest = digest; + + if (isImplicit) + { + trailer = TRAILER_IMPLICIT; + } + else + { + string name = digest.AlgorithmName; + if (!trailerMap.Contains(name)) + throw new ArgumentException("no valid trailer", "digest"); + + trailer = (int)trailerMap[name]; + } + } + + [Obsolete] + public virtual string AlgorithmName + { + get { return digest.AlgorithmName + "withX931"; } + } + + /** + * Constructor for a signer with an explicit digest trailer. + * + * @param cipher cipher to use. + * @param digest digest to sign with. + */ + public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest) + : this(cipher, digest, false) + { + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + kParam = (RsaKeyParameters)parameters; + + cipher.Init(forSigning, kParam); + + keyBits = kParam.Modulus.BitLength; + + block = new byte[(keyBits + 7) / 8]; + + Reset(); + } + + /// clear possible sensitive data + private void ClearBlock(byte[] block) + { + Array.Clear(block, 0, block.Length); + } + + /** + * update the internal digest with the byte b + */ + public virtual void Update(byte b) + { + digest.Update(b); + } + + /** + * update the internal digest with the byte array in + */ + public virtual void BlockUpdate(byte[] input, int off, int len) + { + digest.BlockUpdate(input, off, len); + } + + /** + * reset the internal state + */ + public virtual void Reset() + { + digest.Reset(); + } + + /** + * generate a signature for the loaded message using the key we were + * initialised with. + */ + public virtual byte[] GenerateSignature() + { + CreateSignatureBlock(); + + BigInteger t = new BigInteger(1, cipher.ProcessBlock(block, 0, block.Length)); + ClearBlock(block); + + t = t.Min(kParam.Modulus.Subtract(t)); + + return BigIntegers.AsUnsignedByteArray((kParam.Modulus.BitLength + 7) / 8, t); + } + + private void CreateSignatureBlock() + { + int digSize = digest.GetDigestSize(); + + int delta; + + if (trailer == TRAILER_IMPLICIT) + { + delta = block.Length - digSize - 1; + digest.DoFinal(block, delta); + block[block.Length - 1] = (byte)TRAILER_IMPLICIT; + } + else + { + delta = block.Length - digSize - 2; + digest.DoFinal(block, delta); + block[block.Length - 2] = (byte)(trailer >> 8); + block[block.Length - 1] = (byte)trailer; + } + + block[0] = 0x6b; + for (int i = delta - 2; i != 0; i--) + { + block[i] = (byte)0xbb; + } + block[delta - 1] = (byte)0xba; + } + + /** + * return true if the signature represents a ISO9796-2 signature + * for the passed in message. + */ + public virtual bool VerifySignature(byte[] signature) + { + try + { + block = cipher.ProcessBlock(signature, 0, signature.Length); + } + catch (Exception) + { + return false; + } + + BigInteger t = new BigInteger(block); + BigInteger f; + + if ((t.IntValue & 15) == 12) + { + f = t; + } + else + { + t = kParam.Modulus.Subtract(t); + if ((t.IntValue & 15) == 12) + { + f = t; + } + else + { + return false; + } + } + + CreateSignatureBlock(); + + byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f); + + bool rv = Arrays.ConstantTimeAreEqual(block, fBlock); + + ClearBlock(block); + ClearBlock(fBlock); + + return rv; + } + } +} diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index 27d6bb0e9..0b7a0f72d 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -118,7 +118,8 @@ namespace Org.BouncyCastle.Crypto.Tests new SipHashTest(), new Poly1305Test(), new OcbTest(), - new SM3DigestTest() + new SM3DigestTest(), + new X931SignerTest() }; public static void Main( diff --git a/crypto/test/src/crypto/test/X931SignerTest.cs b/crypto/test/src/crypto/test/X931SignerTest.cs new file mode 100644 index 000000000..d03cbc8e4 --- /dev/null +++ b/crypto/test/src/crypto/test/X931SignerTest.cs @@ -0,0 +1,145 @@ +using System; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class X931SignerTest + : SimpleTest + { + public override string Name + { + get { return "X931Signer"; } + } + + public override void PerformTest() + { + BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt")); + BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ==")); + BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt")); + BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ==")); + BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ==")); + BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E=")); + BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE=")); + BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0=")); + BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg==")); + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp); + RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv); + + byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 }; + + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + signer.Init(true, rsaPrivate); + signer.BlockUpdate(msg, 0, msg.Length); + byte[] sig = signer.GenerateSignature(); + + signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + signer.Init(false, rsaPublic); + signer.BlockUpdate(msg, 0, msg.Length); + if (!signer.VerifySignature(sig)) + { + Fail("X9.31 Signer failed."); + } + + ShouldPassSignatureTest1(); + ShouldPassSignatureTest2(); + ShouldPassSignatureTest3(); + } + + private void ShouldPassSignatureTest1() + { + BigInteger n = new BigInteger("c9be1b28f8caccca65d86cc3c9bbcc13eccc059df3b80bd2292b811eff3aa0dd75e1e85c333b8e3fa9bed53bb20f5359ff4e6900c5e9a388e3a4772a583a79e2299c76582c2b27694b65e9ba22e66bfb817f8b70b22206d7d8ae488c86dbb7137c26d5eff9b33c90e6cee640630313b7a715802e15142fef498c404a8de19674974785f0f852e2d470fe85a2e54ffca9f5851f672b71df691785a5cdabe8f14aa628942147de7593b2cf962414a5b59c632c4e14f1768c0ab2e9250824beea60a3529f11bf5e070ce90a47686eb0be1086fb21f0827f55295b4a48307db0b048c05a4aec3f488c576ca6f1879d354224c7e84cbcd8e76dd217a3de54dba73c35", 16); + BigInteger e = new BigInteger("e75b1b", 16); + byte[] msg = Hex.Decode("5bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce"); + byte[] sig = Hex.Decode("0fe8bb8e3109a1eb7489ef35bf4c1a0780071da789c8bd226a4170538eafefdd30b732d628f0e87a0b9450051feae9754d4fb61f57862d10f0bacc4f660d13281d0cd1141c006ade5186ff7d961a4c6cd0a4b352fc1295c5afd088f80ac1f8e192ef116a010a442655fe8ff5eeacea15807906fb0f0dfa86e680d4c005872357f7ece9aa4e20b15d5f709b30f08648ecaa34f2fbf54eb6b414fa2ff6f87561f70163235e69ccb4ac82a2e46d3be214cc2ef5263b569b2d8fd839b21a9e102665105ea762bda25bb446cfd831487a6b846100dee113ae95ae64f4af22c428c87bab809541c962bb3a56d4c86588e0af4ebc7fcc66dadced311051356d3ea745f7"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 1 failed."); + } + } + + private void ShouldPassSignatureTest2() + { + BigInteger n = new BigInteger("b746ba6c3c0be64bbe33aa55b2929b0af4e86d773d44bfe5914db9287788c4663984b61a418d2eecca30d752ff6b620a07ec72eeb2b422d2429da352407b99982800b9dd7697be6a7b1baa98ca5f4fc2fe33400f20b9dba337ac25c987804165d4a6e0ee4d18eabd6de5abdfe578cae6713ff91d16c80a5bb20217fe614d9509e75a43e1825327b9da8f0a9f6eeaa1c04b69fb4bacc073569fff4ab491becbe6d0441d437fc3fa823239c4a0f75321666b68dd3f66e2dd394089a15bcc288a68a4eb0a48e17d639743b9dea0a91cc35820544732aff253f8ca9967c609dc01c2f8cd0313a7a91cfa94ff74289a1d2b6f19d1811f4b9a65f4cce9e5759b4cc64f", 16); + BigInteger e = new BigInteger("dcbbdb", 16); + byte[] msg = Hex.Decode("a5d3c8a060f897bbbc20ae0955052f37fbc70986b6e11c65075c9f457142bfa93856897c69020aa81a91b5e4f39e05cdeecc63395ab849c8262ca8bc5c96870aecb8edb0aba0024a9bdb71e06de6100344e5c318bc979ef32b8a49a8278ba99d4861bce42ebbc5c8c666aaa6cac39aff8779f2cae367620f9edd4cb1d80b6c8c"); + byte[] sig = Hex.Decode("39fbbd1804c689a533b0043f84da0f06081038c0fbf31e443e46a05e58f50de5198bbca40522afefaba3aed7082a6cb93b1da39f1f5a42246bf64930781948d300549bef0f8d554ecfca60a1b1ecba95a7014ee4545ad4f0c4e3a31942c6738b4ccd6244b6a21267dadf0826a5f713f13b1f5a9ab8501d957a26d4948278ac67851071a315674bdab173bfef2c2690c8373da6bf3d69f30c0e5da8883de872f59521b40793854085641adf98d13db991c5d0a8aaa0222934fa33332e90ef0b954e195cb267d6ffb36c96e14d1ec7b915a87598b4461a3146566354dc2ae748c84ee0cd46543b53ebff8cdf47725b280a1f799fb6ebb4a31ad2bdd5178250f83a"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha224Digest()); + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 2 failed."); + } + } + + private void ShouldPassSignatureTest3() + { + BigInteger n = new BigInteger("dcb5686a3d2063a3f9cf7b9b32d2d3765b4c449b09b4960245a9111cd3b0cbd3260496885b8e1fa5db33b03efcc759d9c1afe29d93c6faebc7e0efada334b5b9a29655e2da2c8f11103d8203be311feab7ae88e9f1b2ec7d8fc655d77202b1681dd9717ec0f525b35584987e19539635a1ed23ca482a00149c609a23dc1645fd", 16); + BigInteger e = new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc9f7", 16); + BigInteger d = new BigInteger("189d6345099098992e0c9ca5f281e1338092342fa0acc85cc2a111f30f9bd2fb4753cd1a48ef0ddca9bf1af33ec76fb2e23a9fb4896c26f2235b516f7c05ef7ae81e70f4b491a5fedba9b935e9c76d761a813ce7776ff8a1e5efe1166ff2eca26aa900da88c908d51af9de26977fe39719cc781df32216fa41b838f0c63803c3", 16); + + byte[] msg = Hex.Decode("911475c6e210ef4ac65b6fe8d2bfe5e01b959771b137c4ef69b88716e0d2ff9ebc1fad0f358c1dd7d50cc99a7b893ac9a6207076f08d8467d9e48c69c683bfe64a44dabaa3f7c243880f6ab7229bf7bb587822314fc5de5131983bfb2eef8b4bc1eac36f353724b567cd1ae8cddd64ddb7057549d5c81ad5fa3b5e751f00abf5"); + byte[] sig = Hex.Decode("02c50ec0ac8a7f38ef5630c396964d6a6daaa7e3083ab5b57fa2a2632f3b70e2e85c8456cd774d45d7e44fcb063f0f04fff9f1e3adfda11272535a92cb59320b190b5ee4261f23d6ceaa925df3a7bfa42e26bf61ea9645d9d64b3c90a820802768a6e209c9f83705375a3867afccc037e8242a98fa4c3db6b2d9877754d47289"); + + RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e); + X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest()); + + signer.Init(true, new RsaKeyParameters(true, n, d)); + + signer.BlockUpdate(msg, 0, msg.Length); + + byte[] s = signer.GenerateSignature(); + + if (!Arrays.AreEqual(sig, s)) + { + Fail("RSA X931 sig test 3 failed."); + } + + signer.Init(false, rsaPublic); + + signer.BlockUpdate(msg, 0, msg.Length); + + if (!signer.VerifySignature(sig)) + { + Fail("RSA X931 verify test 3 failed."); + } + } + + public static void Main(string[] args) + { + RunTest(new X931SignerTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} -- cgit 1.4.1 From 81e2ba37a3bbc0f4da77175bdea2486dcfa2f239 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 16:57:58 +0700 Subject: Add SignerUtilities handling for X931Signer --- crypto/src/crypto/signers/X931Signer.cs | 3 +-- crypto/src/security/SignerUtilities.cs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs index cc3292159..89f512b78 100644 --- a/crypto/src/crypto/signers/X931Signer.cs +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -81,10 +81,9 @@ namespace Org.BouncyCastle.Crypto.Signers } } - [Obsolete] public virtual string AlgorithmName { - get { return digest.AlgorithmName + "withX931"; } + get { return digest.AlgorithmName + "with" + cipher.AlgorithmName + "/X9.31"; } } /** diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index c1aea50d6..bd1515147 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -534,6 +534,26 @@ namespace Org.BouncyCastle.Security return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true); } + if (mechanism.EndsWith("/X9.31")) + { + string x931 = mechanism.Substring(0, mechanism.Length - "/X9.31".Length); + int withPos = x931.IndexOf("WITH"); + if (withPos > 0) + { + int endPos = withPos + "WITH".Length; + + string digestName = x931.Substring(0, withPos); + IDigest digest = DigestUtilities.GetDigest(digestName); + + string cipherName = x931.Substring(endPos, x931.Length - endPos); + if (cipherName.Equals("RSA")) + { + IAsymmetricBlockCipher cipher = new RsaBlindedEngine(); + return new X931Signer(cipher, digest); + } + } + } + throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); } -- cgit 1.4.1 From 18db014ea245eff3de280bee415af1db1b6f6dfd Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 16:58:41 +0700 Subject: Add constants for GNU protection modes --- crypto/src/bcpg/S2k.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'crypto') diff --git a/crypto/src/bcpg/S2k.cs b/crypto/src/bcpg/S2k.cs index de08c016c..f6d306890 100644 --- a/crypto/src/bcpg/S2k.cs +++ b/crypto/src/bcpg/S2k.cs @@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Bcpg public const int Salted = 1; public const int SaltedAndIterated = 3; public const int GnuDummyS2K = 101; + public const int GnuProtectionModeNoPrivateKey = 1; + public const int GnuProtectionModeDivertToCard = 2; internal int type; internal HashAlgorithmTag algorithm; -- cgit 1.4.1 From 51a48c2276c4fa48e38da1a678f86d3a638f8768 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 17:13:35 +0700 Subject: Remove extraneous class reference --- crypto/src/crypto/tls/TlsEccUtilities.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs index e938b1685..d0d794d0e 100644 --- a/crypto/src/crypto/tls/TlsEccUtilities.cs +++ b/crypto/src/crypto/tls/TlsEccUtilities.cs @@ -427,7 +427,7 @@ namespace Org.BouncyCastle.Crypto.Tls public static ECPrivateKeyParameters GenerateEphemeralClientKeyExchange(SecureRandom random, byte[] ecPointFormats, ECDomainParameters ecParams, Stream output) { - AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(random, ecParams); + AsymmetricCipherKeyPair kp = GenerateECKeyPair(random, ecParams); ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public; WriteECPoint(ecPointFormats, ecPublicKey.Q, output); -- cgit 1.4.1 From f6ff8794291fca376482633b26eaf8101c8cb44d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 21:26:50 +0700 Subject: Port of TlsTestSuite from Java, and misc. TLS code - Upgrade to NUnit 2.6.4 and adjust various test code --- .gitattributes | 1 + crypto/crypto.csproj | 40 ++++ crypto/test/lib/nunit.core.dll | Bin 90112 -> 139264 bytes crypto/test/lib/nunit.core.interfaces.dll | Bin 40960 -> 61440 bytes crypto/test/lib/nunit.framework.dll | Bin 81920 -> 139264 bytes crypto/test/src/asn1/test/AllTests.cs | 28 +-- crypto/test/src/cms/test/AllTests.cs | 33 ++- crypto/test/src/crypto/io/test/AllTests.cs | 29 ++- crypto/test/src/crypto/test/AllTests.cs | 37 ++- .../crypto/tls/test/LoggingDatagramTransport.cs | 86 +++++++ .../src/crypto/tls/test/MockDatagramAssociation.cs | 104 ++++++++ .../test/src/crypto/tls/test/MockPskTlsClient.cs | 2 +- .../test/src/crypto/tls/test/MockSrpTlsClient.cs | 2 +- crypto/test/src/crypto/tls/test/MockTlsClient.cs | 2 +- crypto/test/src/crypto/tls/test/NetworkStream.cs | 101 ++++++++ crypto/test/src/crypto/tls/test/TlsTestCase.cs | 158 +++++++++++++ .../test/src/crypto/tls/test/TlsTestClientImpl.cs | 262 +++++++++++++++++++++ crypto/test/src/crypto/tls/test/TlsTestConfig.cs | 101 ++++++++ .../test/src/crypto/tls/test/TlsTestServerImpl.cs | 194 +++++++++++++++ crypto/test/src/crypto/tls/test/TlsTestSuite.cs | 119 ++++++++++ crypto/test/src/math/ec/test/AllTests.cs | 23 +- crypto/test/src/math/test/AllTests.cs | 21 +- crypto/test/src/ocsp/test/AllTests.cs | 29 ++- crypto/test/src/openpgp/examples/test/AllTests.cs | 32 ++- crypto/test/src/openssl/test/AllTests.cs | 37 ++- crypto/test/src/tsp/test/AllTests.cs | 27 +-- crypto/test/src/util/io/pem/test/AllTests.cs | 35 ++- 27 files changed, 1325 insertions(+), 178 deletions(-) create mode 100644 crypto/test/src/crypto/tls/test/LoggingDatagramTransport.cs create mode 100644 crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs create mode 100644 crypto/test/src/crypto/tls/test/NetworkStream.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestCase.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestConfig.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs create mode 100644 crypto/test/src/crypto/tls/test/TlsTestSuite.cs (limited to 'crypto') diff --git a/.gitattributes b/.gitattributes index 14f495692..4989b01a5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,6 +24,7 @@ *.crl binary *.crt binary *.data binary +*.dll binary *.dsa binary *.jpg binary *.jpeg binary diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index ded3d6025..9d185ade3 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11087,6 +11087,16 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + + + = 0) + { + DumpDatagram("Received", buf, off, length); + } + return length; + } + + public virtual void Send(byte[] buf, int off, int len) + { + DumpDatagram("Sending", buf, off, len); + transport.Send(buf, off, len); + } + + public virtual void Close() + { + } + + private void DumpDatagram(string verb, byte[] buf, int off, int len) + { + long timestamp = DateTimeUtilities.CurrentUnixMs() - launchTimestamp; + StringBuilder sb = new StringBuilder("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:"); + for (int pos = 0; pos < len; ++pos) + { + if (pos % 16 == 0) + { + sb.Append(Environment.NewLine); + sb.Append(" "); + } + else if (pos % 16 == 8) + { + sb.Append('-'); + } + else + { + sb.Append(' '); + } + int val = buf[off + pos] & 0xFF; + sb.Append(HEX_CHARS[val >> 4]); + sb.Append(HEX_CHARS[val & 0xF]); + } + Dump(sb.ToString()); + } + + private void Dump(string s) + { + lock (this) output.WriteLine(s); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs new file mode 100644 index 000000000..0391f4fef --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections; +using System.IO; +using System.Net; +using System.Threading; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDatagramAssociation + { + private int mtu; + private MockDatagramTransport client, server; + + public MockDatagramAssociation(int mtu) + { + this.mtu = mtu; + + IList clientQueue = new ArrayList(); + IList serverQueue = new ArrayList(); + + this.client = new MockDatagramTransport(this, clientQueue, serverQueue); + this.server = new MockDatagramTransport(this, serverQueue, clientQueue); + } + + public DatagramTransport getClient() + { + return client; + } + + public DatagramTransport getServer() + { + return server; + } + + private class MockDatagramTransport + : DatagramTransport + { + private readonly MockDatagramAssociation mOuter; + + private IList receiveQueue, sendQueue; + + internal MockDatagramTransport(MockDatagramAssociation outer, IList receiveQueue, IList sendQueue) + { + this.mOuter = outer; + this.receiveQueue = receiveQueue; + this.sendQueue = sendQueue; + } + + public virtual int GetReceiveLimit() + { + return mOuter.mtu; + } + + public virtual int GetSendLimit() + { + return mOuter.mtu; + } + + public virtual int Receive(byte[] buf, int off, int len, int waitMillis) + { + lock (receiveQueue) + { + if (receiveQueue.Count < 1) + { + Monitor.Wait(waitMillis); + + if (receiveQueue.Count < 1) + { + return -1; + } + } + byte[] packet = (byte[])receiveQueue[0]; + receiveQueue.RemoveAt(0); + int copyLength = System.Math.Min(len, packet.Length); + Array.Copy(packet, 0, buf, off, copyLength); + return copyLength; + } + } + + public virtual void Send(byte[] buf, int off, int len) + { + if (len > mOuter.mtu) + { + // TODO Simulate rejection? + } + + byte[] packet = Arrays.CopyOfRange(buf, off, off + len); + + lock (sendQueue) + { + sendQueue.Add(packet); + Monitor.PulseAll(sendQueue); + } + } + + public virtual void Close() + { + // TODO? + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs index 4e183cba1..a186a8b58 100644 --- a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs @@ -123,7 +123,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { X509CertificateStructure entry = chain[i]; // TODO Create Fingerprint based on certificate signature algorithm digest - Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } } diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs index 7225d84ce..2b9549e82 100644 --- a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs @@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { X509CertificateStructure entry = chain[i]; // TODO Create Fingerprint based on certificate signature algorithm digest - Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } } diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index fd673c3b9..dbeb3fe41 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { X509CertificateStructure entry = chain[i]; // TODO Create Fingerprint based on certificate signature algorithm digest - Console.WriteLine(" Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } } diff --git a/crypto/test/src/crypto/tls/test/NetworkStream.cs b/crypto/test/src/crypto/tls/test/NetworkStream.cs new file mode 100644 index 000000000..04de81e13 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/NetworkStream.cs @@ -0,0 +1,101 @@ +using System; +using System.IO; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class NetworkStream + : Stream + { + private readonly Stream mInner; + private bool mClosed = false; + + internal NetworkStream(Stream inner) + { + this.mInner = inner; + } + + internal virtual bool IsClosed + { + get { lock (this) return mClosed; } + } + + public override bool CanRead + { + get { return mInner.CanRead; } + } + + public override bool CanSeek + { + get { return mInner.CanSeek; } + } + + public override bool CanWrite + { + get { return mInner.CanWrite; } + } + + public override void Close() + { + lock (this) mClosed = true; + } + + public override void Flush() + { + mInner.Flush(); + } + + public override long Length + { + get { return mInner.Length; } + } + + public override long Position + { + get { return mInner.Position; } + set { mInner.Position = value; } + } + + public override long Seek(long offset, SeekOrigin origin) + { + return mInner.Seek(offset, origin); + } + + public override void SetLength(long value) + { + mInner.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + CheckNotClosed(); + return mInner.Read(buffer, offset, count); + } + + public override int ReadByte() + { + CheckNotClosed(); + return mInner.ReadByte(); + } + + public override void Write(byte[] buf, int off, int len) + { + CheckNotClosed(); + mInner.Write(buf, off, len); + } + + public override void WriteByte(byte value) + { + CheckNotClosed(); + mInner.WriteByte(value); + } + + private void CheckNotClosed() + { + lock (this) + { + if (mClosed) + throw new ObjectDisposedException(this.GetType().Name); + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs new file mode 100644 index 000000000..8ac1c4ed2 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs @@ -0,0 +1,158 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class TlsTestCase + { + private static void CheckTlsVersion(ProtocolVersion version) + { + if (version != null && !version.IsTls) + throw new InvalidOperationException("Non-TLS version"); + } + + [Test, TestCaseSource(typeof(TlsTestSuite), "Suite")] + public void RunTest(TlsTestConfig config) + { + CheckTlsVersion(config.clientMinimumVersion); + CheckTlsVersion(config.clientOfferVersion); + CheckTlsVersion(config.serverMaximumVersion); + CheckTlsVersion(config.serverMinimumVersion); + + SecureRandom secureRandom = new SecureRandom(); + + PipedStream clientPipe = new PipedStream(); + PipedStream serverPipe = new PipedStream(clientPipe); + + NetworkStream clientNet = new NetworkStream(clientPipe); + NetworkStream serverNet = new NetworkStream(serverPipe); + + TlsClientProtocol clientProtocol = new TlsClientProtocol(clientNet, secureRandom); + TlsServerProtocol serverProtocol = new TlsServerProtocol(serverNet, secureRandom); + + TlsTestClientImpl clientImpl = new TlsTestClientImpl(config); + TlsTestServerImpl serverImpl = new TlsTestServerImpl(config); + + Server server = new Server(this, serverProtocol, serverImpl); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + Exception caught = null; + try + { + clientProtocol.Connect(clientImpl); + + // NOTE: Because we write-all before we read-any, this length can't be more than the pipe capacity + int length = 1000; + + byte[] data = new byte[length]; + secureRandom.NextBytes(data); + + Stream output = clientProtocol.Stream; + output.Write(data, 0, data.Length); + + byte[] echo = new byte[data.Length]; + int count = Streams.ReadFully(clientProtocol.Stream, echo); + + Assert.AreEqual(count, data.Length); + Assert.IsTrue(Arrays.AreEqual(data, echo)); + + output.Close(); + } + catch (Exception e) + { + caught = e; + LogException(caught); + } + + server.AllowExit(); + serverThread.Join(); + + Assert.IsTrue(clientNet.IsClosed, "Client Stream not closed"); + Assert.IsTrue(serverNet.IsClosed, "Server Stream not closed"); + + Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end"); + Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end"); + + Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description"); + Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description"); + + if (config.expectFatalAlertConnectionEnd == -1) + { + Assert.IsNull(caught, "Unexpected client exception"); + Assert.IsNull(server.mCaught, "Unexpected server exception"); + } + } + + protected virtual void LogException(Exception e) + { + if (TlsTestConfig.DEBUG) + { + Console.Error.WriteLine(e); + } + } + + internal class Server + { + protected readonly TlsTestCase mOuter; + protected readonly TlsServerProtocol mServerProtocol; + protected readonly TlsTestServerImpl mServerImpl; + + internal bool mCanExit = false; + internal Exception mCaught = null; + + internal Server(TlsTestCase outer, TlsServerProtocol serverProtocol, TlsTestServerImpl serverImpl) + { + this.mOuter = outer; + this.mServerProtocol = serverProtocol; + this.mServerImpl = serverImpl; + } + + internal void AllowExit() + { + lock (this) + { + mCanExit = true; + Monitor.PulseAll(this); + } + } + + public void Run() + { + try + { + mServerProtocol.Accept(mServerImpl); + Streams.PipeAll(mServerProtocol.Stream, mServerProtocol.Stream); + mServerProtocol.Close(); + } + catch (Exception e) + { + mCaught = e; + mOuter.LogException(mCaught); + } + + WaitExit(); + } + + protected void WaitExit() + { + lock (this) + { + while (!mCanExit) + { + Monitor.Wait(this); + } + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs new file mode 100644 index 000000000..48af9e0f8 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestClientImpl.cs @@ -0,0 +1,262 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestClientImpl + : DefaultTlsClient + { + protected readonly TlsTestConfig mConfig; + + protected int firstFatalAlertConnectionEnd = -1; + protected int firstFatalAlertDescription = -1; + + internal TlsTestClientImpl(TlsTestConfig config) + { + this.mConfig = config; + } + + internal int FirstFatalAlertConnectionEnd + { + get { return firstFatalAlertConnectionEnd; } + } + + internal int FirstFatalAlertDescription + { + get { return firstFatalAlertDescription; } + } + + public override ProtocolVersion ClientVersion + { + get + { + if (mConfig.clientOfferVersion != null) + { + return mConfig.clientOfferVersion; + } + + return base.ClientVersion; + } + } + + public override ProtocolVersion MinimumVersion + { + get + { + if (mConfig.clientMinimumVersion != null) + { + return mConfig.clientMinimumVersion; + } + + return base.MinimumVersion; + } + } + + public override bool IsFallback + { + get { return mConfig.clientFallback; } + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.client; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.server; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS client negotiated " + serverVersion); + } + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(this, mContext); + } + + protected virtual Certificate CorruptCertificate(Certificate cert) + { + X509CertificateStructure[] certList = cert.GetCertificateList(); + certList[0] = CorruptCertificateSignature(certList[0]); + return new Certificate(certList); + } + + protected virtual X509CertificateStructure CorruptCertificateSignature(X509CertificateStructure cert) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + v.Add(cert.TbsCertificate); + v.Add(cert.SignatureAlgorithm); + v.Add(CorruptBitString(cert.Signature)); + + return X509CertificateStructure.GetInstance(new DerSequence(v)); + } + + protected virtual DerBitString CorruptBitString(DerBitString bs) + { + return new DerBitString(CorruptBit(bs.GetBytes())); + } + + protected virtual byte[] CorruptBit(byte[] bs) + { + bs = Arrays.Clone(bs); + + // Flip a random bit + int bit = mContext.SecureRandom.Next(bs.Length << 3); + bs[bit >> 3] ^= (byte)(1 << (bit & 7)); + + return bs; + } + + internal class MyTlsAuthentication + : TlsAuthentication + { + private readonly TlsTestClientImpl mOuter; + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsTestClientImpl outer, TlsContext context) + { + this.mOuter = outer; + this.mContext = context; + } + + public virtual void NotifyServerCertificate(Certificate serverCertificate) + { + bool isEmpty = serverCertificate == null || serverCertificate.IsEmpty; + + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + + // TODO Cache test resources? + if (isEmpty || !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-dsa.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-server-ecdsa.pem")))) + { + throw new TlsFatalAlert(AlertDescription.bad_certificate); + } + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + } + + public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) + { + if (mOuter.mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE) + throw new InvalidOperationException(); + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE) + return null; + + byte[] certificateTypes = certificateRequest.CertificateTypes; + if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) + { + return null; + } + + TlsSignerCredentials signerCredentials = TlsTestUtilities.LoadSignerCredentials(mContext, + certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-client.pem", "x509-client-key.pem"); + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_VALID) + { + return signerCredentials; + } + + return new MyTlsSignerCredentials(mOuter, signerCredentials); + } + }; + + internal class MyTlsSignerCredentials + : TlsSignerCredentials + { + private readonly TlsTestClientImpl mOuter; + private readonly TlsSignerCredentials mInner; + + internal MyTlsSignerCredentials(TlsTestClientImpl outer, TlsSignerCredentials inner) + { + this.mOuter = outer; + this.mInner = inner; + } + + public virtual byte[] GenerateCertificateSignature(byte[] hash) + { + byte[] sig = mInner.GenerateCertificateSignature(hash); + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_VERIFY) + { + sig = mOuter.CorruptBit(sig); + } + + return sig; + } + + public virtual Certificate Certificate + { + get + { + Certificate cert = mInner.Certificate; + + if (mOuter.mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_INVALID_CERT) + { + cert = mOuter.CorruptCertificate(cert); + } + + return cert; + } + } + + public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm + { + get { return mInner.SignatureAndHashAlgorithm; } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestConfig.cs b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs new file mode 100644 index 000000000..0d1e7badb --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestConfig.cs @@ -0,0 +1,101 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class TlsTestConfig + { + public static readonly bool DEBUG = false; + + /** + * Client does not authenticate, ignores any certificate request + */ + public const int CLIENT_AUTH_NONE = 0; + + /** + * Client will authenticate if it receives a certificate request + */ + public const int CLIENT_AUTH_VALID = 1; + + /** + * Client will authenticate if it receives a certificate request, with an invalid certificate + */ + public const int CLIENT_AUTH_INVALID_CERT = 2; + + /** + * Client will authenticate if it receives a certificate request, with an invalid CertificateVerify signature + */ + public const int CLIENT_AUTH_INVALID_VERIFY = 3; + + /** + * Server will not request a client certificate + */ + public const int SERVER_CERT_REQ_NONE = 0; + + /** + * Server will request a client certificate but receiving one is optional + */ + public const int SERVER_CERT_REQ_OPTIONAL = 1; + + /** + * Server will request a client certificate and receiving one is mandatory + */ + public const int SERVER_CERT_REQ_MANDATORY = 2; + + /** + * Configures the client authentication behaviour of the test client. Use CLIENT_AUTH_* constants. + */ + public int clientAuth = CLIENT_AUTH_VALID; + + /** + * Configures the minimum protocol version the client will accept. If null, uses the library's default. + */ + public ProtocolVersion clientMinimumVersion = null; + + /** + * Configures the protocol version the client will offer. If null, uses the library's default. + */ + public ProtocolVersion clientOfferVersion = null; + + /** + * Configures whether the client will indicate version fallback via TLS_FALLBACK_SCSV. + */ + public bool clientFallback = false; + + /** + * Configures whether the test server will send a certificate request. + */ + public int serverCertReq = SERVER_CERT_REQ_OPTIONAL; + + /** + * Configures the maximum protocol version the server will accept. If null, uses the library's default. + */ + public ProtocolVersion serverMaximumVersion = null; + + /** + * Configures the minimum protocol version the server will accept. If null, uses the library's default. + */ + public ProtocolVersion serverMinimumVersion = null; + + /** + * Configures the connection end that a fatal alert is expected to be raised. Use ConnectionEnd.* constants. + */ + public int expectFatalAlertConnectionEnd = -1; + + /** + * Configures the type of fatal alert expected to be raised. Use AlertDescription.* constants. + */ + public int expectFatalAlertDescription = -1; + + public void ExpectClientFatalAlert(byte alertDescription) + { + this.expectFatalAlertConnectionEnd = ConnectionEnd.client; + this.expectFatalAlertDescription = alertDescription; + } + + public void ExpectServerFatalAlert(byte alertDescription) + { + this.expectFatalAlertConnectionEnd = ConnectionEnd.server; + this.expectFatalAlertDescription = alertDescription; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs new file mode 100644 index 000000000..152d5dbdc --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestServerImpl.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + internal class TlsTestServerImpl + : DefaultTlsServer + { + protected readonly TlsTestConfig mConfig; + + protected int firstFatalAlertConnectionEnd = -1; + protected int firstFatalAlertDescription = -1; + + internal TlsTestServerImpl(TlsTestConfig config) + { + this.mConfig = config; + } + + internal int FirstFatalAlertConnectionEnd + { + get { return firstFatalAlertConnectionEnd; } + } + + internal int FirstFatalAlertDescription + { + get { return firstFatalAlertDescription; } + } + + protected override ProtocolVersion MaximumVersion + { + get + { + if (mConfig.serverMaximumVersion != null) + { + return mConfig.serverMaximumVersion; + } + + return base.MaximumVersion; + } + } + + protected override ProtocolVersion MinimumVersion + { + get + { + if (mConfig.serverMinimumVersion != null) + { + return mConfig.serverMinimumVersion; + } + + return base.MinimumVersion; + } + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.server; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + if (alertLevel == AlertLevel.fatal && firstFatalAlertConnectionEnd == -1) + { + firstFatalAlertConnectionEnd = ConnectionEnd.client; + firstFatalAlertDescription = alertDescription; + } + + if (TlsTestConfig.DEBUG) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("TLS server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + } + + public override ProtocolVersion GetServerVersion() + { + ProtocolVersion serverVersion = base.GetServerVersion(); + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS server negotiated " + serverVersion); + } + + return serverVersion; + } + + public override CertificateRequest GetCertificateRequest() + { + if (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_NONE) + { + return null; + } + + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + + IList serverSigAlgs = null; + if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) + { + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + } + + IList certificateAuthorities = new ArrayList(); + certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); + + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); + } + + public override void NotifyClientCertificate(Certificate clientCertificate) + { + bool isEmpty = (clientCertificate == null || clientCertificate.IsEmpty); + + if (isEmpty != (mConfig.clientAuth == TlsTestConfig.CLIENT_AUTH_NONE)) + { + throw new InvalidOperationException(); + } + if (isEmpty && (mConfig.serverCertReq == TlsTestConfig.SERVER_CERT_REQ_MANDATORY)) + { + throw new TlsFatalAlert(AlertDescription.handshake_failure); + } + + X509CertificateStructure[] chain = clientCertificate.GetCertificateList(); + + // TODO Cache test resources? + if (!isEmpty && !(chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-dsa.pem")) + || chain[0].Equals(TlsTestUtilities.LoadCertificateResource("x509-client-ecdsa.pem")))) + { + throw new TlsFatalAlert(AlertDescription.bad_certificate); + } + + if (TlsTestConfig.DEBUG) + { + Console.WriteLine("TLS server received client certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + } + + protected override TlsSignerCredentials GetDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.dsa, + "x509-server-dsa.pem", "x509-server-key-dsa.pem"); + } + + protected override TlsSignerCredentials GetECDsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.ecdsa, + "x509-server-ecdsa.pem", "x509-server-key-ecdsa.pem"); + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{ "x509-server.pem", "x509-ca.pem" }, + "x509-server-key.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestSuite.cs b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs new file mode 100644 index 000000000..dfd09d06e --- /dev/null +++ b/crypto/test/src/crypto/tls/test/TlsTestSuite.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class TlsTestSuite + { + // Make the access to constants less verbose + internal class C : TlsTestConfig {} + + public TlsTestSuite() + { + } + + public static IEnumerable Suite() + { + IList testSuite = new ArrayList(); + + AddFallbackTests(testSuite); + AddVersionTests(testSuite, ProtocolVersion.TLSv10); + AddVersionTests(testSuite, ProtocolVersion.TLSv11); + AddVersionTests(testSuite, ProtocolVersion.TLSv12); + + return testSuite; + } + + private static void AddFallbackTests(IList testSuite) + { + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientFallback = true; + + testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientOfferVersion = ProtocolVersion.TLSv11; + c.clientFallback = true; + c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); + + testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(ProtocolVersion.TLSv12); + c.clientOfferVersion = ProtocolVersion.TLSv11; + + testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + } + } + + private static void AddVersionTests(IList testSuite, ProtocolVersion version) + { + string prefix = version.ToString() + .Replace(" ", "") + .Replace("\\", "") + .Replace(".", "") + + "_"; + + { + TlsTestConfig c = CreateTlsTestConfig(version); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; + c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; + c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; + c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.serverCertReq = C.SERVER_CERT_REQ_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + } + + { + TlsTestConfig c = CreateTlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + } + } + + private static TlsTestConfig CreateTlsTestConfig(ProtocolVersion version) + { + TlsTestConfig c = new TlsTestConfig(); + c.clientMinimumVersion = ProtocolVersion.TLSv10; + c.clientOfferVersion = ProtocolVersion.TLSv12; + c.serverMaximumVersion = version; + c.serverMinimumVersion = ProtocolVersion.TLSv10; + return c; + } + } +} diff --git a/crypto/test/src/math/ec/test/AllTests.cs b/crypto/test/src/math/ec/test/AllTests.cs index d4c7dc768..3e014ffd2 100644 --- a/crypto/test/src/math/ec/test/AllTests.cs +++ b/crypto/test/src/math/ec/test/AllTests.cs @@ -7,22 +7,21 @@ namespace Org.BouncyCastle.Math.EC.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("EC Math tests"); - - suite.Add(new ECAlgorithmsTest()); - suite.Add(new ECPointTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("EC Math tests"); + suite.Add(new ECAlgorithmsTest()); + suite.Add(new ECPointTest()); + return suite; + } } } } diff --git a/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs index 6f2b50140..40cfe3774 100644 --- a/crypto/test/src/math/test/AllTests.cs +++ b/crypto/test/src/math/test/AllTests.cs @@ -7,21 +7,20 @@ namespace Org.BouncyCastle.Math.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { -// junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("Math tests"); - - suite.Add(new BigIntegerTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("Math tests"); + suite.Add(new BigIntegerTest()); + return suite; + } } } } diff --git a/crypto/test/src/ocsp/test/AllTests.cs b/crypto/test/src/ocsp/test/AllTests.cs index 2b30e3ad4..5e919fd91 100644 --- a/crypto/test/src/ocsp/test/AllTests.cs +++ b/crypto/test/src/ocsp/test/AllTests.cs @@ -9,21 +9,20 @@ namespace Org.BouncyCastle.Ocsp.Tests { public class AllTests { - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - public static TestSuite suite() - { - TestSuite suite = new TestSuite("OCSP Tests"); - - suite.Add(new OcspTest()); - - return suite; - } + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OCSP Tests"); + suite.Add(new OcspTest()); + return suite; + } + } } } diff --git a/crypto/test/src/openpgp/examples/test/AllTests.cs b/crypto/test/src/openpgp/examples/test/AllTests.cs index 180d2fa80..e9a7a744d 100644 --- a/crypto/test/src/openpgp/examples/test/AllTests.cs +++ b/crypto/test/src/openpgp/examples/test/AllTests.cs @@ -382,22 +382,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests return bRd.ReadLine(); } - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); - } - - public static TestSuite suite() - { - TestSuite suite = new TestSuite("OpenPGP Example Tests"); - - suite.Add(new AllTests()); - - return suite; - } - + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } + + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OpenPGP Example Tests"); + suite.Add(new AllTests()); + return suite; + } + } } } diff --git a/crypto/test/src/openssl/test/AllTests.cs b/crypto/test/src/openssl/test/AllTests.cs index 921208179..f843d0479 100644 --- a/crypto/test/src/openssl/test/AllTests.cs +++ b/crypto/test/src/openssl/test/AllTests.cs @@ -32,19 +32,24 @@ namespace Org.BouncyCastle.OpenSsl.Tests return (char[]) password.Clone(); } } - - [Suite] - public static TestSuite Suite - { - get - { - TestSuite suite = new TestSuite("OpenSSL Tests"); - suite.Add(new AllTests()); - return suite; - } - } - [Test] + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } + + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("OpenSSL Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] public void TestOpenSsl() { Org.BouncyCastle.Utilities.Test.ITest[] tests = new Org.BouncyCastle.Utilities.Test.ITest[]{ @@ -121,13 +126,5 @@ namespace Org.BouncyCastle.OpenSsl.Tests Assert.AreEqual(privKey, rdKey); } - - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - Suite.Run(el); - } } } diff --git a/crypto/test/src/tsp/test/AllTests.cs b/crypto/test/src/tsp/test/AllTests.cs index 66dc9c480..3e8b0cd5e 100644 --- a/crypto/test/src/tsp/test/AllTests.cs +++ b/crypto/test/src/tsp/test/AllTests.cs @@ -9,24 +9,23 @@ namespace Org.BouncyCastle.Tsp.Tests { public class AllTests { - public static void Main( - string[] args) + public static void Main(string[] args) { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - suite().Run(el); + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); } - public static TestSuite suite() + [Suite] + public static TestSuite Suite { - TestSuite suite = new TestSuite("TSP Tests"); - - suite.Add(new GenTimeAccuracyUnitTest()); - suite.Add(new ParseTest()); - suite.Add(new TimeStampTokenInfoUnitTest()); - suite.Add(new TspTest()); - - return suite; + get + { + TestSuite suite = new TestSuite("TSP Tests"); + suite.Add(new GenTimeAccuracyUnitTest()); + suite.Add(new ParseTest()); + suite.Add(new TimeStampTokenInfoUnitTest()); + suite.Add(new TspTest()); + return suite; + } } } } diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs index b44949383..c36f79304 100644 --- a/crypto/test/src/util/io/pem/test/AllTests.cs +++ b/crypto/test/src/util/io/pem/test/AllTests.cs @@ -19,18 +19,23 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests [TestFixture] public class AllTests { - [Suite] - public static TestSuite Suite - { - get - { - TestSuite suite = new TestSuite("PEM Utilities Tests"); - suite.Add(new AllTests()); - return suite; - } - } + public static void Main(string[] args) + { + Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty); + } - [Test] + [Suite] + public static TestSuite Suite + { + get + { + TestSuite suite = new TestSuite("PEM Utilities Tests"); + suite.Add(new AllTests()); + return suite; + } + } + + [Test] public void TestPemLength() { for (int i = 1; i != 60; i++) @@ -65,13 +70,5 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests Assert.AreEqual(sw.ToString().Length, pWrt.GetOutputSize(pemObj)); } - - public static void Main( - string[] args) - { - //junit.textui.TestRunner.run(suite()); - EventListener el = new NullListener(); - Suite.Run(el); - } } } -- cgit 1.4.1 From 652d1db675ca9bd3b41914649dd4e61f32c238e6 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 9 Mar 2015 23:25:20 +0700 Subject: Port of DTLS tests from Java --- crypto/crypto.csproj | 30 ++++ crypto/src/crypto/tls/DtlsReliableHandshake.cs | 8 +- .../test/src/crypto/tls/test/DtlsProtocolTest.cs | 102 ++++++++++++++ crypto/test/src/crypto/tls/test/DtlsTestCase.cs | 153 +++++++++++++++++++++ crypto/test/src/crypto/tls/test/DtlsTestSuite.cs | 134 ++++++++++++++++++ .../src/crypto/tls/test/MockDatagramAssociation.cs | 18 ++- crypto/test/src/crypto/tls/test/MockDtlsClient.cs | 151 ++++++++++++++++++++ crypto/test/src/crypto/tls/test/MockDtlsServer.cs | 100 ++++++++++++++ .../test/src/crypto/tls/test/MockPskTlsClient.cs | 2 +- .../test/src/crypto/tls/test/MockSrpTlsClient.cs | 2 +- crypto/test/src/crypto/tls/test/MockTlsClient.cs | 2 +- .../test/src/crypto/tls/test/PskTlsClientTest.cs | 79 +++++++++++ crypto/test/src/crypto/tls/test/TlsTestCase.cs | 8 +- 13 files changed, 775 insertions(+), 14 deletions(-) create mode 100644 crypto/test/src/crypto/tls/test/DtlsProtocolTest.cs create mode 100644 crypto/test/src/crypto/tls/test/DtlsTestCase.cs create mode 100644 crypto/test/src/crypto/tls/test/DtlsTestSuite.cs create mode 100644 crypto/test/src/crypto/tls/test/MockDtlsClient.cs create mode 100644 crypto/test/src/crypto/tls/test/MockDtlsServer.cs create mode 100644 crypto/test/src/crypto/tls/test/PskTlsClientTest.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 9d185ade3..35474aebb 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11087,6 +11087,21 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + = 0) + { + } + + dtlsClient.Close(); + + server.Shutdown(serverThread); + } + + internal class Server + { + private readonly DtlsServerProtocol mServerProtocol; + private readonly DatagramTransport mServerTransport; + private volatile bool isShutdown = false; + + internal Server(DtlsServerProtocol serverProtocol, DatagramTransport serverTransport) + { + this.mServerProtocol = serverProtocol; + this.mServerTransport = serverTransport; + } + + public void Run() + { + try + { + MockDtlsServer server = new MockDtlsServer(); + DtlsTransport dtlsServer = mServerProtocol.Accept(server, mServerTransport); + byte[] buf = new byte[dtlsServer.GetReceiveLimit()]; + while (!isShutdown) + { + int length = dtlsServer.Receive(buf, 0, buf.Length, 1000); + if (length >= 0) + { + dtlsServer.Send(buf, 0, length); + } + } + dtlsServer.Close(); + } + catch (Exception e) + { + Console.Error.WriteLine(e.StackTrace); + } + } + + internal void Shutdown(Thread serverThread) + { + if (!isShutdown) + { + isShutdown = true; + serverThread.Join(); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestCase.cs b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs new file mode 100644 index 000000000..d4af04fac --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestCase.cs @@ -0,0 +1,153 @@ +using System; +using System.IO; +using System.Threading; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + [TestFixture] + public class DtlsTestCase + { + private static void CheckDtlsVersion(ProtocolVersion version) + { + if (version != null && !version.IsDtls) + throw new InvalidOperationException("Non-DTLS version"); + } + + [Test, TestCaseSource(typeof(DtlsTestSuite), "Suite")] + public void RunTest(TlsTestConfig config) + { + CheckDtlsVersion(config.clientMinimumVersion); + CheckDtlsVersion(config.clientOfferVersion); + CheckDtlsVersion(config.serverMaximumVersion); + CheckDtlsVersion(config.serverMinimumVersion); + + SecureRandom secureRandom = new SecureRandom(); + + DtlsClientProtocol clientProtocol = new DtlsClientProtocol(secureRandom); + DtlsServerProtocol serverProtocol = new DtlsServerProtocol(secureRandom); + + MockDatagramAssociation network = new MockDatagramAssociation(1500); + + TlsTestClientImpl clientImpl = new TlsTestClientImpl(config); + TlsTestServerImpl serverImpl = new TlsTestServerImpl(config); + + Server server = new Server(this, serverProtocol, network.Server, serverImpl); + + Thread serverThread = new Thread(new ThreadStart(server.Run)); + serverThread.Start(); + + Exception caught = null; + try + { + DatagramTransport clientTransport = network.Client; + + if (TlsTestConfig.DEBUG) + { + clientTransport = new LoggingDatagramTransport(clientTransport, Console.Out); + } + + DtlsTransport dtlsClient = clientProtocol.Connect(clientImpl, clientTransport); + + for (int i = 1; i <= 10; ++i) + { + byte[] data = new byte[i]; + Arrays.Fill(data, (byte)i); + dtlsClient.Send(data, 0, data.Length); + } + + byte[] buf = new byte[dtlsClient.GetReceiveLimit()]; + while (dtlsClient.Receive(buf, 0, buf.Length, 100) >= 0) + { + } + + dtlsClient.Close(); + } + catch (Exception e) + { + caught = e; + LogException(caught); + } + + server.Shutdown(serverThread); + + // TODO Add checks that the various streams were closed + + Assert.AreEqual(config.expectFatalAlertConnectionEnd, clientImpl.FirstFatalAlertConnectionEnd, "Client fatal alert connection end"); + Assert.AreEqual(config.expectFatalAlertConnectionEnd, serverImpl.FirstFatalAlertConnectionEnd, "Server fatal alert connection end"); + + Assert.AreEqual(config.expectFatalAlertDescription, clientImpl.FirstFatalAlertDescription, "Client fatal alert description"); + Assert.AreEqual(config.expectFatalAlertDescription, serverImpl.FirstFatalAlertDescription, "Server fatal alert description"); + + if (config.expectFatalAlertConnectionEnd == -1) + { + Assert.IsNull(caught, "Unexpected client exception"); + Assert.IsNull(server.mCaught, "Unexpected server exception"); + } + } + + protected void LogException(Exception e) + { + if (TlsTestConfig.DEBUG) + { + Console.Error.WriteLine(e.StackTrace); + } + } + + internal class Server + { + private readonly DtlsTestCase mOuter; + private readonly DtlsServerProtocol mServerProtocol; + private readonly DatagramTransport mServerTransport; + private readonly TlsTestServerImpl mServerImpl; + + private volatile bool isShutdown = false; + internal Exception mCaught = null; + + internal Server(DtlsTestCase outer, DtlsServerProtocol serverProtocol, DatagramTransport serverTransport, TlsTestServerImpl serverImpl) + { + this.mOuter = outer; + this.mServerProtocol = serverProtocol; + this.mServerTransport = serverTransport; + this.mServerImpl = serverImpl; + } + + public void Run() + { + try + { + DtlsTransport dtlsServer = mServerProtocol.Accept(mServerImpl, mServerTransport); + byte[] buf = new byte[dtlsServer.GetReceiveLimit()]; + while (!isShutdown) + { + int length = dtlsServer.Receive(buf, 0, buf.Length, 100); + if (length >= 0) + { + dtlsServer.Send(buf, 0, length); + } + } + dtlsServer.Close(); + } + catch (Exception e) + { + mCaught = e; + mOuter.LogException(mCaught); + } + } + + internal void Shutdown(Thread serverThread) + { + if (!isShutdown) + { + isShutdown = true; + serverThread.Interrupt(); + serverThread.Join(); + } + } + } + } +} diff --git a/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs new file mode 100644 index 000000000..eb9d42e5f --- /dev/null +++ b/crypto/test/src/crypto/tls/test/DtlsTestSuite.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections; + +using NUnit.Framework; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class DtlsTestSuite + { + // Make the access to constants less verbose + internal class C : TlsTestConfig {} + + public DtlsTestSuite() + { + } + + public static IEnumerable Suite() + { + IList testSuite = new ArrayList(); + + AddFallbackTests(testSuite); + AddVersionTests(testSuite, ProtocolVersion.DTLSv10); + AddVersionTests(testSuite, ProtocolVersion.DTLSv12); + + return testSuite; + } + + private static void AddFallbackTests(IList testSuite) + { + { + TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + c.clientFallback = true; + + testSuite.Add(new TestCaseData(c).SetName("FallbackGood")); + } + + /* + * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit + * of the DTLS server after a fatal alert. As of writing, manual runs show the correct + * alerts being raised + */ + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + // c.clientOfferVersion = ProtocolVersion.DTLSv10; + // c.clientFallback = true; + // c.ExpectServerFatalAlert(AlertDescription.inappropriate_fallback); + + // testSuite.Add(new TestCaseData(c).SetName("FallbackBad")); + //} + + { + TlsTestConfig c = CreateDtlsTestConfig(ProtocolVersion.DTLSv12); + c.clientOfferVersion = ProtocolVersion.DTLSv10; + + testSuite.Add(new TestCaseData(c).SetName("FallbackNone")); + } + } + + private static void AddVersionTests(IList testSuite, ProtocolVersion version) + { + string prefix = version.ToString() + .Replace(" ", "") + .Replace("\\", "") + .Replace(".", "") + + "_"; + + /* + * NOTE: Temporarily disabled automatic test runs because of problems getting a clean exit + * of the DTLS server after a fatal alert. As of writing, manual runs show the correct + * alerts being raised + */ + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_INVALID_VERIFY; + // c.ExpectServerFatalAlert(AlertDescription.decrypt_error); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadCertificateVerify")); + //} + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_INVALID_CERT; + // c.ExpectServerFatalAlert(AlertDescription.bad_certificate); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadClientCertificate")); + //} + + //{ + // TlsTestConfig c = CreateDtlsTestConfig(version); + // c.clientAuth = C.CLIENT_AUTH_NONE; + // c.serverCertReq = C.SERVER_CERT_REQ_MANDATORY; + // c.ExpectServerFatalAlert(AlertDescription.handshake_failure); + + // testSuite.Add(new TestCaseData(c).SetName(prefix + "BadMandatoryCertReqDeclined")); + //} + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodDefault")); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.serverCertReq = C.SERVER_CERT_REQ_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodNoCertReq")); + } + + { + TlsTestConfig c = CreateDtlsTestConfig(version); + c.clientAuth = C.CLIENT_AUTH_NONE; + + testSuite.Add(new TestCaseData(c).SetName(prefix + "GoodOptionalCertReqDeclined")); + } + } + + private static TlsTestConfig CreateDtlsTestConfig(ProtocolVersion version) + { + TlsTestConfig c = new TlsTestConfig(); + c.clientMinimumVersion = ProtocolVersion.DTLSv10; + /* + * TODO We'd like to just set the offer version to DTLSv12, but there is a known issue with + * overly-restrictive version checks b/w BC DTLS 1.2 client, BC DTLS 1.0 server + */ + c.clientOfferVersion = version; + c.serverMaximumVersion = version; + c.serverMinimumVersion = ProtocolVersion.DTLSv10; + return c; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs index 0391f4fef..48df36ca9 100644 --- a/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs +++ b/crypto/test/src/crypto/tls/test/MockDatagramAssociation.cs @@ -24,14 +24,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests this.server = new MockDatagramTransport(this, serverQueue, clientQueue); } - public DatagramTransport getClient() + public virtual DatagramTransport Client { - return client; + get { return client; } } - public DatagramTransport getServer() + public virtual DatagramTransport Server { - return server; + get { return server; } } private class MockDatagramTransport @@ -64,8 +64,14 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { if (receiveQueue.Count < 1) { - Monitor.Wait(waitMillis); - + try + { + Monitor.Wait(receiveQueue, waitMillis); + } + catch (ThreadInterruptedException) + { + // TODO Keep waiting until full wait expired? + } if (receiveQueue.Count < 1) { return -1; diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs new file mode 100644 index 000000000..32491c425 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDtlsClient + : DefaultTlsClient + { + protected TlsSession mSession; + + public MockDtlsClient(TlsSession session) + { + this.mSession = session; + } + + public override TlsSession GetSessionToResume() + { + return this.mSession; + } + + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override ProtocolVersion ClientVersion + { + get { return ProtocolVersion.DTLSv12; } + } + + public override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.DTLSv10; } + } + + //public override int[] GetCipherSuites() + //{ + // return Arrays.Concatenate(base.GetCipherSuites(), + // new int[] + // { + // CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + // CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + // CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + // }); + //} + + public override IDictionary GetClientExtensions() + { + IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); + TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); + // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though) + //TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); + TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); + TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); + return clientExtensions; + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("Negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return new MyTlsAuthentication(mContext); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + TlsSession newSession = mContext.ResumableSession; + if (newSession != null) + { + byte[] newSessionID = newSession.SessionID; + string hex = Hex.ToHexString(newSessionID); + + if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID)) + { + Console.WriteLine("Resumed session: " + hex); + } + else + { + Console.WriteLine("Established session: " + hex); + } + + this.mSession = newSession; + } + } + + internal class MyTlsAuthentication + : TlsAuthentication + { + private readonly TlsContext mContext; + + internal MyTlsAuthentication(TlsContext context) + { + this.mContext = context; + } + + public virtual void NotifyServerCertificate(Certificate serverCertificate) + { + X509CertificateStructure[] chain = serverCertificate.GetCertificateList(); + Console.WriteLine("DTLS client received server certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + + public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) + { + byte[] certificateTypes = certificateRequest.CertificateTypes; + if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) + return null; + + return TlsTestUtilities.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms, + SignatureAlgorithm.rsa, "x509-client.pem", "x509-client-key.pem"); + } + }; + } +} diff --git a/crypto/test/src/crypto/tls/test/MockDtlsServer.cs b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs new file mode 100644 index 000000000..19062181b --- /dev/null +++ b/crypto/test/src/crypto/tls/test/MockDtlsServer.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections; +using System.IO; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + public class MockDtlsServer + : DefaultTlsServer + { + public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS server raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(byte alertLevel, byte alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS server received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + protected override int[] GetCipherSuites() + { + return Arrays.Concatenate(base.GetCipherSuites(), + new int[] + { + CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1, + CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1, + CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1, + CipherSuite.TLS_RSA_WITH_SALSA20_SHA1, + }); + } + + public override CertificateRequest GetCertificateRequest() + { + byte[] certificateTypes = new byte[]{ ClientCertificateType.rsa_sign, + ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign }; + + IList serverSigAlgs = null; + if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion)) + { + serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(); + } + + IList certificateAuthorities = new ArrayList(); + certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject); + + return new CertificateRequest(certificateTypes, serverSigAlgs, certificateAuthorities); + } + + public override void NotifyClientCertificate(Certificate clientCertificate) + { + X509CertificateStructure[] chain = clientCertificate.GetCertificateList(); + Console.WriteLine("DTLS server received client certificate chain of length " + chain.Length); + for (int i = 0; i != chain.Length; i++) + { + X509CertificateStructure entry = chain[i]; + // TODO Create fingerprint based on certificate signature algorithm digest + Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + + entry.Subject + ")"); + } + } + + protected override ProtocolVersion MaximumVersion + { + get { return ProtocolVersion.DTLSv12; } + } + + protected override ProtocolVersion MinimumVersion + { + get { return ProtocolVersion.DTLSv10; } + } + + protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() + { + return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[] { "x509-server.pem", "x509-ca.pem" }, + "x509-server-key.pem"); + } + + protected override TlsSignerCredentials GetRsaSignerCredentials() + { + return TlsTestUtilities.LoadSignerCredentials(mContext, mSupportedSignatureAlgorithms, SignatureAlgorithm.rsa, + "x509-server.pem", "x509-server-key.pem"); + } + } +} diff --git a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs index a186a8b58..dfc0e93a0 100644 --- a/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockPskTlsClient.cs @@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests for (int i = 0; i != chain.Length; i++) { X509CertificateStructure entry = chain[i]; - // TODO Create Fingerprint based on certificate signature algorithm digest + // TODO Create fingerprint based on certificate signature algorithm digest Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } diff --git a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs index 2b9549e82..8a6b9f496 100644 --- a/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockSrpTlsClient.cs @@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests for (int i = 0; i != chain.Length; i++) { X509CertificateStructure entry = chain[i]; - // TODO Create Fingerprint based on certificate signature algorithm digest + // TODO Create fingerprint based on certificate signature algorithm digest Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index dbeb3fe41..4d7c59afa 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -121,7 +121,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests for (int i = 0; i != chain.Length; i++) { X509CertificateStructure entry = chain[i]; - // TODO Create Fingerprint based on certificate signature algorithm digest + // TODO Create fingerprint based on certificate signature algorithm digest Console.WriteLine(" fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " (" + entry.Subject + ")"); } diff --git a/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs new file mode 100644 index 000000000..7072c7105 --- /dev/null +++ b/crypto/test/src/crypto/tls/test/PskTlsClientTest.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using System.Net.Sockets; +using System.Text; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Tls.Tests +{ + /** + * A simple test designed to conduct a TLS handshake with an external TLS server. + *

+ * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in + * this package (under 'src/test/resources') for help configuring an external TLS server. + *

+ * In both cases, extra options are required to enable PSK ciphersuites and configure identities/keys. + *

+ */ + public class PskTlsClientTest + { + private static readonly SecureRandom secureRandom = new SecureRandom(); + + public static void Main(string[] args) + { + string hostname = "localhost"; + int port = 5556; + + long time1 = DateTime.UtcNow.Ticks; + + /* + * Note: This is the default PSK identity for 'openssl s_server' testing, the server must be + * started with "-psk 6161616161" to make the keys match, and possibly the "-psk_hint" + * option should be present. + */ + string psk_identity = "Client_identity"; + byte[] psk = new byte[]{ 0x61, 0x61, 0x61, 0x61, 0x61 }; + + BasicTlsPskIdentity pskIdentity = new BasicTlsPskIdentity(psk_identity, psk); + + MockPskTlsClient client = new MockPskTlsClient(null, pskIdentity); + TlsClientProtocol protocol = OpenTlsConnection(hostname, port, client); + protocol.Close(); + + long time2 = DateTime.UtcNow.Ticks; + Console.WriteLine("Elapsed 1: " + (time2 - time1)/TimeSpan.TicksPerMillisecond + "ms"); + + client = new MockPskTlsClient(client.GetSessionToResume(), pskIdentity); + protocol = OpenTlsConnection(hostname, port, client); + + long time3 = DateTime.UtcNow.Ticks; + Console.WriteLine("Elapsed 2: " + (time3 - time2)/TimeSpan.TicksPerMillisecond + "ms"); + + byte[] req = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n\r\n"); + + Stream tlsStream = protocol.Stream; + tlsStream.Write(req, 0, req.Length); + tlsStream.Flush(); + + StreamReader reader = new StreamReader(tlsStream); + + String line; + while ((line = reader.ReadLine()) != null) + { + Console.WriteLine(">>> " + line); + } + + protocol.Close(); + } + + internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client) + { + TcpClient tcp = new TcpClient(hostname, port); + + TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom); + protocol.Connect(client); + return protocol; + } + } +} diff --git a/crypto/test/src/crypto/tls/test/TlsTestCase.cs b/crypto/test/src/crypto/tls/test/TlsTestCase.cs index 8ac1c4ed2..4b0c12710 100644 --- a/crypto/test/src/crypto/tls/test/TlsTestCase.cs +++ b/crypto/test/src/crypto/tls/test/TlsTestCase.cs @@ -149,7 +149,13 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { while (!mCanExit) { - Monitor.Wait(this); + try + { + Monitor.Wait(this); + } + catch (ThreadInterruptedException) + { + } } } } -- cgit 1.4.1 From 57dde9f1c5a892deb482327d7da57c99a1be5cae Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 10 Mar 2015 19:05:07 +0700 Subject: Update TLS for draft-ietf-tls-session-hash-04 --- crypto/src/crypto/tls/AbstractTlsContext.cs | 9 +++++++ crypto/src/crypto/tls/DtlsClientProtocol.cs | 33 +++++++++-------------- crypto/src/crypto/tls/DtlsServerProtocol.cs | 6 +++++ crypto/src/crypto/tls/ExporterLabel.cs | 2 +- crypto/src/crypto/tls/ExtensionType.cs | 2 +- crypto/src/crypto/tls/TlsClientProtocol.cs | 33 +++++++---------------- crypto/src/crypto/tls/TlsServerProtocol.cs | 6 +++++ crypto/test/src/crypto/tls/test/MockDtlsClient.cs | 3 +-- crypto/test/src/crypto/tls/test/MockTlsClient.cs | 3 +-- 9 files changed, 47 insertions(+), 50 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/tls/AbstractTlsContext.cs b/crypto/src/crypto/tls/AbstractTlsContext.cs index 83150d37e..e283ee58c 100644 --- a/crypto/src/crypto/tls/AbstractTlsContext.cs +++ b/crypto/src/crypto/tls/AbstractTlsContext.cs @@ -96,6 +96,15 @@ namespace Org.BouncyCastle.Crypto.Tls public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length) { + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 5.4. If a client or server chooses to continue with a full + * handshake without the extended master secret extension, [..] the client or server MUST + * NOT export any key material based on the new master secret for any subsequent + * application-level authentication. In particular, it MUST disable [RFC5705] [..]. + */ + if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length)) throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value"); diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs index 200bb1946..76635065c 100644 --- a/crypto/src/crypto/tls/DtlsClientProtocol.cs +++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs @@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, state.clientContext, client, ContentType.handshake); TlsSession sessionToResume = state.client.GetSessionToResume(); - if (sessionToResume != null) + if (sessionToResume != null && sessionToResume.IsResumable) { SessionParameters sessionParameters = sessionToResume.ExportSessionParameters(); if (sessionParameters != null) @@ -143,6 +143,8 @@ namespace Org.BouncyCastle.Crypto.Tls IDictionary sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); + // TODO Check encrypt-then-MAC extension and maybe others + securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); securityParameters.masterSecret = Arrays.Clone(state.sessionParameters.MasterSecret); @@ -430,8 +432,6 @@ namespace Org.BouncyCastle.Crypto.Tls // Integer -> byte[] state.clientExtensions = client.GetClientExtensions(); - securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions); - // Cipher Suites (and SCSV) { /* @@ -645,15 +645,6 @@ namespace Org.BouncyCastle.Crypto.Tls // Integer -> byte[] IDictionary serverExtensions = TlsProtocol.ReadExtensions(buf); - /* - * draft-ietf-tls-session-hash-01 5.2. If a server receives the "extended_master_secret" - * extension, it MUST include the "extended_master_secret" extension in its ServerHello - * message. - */ - bool serverSentExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions); - if (serverSentExtendedMasterSecret != securityParameters.extendedMasterSecret) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. However, see RFC 5746 exception below. We always include @@ -683,15 +674,6 @@ namespace Org.BouncyCastle.Crypto.Tls if (null == TlsUtilities.GetExtensionData(state.clientExtensions, extType)) throw new TlsFatalAlert(AlertDescription.unsupported_extension); - /* - * draft-ietf-tls-session-hash-01 5.2. Implementation note: if the server decides to - * proceed with resumption, the extension does not have any effect. Requiring the - * extension to be included anyway makes the extension negotiation logic easier, - * because it does not depend on whether resumption is accepted or not. - */ - if (extType == ExtensionType.extended_master_secret) - continue; - /* * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and send a server hello containing no @@ -743,6 +725,8 @@ namespace Org.BouncyCastle.Crypto.Tls securityParameters.encryptThenMac = serverSentEncryptThenMAC; + securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions); + state.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions, AlertDescription.illegal_parameter); @@ -755,6 +739,13 @@ namespace Org.BouncyCastle.Crypto.Tls ExtensionType.session_ticket, AlertDescription.illegal_parameter); } + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ + state.client.NotifySecureRenegotiation(state.secure_renegotiation); if (state.clientExtensions != null) diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs index 3335a9f36..f148eb7d7 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs @@ -538,6 +538,12 @@ namespace Org.BouncyCastle.Crypto.Tls TlsServerContextImpl context = state.serverContext; SecurityParameters securityParameters = context.SecurityParameters; + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions); context.SetClientVersion(client_version); diff --git a/crypto/src/crypto/tls/ExporterLabel.cs b/crypto/src/crypto/tls/ExporterLabel.cs index 280321e2a..5970769d7 100644 --- a/crypto/src/crypto/tls/ExporterLabel.cs +++ b/crypto/src/crypto/tls/ExporterLabel.cs @@ -30,7 +30,7 @@ namespace Org.BouncyCastle.Crypto.Tls public const string dtls_srtp = "EXTRACTOR-dtls_srtp"; /* - * draft-ietf-tls-session-hash-01 + * draft-ietf-tls-session-hash-04 */ public static readonly string extended_master_secret = "extended master secret"; } diff --git a/crypto/src/crypto/tls/ExtensionType.cs b/crypto/src/crypto/tls/ExtensionType.cs index acee380b6..b4b24f7c3 100644 --- a/crypto/src/crypto/tls/ExtensionType.cs +++ b/crypto/src/crypto/tls/ExtensionType.cs @@ -49,7 +49,7 @@ namespace Org.BouncyCastle.Crypto.Tls public const int encrypt_then_mac = 22; /* - * draft-ietf-tls-session-hash-01 + * draft-ietf-tls-session-hash-04 * * NOTE: Early code-point assignment */ diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 1bd0653a6..5b9e81b3f 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mRecordStream.Init(mTlsClientContext); TlsSession sessionToResume = tlsClient.GetSessionToResume(); - if (sessionToResume != null) + if (sessionToResume != null && sessionToResume.IsResumable) { SessionParameters sessionParameters = sessionToResume.ExportSessionParameters(); if (sessionParameters != null) @@ -623,15 +623,6 @@ namespace Org.BouncyCastle.Crypto.Tls */ this.mServerExtensions = ReadExtensions(buf); - /* - * draft-ietf-tls-session-hash-01 5.2. If a server receives the "extended_master_secret" - * extension, it MUST include the "extended_master_secret" extension in its ServerHello - * message. - */ - bool serverSentExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mServerExtensions); - if (serverSentExtendedMasterSecret != mSecurityParameters.extendedMasterSecret) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. @@ -663,15 +654,6 @@ namespace Org.BouncyCastle.Crypto.Tls if (null == TlsUtilities.GetExtensionData(this.mClientExtensions, extType)) throw new TlsFatalAlert(AlertDescription.unsupported_extension); - /* - * draft-ietf-tls-session-hash-01 5.2. Implementation note: if the server decides to - * proceed with resumption, the extension does not have any effect. Requiring the - * extension to be included anyway makes the extension negotiation logic easier, - * because it does not depend on whether resumption is accepted or not. - */ - if (extType == ExtensionType.extended_master_secret) - continue; - /* * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and Send a server hello containing no @@ -725,8 +707,6 @@ namespace Org.BouncyCastle.Crypto.Tls sessionClientExtensions = null; sessionServerExtensions = this.mSessionParameters.ReadServerExtensions(); - - this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); } this.mSecurityParameters.cipherSuite = selectedCipherSuite; @@ -746,6 +726,8 @@ namespace Org.BouncyCastle.Crypto.Tls this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC; + this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); + this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); @@ -764,6 +746,13 @@ namespace Org.BouncyCastle.Crypto.Tls AlertDescription.illegal_parameter); } + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ + if (sessionClientExtensions != null) { this.mTlsClient.ProcessServerExtensions(sessionServerExtensions); @@ -820,8 +809,6 @@ namespace Org.BouncyCastle.Crypto.Tls this.mClientExtensions = this.mTlsClient.GetClientExtensions(); - this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); - HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello); TlsUtilities.WriteVersion(client_version, message); diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index d2959cfed..fd6808382 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -501,6 +501,12 @@ namespace Org.BouncyCastle.Crypto.Tls */ this.mClientExtensions = ReadExtensions(buf); + /* + * TODO[session-hash] + * + * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes + * that do not use the extended master secret [..]. (and see 5.2, 5.3) + */ this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions); ContextAdmin.SetClientVersion(client_version); diff --git a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs index 32491c425..e3c604db7 100644 --- a/crypto/test/src/crypto/tls/test/MockDtlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockDtlsClient.cs @@ -72,8 +72,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); - // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though) - //TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); + TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); return clientExtensions; diff --git a/crypto/test/src/crypto/tls/test/MockTlsClient.cs b/crypto/test/src/crypto/tls/test/MockTlsClient.cs index 4d7c59afa..7c1198632 100644 --- a/crypto/test/src/crypto/tls/test/MockTlsClient.cs +++ b/crypto/test/src/crypto/tls/test/MockTlsClient.cs @@ -62,8 +62,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests { IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions()); TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions); - // TODO[draft-ietf-tls-session-hash-01] Enable once code-point assigned (only for compatible server though) -// TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); + TlsExtensionsUtilities.AddExtendedMasterSecretExtension(clientExtensions); TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9); TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions); return clientExtensions; -- cgit 1.4.1 From 05a4b3f0a65533aae313dc5429d2dd82243cd9b6 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 13:41:55 +0700 Subject: Add ANSSI curve FRP256v1 and refactor curve registries --- crypto/crypto.csproj | 10 ++ crypto/src/asn1/anssi/ANSSINamedCurves.cs | 123 +++++++++++++++++++++ crypto/src/asn1/anssi/ANSSIObjectIdentifiers.cs | 13 +++ crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs | 2 +- crypto/src/asn1/nist/NISTNamedCurves.cs | 52 ++++----- crypto/src/asn1/sec/SECNamedCurves.cs | 13 +-- crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs | 42 ++++--- crypto/src/asn1/x9/ECNamedCurveTable.cs | 16 ++- crypto/src/asn1/x9/X962NamedCurves.cs | 12 +- 9 files changed, 213 insertions(+), 70 deletions(-) create mode 100644 crypto/src/asn1/anssi/ANSSINamedCurves.cs create mode 100644 crypto/src/asn1/anssi/ANSSIObjectIdentifiers.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 35474aebb..42990292f 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -538,6 +538,16 @@ SubType = "Code" BuildAction = "Compile" /> + + Date: Mon, 23 Mar 2015 13:56:59 +0700 Subject: Add SquarePow method to ECFieldElement --- crypto/src/math/ec/ECFieldElement.cs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs index e589fc737..27c4ba2d0 100644 --- a/crypto/src/math/ec/ECFieldElement.cs +++ b/crypto/src/math/ec/ECFieldElement.cs @@ -55,6 +55,16 @@ namespace Org.BouncyCastle.Math.EC return Square().Add(x.Multiply(y)); } + public virtual ECFieldElement SquarePow(int pow) + { + ECFieldElement r = this; + for (int i = 0; i < pow; ++i) + { + r = r.Square(); + } + return r; + } + public virtual bool TestBitZero() { return ToBigInteger().TestBit(0); @@ -812,6 +822,11 @@ namespace Org.BouncyCastle.Math.EC return new F2mFieldElement(m, ks, aa); } + public override ECFieldElement SquarePow(int pow) + { + return pow < 1 ? this : new F2mFieldElement(m, ks, x.ModSquareN(pow, m, ks)); + } + public override ECFieldElement Invert() { return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks)); @@ -819,14 +834,7 @@ namespace Org.BouncyCastle.Math.EC public override ECFieldElement Sqrt() { - LongArray x1 = this.x; - if (x1.IsOne() || x1.IsZero()) - { - return this; - } - - LongArray x2 = x1.ModSquareN(m - 1, m, ks); - return new F2mFieldElement(m, ks, x2); + return (x.IsZero() || x.IsOne()) ? this : SquarePow(m - 1); } /** -- cgit 1.4.1 From 7bd7de5760cbdfa7ba0a0f41ff2dee5fd5bca045 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 14:51:41 +0700 Subject: Reduce memory usage of INTERLEAVE2_TABLE --- crypto/src/math/ec/LongArray.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/LongArray.cs b/crypto/src/math/ec/LongArray.cs index c4e3dacbc..84462e0ea 100644 --- a/crypto/src/math/ec/LongArray.cs +++ b/crypto/src/math/ec/LongArray.cs @@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Math.EC * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits. * In a binary field, this operation is the same as squaring an 8 bit number. */ - private static readonly int[] INTERLEAVE2_TABLE = new int[] + private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, -- cgit 1.4.1 From 73b9be78466931d24597fa107df9675c28a0b962 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 15:49:48 +0700 Subject: Improve handling of extensions for session resumption --- crypto/TestResult.xml | 1985 +++++++++++++++++++++++++++ crypto/src/crypto/tls/AbstractTlsServer.cs | 4 + crypto/src/crypto/tls/DtlsClientProtocol.cs | 215 +-- crypto/src/crypto/tls/DtlsProtocol.cs | 28 +- crypto/src/crypto/tls/DtlsServerProtocol.cs | 107 +- crypto/src/crypto/tls/TlsClientProtocol.cs | 81 +- crypto/src/crypto/tls/TlsProtocol.cs | 30 +- crypto/src/crypto/tls/TlsServerProtocol.cs | 32 +- 8 files changed, 2258 insertions(+), 224 deletions(-) create mode 100644 crypto/TestResult.xml (limited to 'crypto') diff --git a/crypto/TestResult.xml b/crypto/TestResult.xml new file mode 100644 index 000000000..047a66cb3 --- /dev/null +++ b/crypto/TestResult.xml @@ -0,0 +1,1985 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs index 7fe3fcbe5..c3e250fd8 100644 --- a/crypto/src/crypto/tls/AbstractTlsServer.cs +++ b/crypto/src/crypto/tls/AbstractTlsServer.cs @@ -140,7 +140,11 @@ namespace Org.BouncyCastle.Crypto.Tls if (clientExtensions != null) { this.mEncryptThenMacOffered = TlsExtensionsUtilities.HasEncryptThenMacExtension(clientExtensions); + this.mMaxFragmentLengthOffered = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions); + if (mMaxFragmentLengthOffered >= 0 && !MaxFragmentLength.IsValid((byte)mMaxFragmentLengthOffered)) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + this.mTruncatedHMacOffered = TlsExtensionsUtilities.HasTruncatedHMacExtension(clientExtensions); this.mSupportedSignatureAlgorithms = TlsUtilities.GetSignatureAlgorithmsExtension(clientExtensions); diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs index 76635065c..411e7cca2 100644 --- a/crypto/src/crypto/tls/DtlsClientProtocol.cs +++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs @@ -112,41 +112,12 @@ namespace Org.BouncyCastle.Crypto.Tls throw new TlsFatalAlert(AlertDescription.unexpected_message); } - if (state.maxFragmentLength >= 0) - { - int plainTextLimit = 1 << (8 + state.maxFragmentLength); - recordLayer.SetPlaintextLimit(plainTextLimit); - } - - securityParameters.cipherSuite = state.selectedCipherSuite; - securityParameters.compressionAlgorithm = (byte)state.selectedCompressionMethod; - securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, state.selectedCipherSuite); - - /* - * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has - * a verify_data_length equal to 12. This includes all existing cipher suites. - */ - securityParameters.verifyDataLength = 12; - handshake.NotifyHelloComplete(); - bool resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null - && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); + ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); - if (resumedSession) + if (state.resumedSession) { - if (securityParameters.CipherSuite != state.sessionParameters.CipherSuite - || securityParameters.CompressionAlgorithm != state.sessionParameters.CompressionAlgorithm) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - IDictionary sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); - - // TODO Check encrypt-then-MAC extension and maybe others - - securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); - securityParameters.masterSecret = Arrays.Clone(state.sessionParameters.MasterSecret); recordLayer.InitPendingEpoch(state.client.GetCipher()); @@ -366,12 +337,14 @@ namespace Org.BouncyCastle.Crypto.Tls if (state.tlsSession != null) { state.sessionParameters = new SessionParameters.Builder() - .SetCipherSuite(securityParameters.cipherSuite) - .SetCompressionAlgorithm(securityParameters.compressionAlgorithm) - .SetMasterSecret(securityParameters.masterSecret) + .SetCipherSuite(securityParameters.CipherSuite) + .SetCompressionAlgorithm(securityParameters.CompressionAlgorithm) + .SetMasterSecret(securityParameters.MasterSecret) .SetPeerCertificate(serverCertificate) - .SetPskIdentity(securityParameters.pskIdentity) - .SetSrpIdentity(securityParameters.srpIdentity) + .SetPskIdentity(securityParameters.PskIdentity) + .SetSrpIdentity(securityParameters.SrpIdentity) + // TODO Consider filtering extensions that aren't relevant to resumed sessions + .SetServerExtensions(state.serverExtensions) .Build(); state.tlsSession = TlsUtilities.ImportSession(state.tlsSession.SessionID, state.sessionParameters); @@ -599,8 +572,10 @@ namespace Org.BouncyCastle.Crypto.Tls MemoryStream buf = new MemoryStream(body, false); - ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); - ReportServerVersion(state, server_version); + { + ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); + ReportServerVersion(state, server_version); + } securityParameters.serverRandom = TlsUtilities.ReadFully(32, buf); @@ -608,24 +583,24 @@ namespace Org.BouncyCastle.Crypto.Tls if (state.selectedSessionID.Length > 32) throw new TlsFatalAlert(AlertDescription.illegal_parameter); state.client.NotifySessionID(state.selectedSessionID); + state.resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null + && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); - state.selectedCipherSuite = TlsUtilities.ReadUint16(buf); - if (!Arrays.Contains(state.offeredCipherSuites, state.selectedCipherSuite) - || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || CipherSuite.IsScsv(state.selectedCipherSuite) - || !TlsUtilities.IsValidCipherSuiteForVersion(state.selectedCipherSuite, server_version)) + int selectedCipherSuite = TlsUtilities.ReadUint16(buf); + if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) + || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL + || CipherSuite.IsScsv(selectedCipherSuite) + || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.clientContext.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } + ValidateSelectedCipherSuite(selectedCipherSuite, AlertDescription.illegal_parameter); + state.client.NotifySelectedCipherSuite(selectedCipherSuite); - ValidateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.illegal_parameter); - - state.client.NotifySelectedCipherSuite(state.selectedCipherSuite); - - state.selectedCompressionMethod = TlsUtilities.ReadUint8(buf); - if (!Arrays.Contains(state.offeredCompressionMethods, (byte)state.selectedCompressionMethod)) + byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf); + if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) throw new TlsFatalAlert(AlertDescription.illegal_parameter); - state.client.NotifySelectedCompressionMethod((byte)state.selectedCompressionMethod); + state.client.NotifySelectedCompressionMethod(selectedCompressionMethod); /* * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server @@ -643,16 +618,16 @@ namespace Org.BouncyCastle.Crypto.Tls */ // Integer -> byte[] - IDictionary serverExtensions = TlsProtocol.ReadExtensions(buf); + state.serverExtensions = TlsProtocol.ReadExtensions(buf); /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. However, see RFC 5746 exception below. We always include * the SCSV, so an Extended Server Hello is always allowed. */ - if (serverExtensions != null) + if (state.serverExtensions != null) { - foreach (int extType in serverExtensions.Keys) + foreach (int extType in state.serverExtensions.Keys) { /* * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a @@ -679,64 +654,92 @@ namespace Org.BouncyCastle.Crypto.Tls * extensions appearing in the client hello, and send a server hello containing no * extensions[.] */ - // TODO[sessions] - // if (this.mResumedSession) - // { - // // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats - // // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats - // // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats - //// throw new TlsFatalAlert(AlertDescription.illegal_parameter); - // } + if (state.resumedSession) + { + // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats + // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats + // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats + //throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } } + } + /* + * RFC 5746 3.4. Client Behavior: Initial Handshake + */ + { /* - * RFC 5746 3.4. Client Behavior: Initial Handshake + * When a ServerHello is received, the client MUST check if it includes the + * "renegotiation_info" extension: */ + byte[] renegExtData = TlsUtilities.GetExtensionData(state.serverExtensions, ExtensionType.renegotiation_info); + if (renegExtData != null) { /* - * When a ServerHello is received, the client MUST check if it includes the - * "renegotiation_info" extension: - */ - byte[] renegExtData = (byte[])serverExtensions[ExtensionType.renegotiation_info]; - if (renegExtData != null) - { - /* - * If the extension is present, set the secure_renegotiation flag to TRUE. The - * client MUST then verify that the length of the "renegotiated_connection" - * field is zero, and if it is not, MUST abort the handshake (by sending a fatal - * handshake_failure alert). - */ - state.secure_renegotiation = true; - - if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) - throw new TlsFatalAlert(AlertDescription.handshake_failure); - } + * If the extension is present, set the secure_renegotiation flag to TRUE. The + * client MUST then verify that the length of the "renegotiated_connection" + * field is zero, and if it is not, MUST abort the handshake (by sending a fatal + * handshake_failure alert). + */ + state.secure_renegotiation = true; + + if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) + throw new TlsFatalAlert(AlertDescription.handshake_failure); } + } - /* - * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client - * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) - * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the - * client. - */ - bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(serverExtensions); - if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(state.selectedCipherSuite)) + // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming + state.client.NotifySecureRenegotiation(state.secure_renegotiation); + + IDictionary sessionClientExtensions = state.clientExtensions, sessionServerExtensions = state.serverExtensions; + if (state.resumedSession) + { + if (selectedCipherSuite != state.sessionParameters.CipherSuite + || selectedCompressionMethod != state.sessionParameters.CompressionAlgorithm) + { throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } - securityParameters.encryptThenMac = serverSentEncryptThenMAC; + sessionClientExtensions = null; + sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); + } - securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions); + securityParameters.cipherSuite = selectedCipherSuite; + securityParameters.compressionAlgorithm = selectedCompressionMethod; - state.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions, - AlertDescription.illegal_parameter); + if (sessionServerExtensions != null) + { + { + /* + * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client + * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) + * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the + * client. + */ + bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); + if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + securityParameters.encryptThenMac = serverSentEncryptThenMAC; + } - securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(serverExtensions); + securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); + + securityParameters.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession, + sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); - state.allowCertificateStatus = TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions, - ExtensionType.status_request, AlertDescription.illegal_parameter); + securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(sessionServerExtensions); + + /* + * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be + * sent in a session resumption handshake. + */ + state.allowCertificateStatus = !state.resumedSession + && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request, + AlertDescription.illegal_parameter); - state.expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions, - ExtensionType.session_ticket, AlertDescription.illegal_parameter); + state.expectSessionTicket = !state.resumedSession + && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket, + AlertDescription.illegal_parameter); } /* @@ -746,12 +749,19 @@ namespace Org.BouncyCastle.Crypto.Tls * that do not use the extended master secret [..]. (and see 5.2, 5.3) */ - state.client.NotifySecureRenegotiation(state.secure_renegotiation); - - if (state.clientExtensions != null) + if (sessionClientExtensions != null) { - state.client.ProcessServerExtensions(serverExtensions); + state.client.ProcessServerExtensions(sessionServerExtensions); } + + securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, + securityParameters.CipherSuite); + + /* + * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has + * a verify_data_length equal to 12. This includes all existing cipher suites. + */ + securityParameters.verifyDataLength = 12; } protected virtual void ProcessServerKeyExchange(ClientHandshakeState state, byte[] body) @@ -813,11 +823,10 @@ namespace Org.BouncyCastle.Crypto.Tls internal int[] offeredCipherSuites = null; internal byte[] offeredCompressionMethods = null; internal IDictionary clientExtensions = null; + internal IDictionary serverExtensions = null; internal byte[] selectedSessionID = null; - internal int selectedCipherSuite = -1; - internal short selectedCompressionMethod = -1; + internal bool resumedSession = false; internal bool secure_renegotiation = false; - internal short maxFragmentLength = -1; internal bool allowCertificateStatus = false; internal bool expectSessionTicket = false; internal TlsKeyExchange keyExchange = null; diff --git a/crypto/src/crypto/tls/DtlsProtocol.cs b/crypto/src/crypto/tls/DtlsProtocol.cs index 6d62c5a90..e4ebd436c 100644 --- a/crypto/src/crypto/tls/DtlsProtocol.cs +++ b/crypto/src/crypto/tls/DtlsProtocol.cs @@ -33,12 +33,32 @@ namespace Org.BouncyCastle.Crypto.Tls } /// - protected static short EvaluateMaxFragmentLengthExtension(IDictionary clientExtensions, IDictionary serverExtensions, - byte alertDescription) + internal static void ApplyMaxFragmentLengthExtension(DtlsRecordLayer recordLayer, short maxFragmentLength) + { + if (maxFragmentLength >= 0) + { + if (!MaxFragmentLength.IsValid((byte)maxFragmentLength)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + int plainTextLimit = 1 << (8 + maxFragmentLength); + recordLayer.SetPlaintextLimit(plainTextLimit); + } + } + + /// + protected static short EvaluateMaxFragmentLengthExtension(bool resumedSession, IDictionary clientExtensions, + IDictionary serverExtensions, byte alertDescription) { short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions); - if (maxFragmentLength >= 0 && maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)) - throw new TlsFatalAlert(alertDescription); + if (maxFragmentLength >= 0) + { + if (!MaxFragmentLength.IsValid((byte)maxFragmentLength) + || (!resumedSession && maxFragmentLength != TlsExtensionsUtilities + .GetMaxFragmentLengthExtension(clientExtensions))) + { + throw new TlsFatalAlert(alertDescription); + } + } return maxFragmentLength; } diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs index f148eb7d7..9c7caf290 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs @@ -94,24 +94,9 @@ namespace Org.BouncyCastle.Crypto.Tls { byte[] serverHelloBody = GenerateServerHello(state); - - if (state.maxFragmentLength >= 0) - { - int plainTextLimit = 1 << (8 + state.maxFragmentLength); - recordLayer.SetPlaintextLimit(plainTextLimit); - } - - securityParameters.cipherSuite = state.selectedCipherSuite; - securityParameters.compressionAlgorithm = (byte)state.selectedCompressionMethod; - securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, - state.selectedCipherSuite); - /* - * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length - * has a verify_data_length equal to 12. This includes all existing cipher suites. - */ - securityParameters.verifyDataLength = 12; - + ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); + handshake.SendMessage(HandshakeType.server_hello, serverHelloBody); } @@ -302,17 +287,19 @@ namespace Org.BouncyCastle.Crypto.Tls MemoryStream buf = new MemoryStream(); - ProtocolVersion server_version = state.server.GetServerVersion(); - if (!server_version.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion)) - throw new TlsFatalAlert(AlertDescription.internal_error); + { + ProtocolVersion server_version = state.server.GetServerVersion(); + if (!server_version.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion)) + throw new TlsFatalAlert(AlertDescription.internal_error); - // TODO Read RFCs for guidance on the expected record layer version number - // recordStream.setReadVersion(server_version); - // recordStream.setWriteVersion(server_version); - // recordStream.setRestrictReadVersion(true); - state.serverContext.SetServerVersion(server_version); + // TODO Read RFCs for guidance on the expected record layer version number + // recordStream.setReadVersion(server_version); + // recordStream.setWriteVersion(server_version); + // recordStream.setRestrictReadVersion(true); + state.serverContext.SetServerVersion(server_version); - TlsUtilities.WriteVersion(state.serverContext.ServerVersion, buf); + TlsUtilities.WriteVersion(state.serverContext.ServerVersion, buf); + } buf.Write(securityParameters.ServerRandom, 0, securityParameters.ServerRandom.Length); @@ -322,23 +309,24 @@ namespace Org.BouncyCastle.Crypto.Tls */ TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, buf); - state.selectedCipherSuite = state.server.GetSelectedCipherSuite(); - if (!Arrays.Contains(state.offeredCipherSuites, state.selectedCipherSuite) - || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || CipherSuite.IsScsv(state.selectedCipherSuite) - || !TlsUtilities.IsValidCipherSuiteForVersion(state.selectedCipherSuite, server_version)) + int selectedCipherSuite = state.server.GetSelectedCipherSuite(); + if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) + || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL + || CipherSuite.IsScsv(selectedCipherSuite) + || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.serverContext.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.internal_error); } + ValidateSelectedCipherSuite(selectedCipherSuite, AlertDescription.internal_error); + securityParameters.cipherSuite = selectedCipherSuite; - ValidateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.internal_error); - - state.selectedCompressionMethod = state.server.GetSelectedCompressionMethod(); - if (!Arrays.Contains(state.offeredCompressionMethods, (byte)state.selectedCompressionMethod)) + byte selectedCompressionMethod = state.server.GetSelectedCompressionMethod(); + if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) throw new TlsFatalAlert(AlertDescription.internal_error); + securityParameters.compressionAlgorithm = selectedCompressionMethod; - TlsUtilities.WriteUint16(state.selectedCipherSuite, buf); - TlsUtilities.WriteUint8((byte)state.selectedCompressionMethod, buf); + TlsUtilities.WriteUint16(selectedCipherSuite, buf); + TlsUtilities.WriteUint8(selectedCompressionMethod, buf); state.serverExtensions = state.server.GetServerExtensions(); @@ -375,24 +363,45 @@ namespace Org.BouncyCastle.Crypto.Tls TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.serverExtensions); } + /* + * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore + * extensions appearing in the client hello, and send a server hello containing no + * extensions. + */ + if (state.serverExtensions != null) { securityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(state.serverExtensions); - state.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.clientExtensions, state.serverExtensions, - AlertDescription.internal_error); + securityParameters.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession, + state.clientExtensions, state.serverExtensions, AlertDescription.internal_error); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(state.serverExtensions); - state.allowCertificateStatus = TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, - ExtensionType.status_request, AlertDescription.internal_error); + /* + * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in + * a session resumption handshake. + */ + state.allowCertificateStatus = !state.resumedSession + && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, ExtensionType.status_request, + AlertDescription.internal_error); - state.expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, - ExtensionType.session_ticket, AlertDescription.internal_error); + state.expectSessionTicket = !state.resumedSession + && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, ExtensionType.session_ticket, + AlertDescription.internal_error); TlsProtocol.WriteExtensions(buf, state.serverExtensions); } + securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, + securityParameters.CipherSuite); + + /* + * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length + * has a verify_data_length equal to 12. This includes all existing cipher suites. + */ + securityParameters.verifyDataLength = 12; + return buf.ToArray(); } @@ -628,16 +637,14 @@ namespace Org.BouncyCastle.Crypto.Tls { internal TlsServer server = null; internal TlsServerContextImpl serverContext = null; - internal int[] offeredCipherSuites; - internal byte[] offeredCompressionMethods; - internal IDictionary clientExtensions; - internal int selectedCipherSuite = -1; - internal short selectedCompressionMethod = -1; + internal int[] offeredCipherSuites = null; + internal byte[] offeredCompressionMethods = null; + internal IDictionary clientExtensions = null; + internal IDictionary serverExtensions = null; + internal bool resumedSession = false; internal bool secure_renegotiation = false; - internal short maxFragmentLength = -1; internal bool allowCertificateStatus = false; internal bool expectSessionTicket = false; - internal IDictionary serverExtensions = null; internal TlsKeyExchange keyExchange = null; internal TlsCredentials serverCredentials = null; internal CertificateRequest certificateRequest = null; diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs index 5b9e81b3f..7b8439acc 100644 --- a/crypto/src/crypto/tls/TlsClientProtocol.cs +++ b/crypto/src/crypto/tls/TlsClientProtocol.cs @@ -224,24 +224,10 @@ namespace Org.BouncyCastle.Crypto.Tls ReceiveServerHelloMessage(buf); this.mConnectionState = CS_SERVER_HELLO; - if (this.mSecurityParameters.maxFragmentLength >= 0) - { - int plainTextLimit = 1 << (8 + this.mSecurityParameters.maxFragmentLength); - mRecordStream.SetPlaintextLimit(plainTextLimit); - } - - this.mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, - this.mSecurityParameters.CipherSuite); - - /* - * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify - * verify_data_length has a verify_data_length equal to 12. This includes all - * existing cipher suites. - */ - this.mSecurityParameters.verifyDataLength = 12; - this.mRecordStream.NotifyHelloComplete(); + ApplyMaxFragmentLengthExtension(); + if (this.mResumedSession) { this.mSecurityParameters.masterSecret = Arrays.Clone(this.mSessionParameters.MasterSecret); @@ -558,21 +544,23 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ReceiveServerHelloMessage(MemoryStream buf) { - ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); - if (server_version.IsDtls) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + { + ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); + if (server_version.IsDtls) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); - // Check that this matches what the server is Sending in the record layer - if (!server_version.Equals(this.mRecordStream.ReadVersion)) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + // Check that this matches what the server is Sending in the record layer + if (!server_version.Equals(this.mRecordStream.ReadVersion)) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); - ProtocolVersion client_version = Context.ClientVersion; - if (!server_version.IsEqualOrEarlierVersionOf(client_version)) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + ProtocolVersion client_version = Context.ClientVersion; + if (!server_version.IsEqualOrEarlierVersionOf(client_version)) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); - this.mRecordStream.SetWriteVersion(server_version); - ContextAdmin.SetServerVersion(server_version); - this.mTlsClient.NotifyServerVersion(server_version); + this.mRecordStream.SetWriteVersion(server_version); + ContextAdmin.SetServerVersion(server_version); + this.mTlsClient.NotifyServerVersion(server_version); + } /* * Read the server random @@ -582,9 +570,7 @@ namespace Org.BouncyCastle.Crypto.Tls this.mSelectedSessionID = TlsUtilities.ReadOpaque8(buf); if (this.mSelectedSessionID.Length > 32) throw new TlsFatalAlert(AlertDescription.illegal_parameter); - this.mTlsClient.NotifySessionID(this.mSelectedSessionID); - this.mResumedSession = this.mSelectedSessionID.Length > 0 && this.mTlsSession != null && Arrays.AreEqual(this.mSelectedSessionID, this.mTlsSession.SessionID); @@ -596,11 +582,10 @@ namespace Org.BouncyCastle.Crypto.Tls if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) - || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version)) + || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } - this.mTlsClient.NotifySelectedCipherSuite(selectedCipherSuite); /* @@ -610,7 +595,6 @@ namespace Org.BouncyCastle.Crypto.Tls byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf); if (!Arrays.Contains(this.mOfferedCompressionMethods, selectedCompressionMethod)) throw new TlsFatalAlert(AlertDescription.illegal_parameter); - this.mTlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod); /* @@ -714,17 +698,19 @@ namespace Org.BouncyCastle.Crypto.Tls if (sessionServerExtensions != null) { - /* - * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client - * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) - * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the - * client. - */ - bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); - if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(selectedCipherSuite)) - throw new TlsFatalAlert(AlertDescription.illegal_parameter); + { + /* + * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client + * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) + * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the + * client. + */ + bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); + if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(selectedCipherSuite)) + throw new TlsFatalAlert(AlertDescription.illegal_parameter); - this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC; + this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC; + } this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); @@ -757,6 +743,15 @@ namespace Org.BouncyCastle.Crypto.Tls { this.mTlsClient.ProcessServerExtensions(sessionServerExtensions); } + + this.mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, this.mSecurityParameters.CipherSuite); + + /* + * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify + * verify_data_length has a verify_data_length equal to 12. This includes all + * existing cipher suites. + */ + this.mSecurityParameters.verifyDataLength = 12; } protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify) diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs index 4ea72cd57..8eb7beb3f 100644 --- a/crypto/src/crypto/tls/TlsProtocol.cs +++ b/crypto/src/crypto/tls/TlsProtocol.cs @@ -99,6 +99,18 @@ namespace Org.BouncyCastle.Crypto.Tls { } + protected virtual void ApplyMaxFragmentLengthExtension() + { + if (mSecurityParameters.maxFragmentLength >= 0) + { + if (!MaxFragmentLength.IsValid((byte)mSecurityParameters.maxFragmentLength)) + throw new TlsFatalAlert(AlertDescription.internal_error); + + int plainTextLimit = 1 << (8 + mSecurityParameters.maxFragmentLength); + mRecordStream.SetPlaintextLimit(plainTextLimit); + } + } + protected virtual void CheckReceivedChangeCipherSpec(bool expected) { if (expected != mReceivedChangeCipherSpec) @@ -164,12 +176,12 @@ namespace Org.BouncyCastle.Crypto.Tls if (this.mSessionParameters == null) { this.mSessionParameters = new SessionParameters.Builder() - .SetCipherSuite(this.mSecurityParameters.cipherSuite) - .SetCompressionAlgorithm(this.mSecurityParameters.compressionAlgorithm) - .SetMasterSecret(this.mSecurityParameters.masterSecret) + .SetCipherSuite(this.mSecurityParameters.CipherSuite) + .SetCompressionAlgorithm(this.mSecurityParameters.CompressionAlgorithm) + .SetMasterSecret(this.mSecurityParameters.MasterSecret) .SetPeerCertificate(this.mPeerCertificate) - .SetPskIdentity(this.mSecurityParameters.pskIdentity) - .SetSrpIdentity(this.mSecurityParameters.srpIdentity) + .SetPskIdentity(this.mSecurityParameters.PskIdentity) + .SetSrpIdentity(this.mSecurityParameters.SrpIdentity) // TODO Consider filtering extensions that aren't relevant to resumed sessions .SetServerExtensions(this.mServerExtensions) .Build(); @@ -761,10 +773,14 @@ namespace Org.BouncyCastle.Crypto.Tls byte alertDescription) { short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions); - if (maxFragmentLength >= 0 && !this.mResumedSession) + if (maxFragmentLength >= 0) { - if (maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions)) + if (!MaxFragmentLength.IsValid((byte)maxFragmentLength) + || (!this.mResumedSession && maxFragmentLength != TlsExtensionsUtilities + .GetMaxFragmentLengthExtension(clientExtensions))) + { throw new TlsFatalAlert(alertDescription); + } } return maxFragmentLength; } diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs index fd6808382..b73cb5a30 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs @@ -106,6 +106,8 @@ namespace Org.BouncyCastle.Crypto.Tls SendServerHelloMessage(); this.mConnectionState = CS_SERVER_HELLO; + mRecordStream.NotifyHelloComplete(); + IList serverSupplementalData = mTlsServer.GetServerSupplementalData(); if (serverSupplementalData != null) { @@ -618,16 +620,18 @@ namespace Org.BouncyCastle.Crypto.Tls { HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello); - ProtocolVersion server_version = mTlsServer.GetServerVersion(); - if (!server_version.IsEqualOrEarlierVersionOf(Context.ClientVersion)) - throw new TlsFatalAlert(AlertDescription.internal_error); + { + ProtocolVersion server_version = mTlsServer.GetServerVersion(); + if (!server_version.IsEqualOrEarlierVersionOf(Context.ClientVersion)) + throw new TlsFatalAlert(AlertDescription.internal_error); - mRecordStream.ReadVersion = server_version; - mRecordStream.SetWriteVersion(server_version); - mRecordStream.SetRestrictReadVersion(true); - ContextAdmin.SetServerVersion(server_version); + mRecordStream.ReadVersion = server_version; + mRecordStream.SetWriteVersion(server_version); + mRecordStream.SetRestrictReadVersion(true); + ContextAdmin.SetServerVersion(server_version); - TlsUtilities.WriteVersion(server_version, message); + TlsUtilities.WriteVersion(server_version, message); + } message.Write(this.mSecurityParameters.serverRandom); @@ -641,7 +645,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) - || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version)) + || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.internal_error); } @@ -722,12 +726,6 @@ namespace Org.BouncyCastle.Crypto.Tls WriteExtensions(message, this.mServerExtensions); } - if (mSecurityParameters.maxFragmentLength >= 0) - { - int plainTextLimit = 1 << (8 + mSecurityParameters.maxFragmentLength); - mRecordStream.SetPlaintextLimit(plainTextLimit); - } - mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite); /* @@ -736,9 +734,9 @@ namespace Org.BouncyCastle.Crypto.Tls */ mSecurityParameters.verifyDataLength = 12; - message.WriteToRecordStream(this); + ApplyMaxFragmentLengthExtension(); - this.mRecordStream.NotifyHelloComplete(); + message.WriteToRecordStream(this); } protected virtual void SendServerHelloDoneMessage() -- cgit 1.4.1 From 94bd14f0d17e617ca1a8b9c4b188416758820c78 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 19:05:36 +0700 Subject: Math.Raw support for custom binary curves - Also migrate the 'raw' stuff into Math.Raw following Java build --- crypto/crypto.csproj | 100 +- crypto/src/math/ec/ECFieldElement.cs | 1 + crypto/src/math/ec/Mod.cs | 184 --- crypto/src/math/ec/Nat.cs | 1013 -------------- crypto/src/math/ec/custom/djb/Curve25519.cs | 2 +- crypto/src/math/ec/custom/djb/Curve25519Field.cs | 2 +- .../math/ec/custom/djb/Curve25519FieldElement.cs | 2 +- crypto/src/math/ec/custom/djb/Curve25519Point.cs | 2 +- crypto/src/math/ec/custom/sec/Nat192.cs | 962 -------------- crypto/src/math/ec/custom/sec/Nat224.cs | 1176 ----------------- crypto/src/math/ec/custom/sec/Nat256.cs | 1300 ------------------ crypto/src/math/ec/custom/sec/Nat384.cs | 46 - crypto/src/math/ec/custom/sec/Nat512.cs | 46 - crypto/src/math/ec/custom/sec/SecP192K1Field.cs | 2 + .../math/ec/custom/sec/SecP192K1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP192K1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP192R1Field.cs | 2 + .../math/ec/custom/sec/SecP192R1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP192R1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP224K1Field.cs | 2 + .../math/ec/custom/sec/SecP224K1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP224K1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP224R1Field.cs | 2 + .../math/ec/custom/sec/SecP224R1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP224R1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP256K1Field.cs | 2 + .../math/ec/custom/sec/SecP256K1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP256K1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP256R1Field.cs | 2 + .../math/ec/custom/sec/SecP256R1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP256R1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP384R1Field.cs | 2 + .../math/ec/custom/sec/SecP384R1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP384R1Point.cs | 2 + crypto/src/math/ec/custom/sec/SecP521R1Field.cs | 2 + .../math/ec/custom/sec/SecP521R1FieldElement.cs | 1 + crypto/src/math/ec/custom/sec/SecP521R1Point.cs | 2 + crypto/src/math/raw/Interleave.cs | 70 + crypto/src/math/raw/Mod.cs | 184 +++ crypto/src/math/raw/Nat.cs | 1053 +++++++++++++++ crypto/src/math/raw/Nat128.cs | 856 ++++++++++++ crypto/src/math/raw/Nat160.cs | 874 ++++++++++++ crypto/src/math/raw/Nat192.cs | 1048 +++++++++++++++ crypto/src/math/raw/Nat224.cs | 1176 +++++++++++++++++ crypto/src/math/raw/Nat256.cs | 1387 ++++++++++++++++++++ crypto/src/math/raw/Nat320.cs | 98 ++ crypto/src/math/raw/Nat384.cs | 46 + crypto/src/math/raw/Nat448.cs | 100 ++ crypto/src/math/raw/Nat512.cs | 46 + crypto/src/math/raw/Nat576.cs | 102 ++ 50 files changed, 7150 insertions(+), 4766 deletions(-) delete mode 100644 crypto/src/math/ec/Mod.cs delete mode 100644 crypto/src/math/ec/Nat.cs delete mode 100644 crypto/src/math/ec/custom/sec/Nat192.cs delete mode 100644 crypto/src/math/ec/custom/sec/Nat224.cs delete mode 100644 crypto/src/math/ec/custom/sec/Nat256.cs delete mode 100644 crypto/src/math/ec/custom/sec/Nat384.cs delete mode 100644 crypto/src/math/ec/custom/sec/Nat512.cs create mode 100644 crypto/src/math/raw/Interleave.cs create mode 100644 crypto/src/math/raw/Mod.cs create mode 100644 crypto/src/math/raw/Nat.cs create mode 100644 crypto/src/math/raw/Nat128.cs create mode 100644 crypto/src/math/raw/Nat160.cs create mode 100644 crypto/src/math/raw/Nat192.cs create mode 100644 crypto/src/math/raw/Nat224.cs create mode 100644 crypto/src/math/raw/Nat256.cs create mode 100644 crypto/src/math/raw/Nat320.cs create mode 100644 crypto/src/math/raw/Nat384.cs create mode 100644 crypto/src/math/raw/Nat448.cs create mode 100644 crypto/src/math/raw/Nat512.cs create mode 100644 crypto/src/math/raw/Nat576.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 42990292f..50daeec48 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5128,16 +5128,6 @@ SubType = "Code" BuildAction = "Compile" /> - - - - - - - + + + + + + + + + + + + + > 1; - m |= m >> 2; - m |= m >> 4; - m |= m >> 8; - m |= m >> 16; - - do - { - byte[] bytes = new byte[len << 2]; - rand.NextBytes(bytes); - Pack.BE_To_UInt32(bytes, 0, s); - s[len - 1] &= m; - } - while (Nat.Gte(len, s, p)); - - return s; - } - - public static void Add(uint[] p, uint[] x, uint[] y, uint[] z) - { - int len = p.Length; - uint c = Nat.Add(len, x, y, z); - if (c != 0) - { - Nat.SubFrom(len, p, z); - } - } - - public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z) - { - int len = p.Length; - int c = Nat.Sub(len, x, y, z); - if (c != 0) - { - Nat.AddTo(len, p, z); - } - } - - private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z) - { - if (ac < 0) - { - Nat.Add(p.Length, a, p, z); - } - else - { - Array.Copy(a, 0, z, 0, p.Length); - } - } - - private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc) - { - int len = p.Length; - int count = 0; - while (u[0] == 0) - { - Nat.ShiftDownWord(uLen, u, 0); - count += 32; - } - - { - int zeroes = GetTrailingZeroes(u[0]); - if (zeroes > 0) - { - Nat.ShiftDownBits(uLen, u, zeroes, 0); - count += zeroes; - } - } - - for (int i = 0; i < count; ++i) - { - if ((x[0] & 1) != 0) - { - if (xc < 0) - { - xc += (int)Nat.AddTo(len, p, x); - } - else - { - xc += Nat.SubFrom(len, p, x); - } - } - - Debug.Assert(xc == 0 || xc == -1); - Nat.ShiftDownBit(len, x, (uint)xc); - } - } - - private static int GetTrailingZeroes(uint x) - { - Debug.Assert(x != 0); - int count = 0; - while ((x & 1) == 0) - { - x >>= 1; - ++count; - } - return count; - } - } -} diff --git a/crypto/src/math/ec/Nat.cs b/crypto/src/math/ec/Nat.cs deleted file mode 100644 index 17b632f26..000000000 --- a/crypto/src/math/ec/Nat.cs +++ /dev/null @@ -1,1013 +0,0 @@ -using System; -using System.Diagnostics; - -using Org.BouncyCastle.Crypto.Utilities; - -namespace Org.BouncyCastle.Math.EC -{ - internal abstract class Nat - { - private const ulong M = 0xFFFFFFFFUL; - - public static uint Add(int len, uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint Add33At(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zPos + 0] + x; - z[zPos + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 1] + 1; - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 2); - } - - public static uint Add33At(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zOff + zPos] + x; - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + zPos + 1] + 1; - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); - } - - public static uint Add33To(int len, uint x, uint[] z) - { - ulong c = (ulong)z[0] + x; - z[0] = (uint)c; - c >>= 32; - c += (ulong)z[1] + 1; - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 2); - } - - public static uint Add33To(int len, uint x, uint[] z, int zOff) - { - ulong c = (ulong)z[zOff + 0] + x; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + 1] + 1; - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 2); - } - - public static uint AddBothTo(int len, uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + y[i] + z[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddBothTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[xOff + i] + y[yOff + i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddDWordAt(int len, ulong x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zPos + 0] + (x & M); - z[zPos + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 1] + (x >> 32); - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 2); - } - - public static uint AddDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - ulong c = (ulong)z[zOff + zPos] + (x & M); - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + zPos + 1] + (x >> 32); - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); - } - - public static uint AddDWordTo(int len, ulong x, uint[] z) - { - ulong c = (ulong)z[0] + (x & M); - z[0] = (uint)c; - c >>= 32; - c += (ulong)z[1] + (x >> 32); - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 2); - } - - public static uint AddDWordTo(int len, ulong x, uint[] z, int zOff) - { - ulong c = (ulong)z[zOff + 0] + (x & M); - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)z[zOff + 1] + (x >> 32); - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 2); - } - - public static uint AddTo(int len, uint[] x, uint[] z) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[i] + z[i]; - z[i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff) - { - ulong c = 0; - for (int i = 0; i < len; ++i) - { - c += (ulong)x[xOff + i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (uint)c; - } - - public static uint AddWordAt(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - ulong c = (ulong)x + z[zPos]; - z[zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 1); - } - - public static uint AddWordAt(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - ulong c = (ulong)x + z[zOff + zPos]; - z[zOff + zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 1); - } - - public static uint AddWordTo(int len, uint x, uint[] z) - { - ulong c = (ulong)x + z[0]; - z[0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, 1); - } - - public static uint AddWordTo(int len, uint x, uint[] z, int zOff) - { - ulong c = (ulong)x + z[zOff]; - z[zOff] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zOff, 1); - } - - public static void Copy(int len, uint[] x, uint[] z) - { - Array.Copy(x, 0, z, 0, len); - } - - public static uint[] Copy(int len, uint[] x) - { - uint[] z = new uint[len]; - Array.Copy(x, 0, z, 0, len); - return z; - } - - public static uint[] Create(int len) - { - return new uint[len]; - } - - public static int Dec(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - if (--z[i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static int Dec(int len, uint[] x, uint[] z) - { - int i = 0; - while (i < len) - { - uint c = x[i] - 1; - z[i] = c; - ++i; - if (c != uint.MaxValue) - { - while (i < len) - { - z[i] = x[i]; - ++i; - } - return 0; - } - } - return -1; - } - - public static int DecAt(int len, uint[] z, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (--z[i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static int DecAt(int len, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (--z[zOff + i] != uint.MaxValue) - { - return 0; - } - } - return -1; - } - - public static bool Eq(int len, uint[] x, uint[] y) - { - for (int i = len - 1; i >= 0; --i) - { - if (x[i] != y[i]) - { - return false; - } - } - return true; - } - - public static uint[] FromBigInteger(int bits, BigInteger x) - { - if (x.SignValue < 0 || x.BitLength > bits) - throw new ArgumentException(); - - int len = (bits + 31) >> 5; - uint[] z = Create(len); - int i = 0; - while (x.SignValue != 0) - { - z[i++] = (uint)x.IntValue; - x = x.ShiftRight(32); - } - return z; - } - - public static uint GetBit(uint[] x, int bit) - { - if (bit == 0) - { - return x[0] & 1; - } - int w = bit >> 5; - if (w < 0 || w >= x.Length) - { - return 0; - } - int b = bit & 31; - return (x[w] >> b) & 1; - } - - public static bool Gte(int len, uint[] x, uint[] y) - { - for (int i = len - 1; i >= 0; --i) - { - uint x_i = x[i], y_i = y[i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static uint Inc(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - if (++z[i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static uint Inc(int len, uint[] x, uint[] z) - { - int i = 0; - while (i < len) - { - uint c = x[i] + 1; - z[i] = c; - ++i; - if (c != 0) - { - while (i < len) - { - z[i] = x[i]; - ++i; - } - return 0; - } - } - return 1; - } - - public static uint IncAt(int len, uint[] z, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (++z[i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static uint IncAt(int len, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= len); - for (int i = zPos; i < len; ++i) - { - if (++z[zOff + i] != uint.MinValue) - { - return 0; - } - } - return 1; - } - - public static bool IsOne(int len, uint[] x) - { - if (x[0] != 1) - { - return false; - } - for (int i = 1; i < len; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static bool IsZero(int len, uint[] x) - { - if (x[0] != 0) - { - return false; - } - for (int i = 1; i < len; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static void Mul(int len, uint[] x, uint[] y, uint[] zz) - { - zz[len] = (uint)MulWord(len, x[0], y, zz); - - for (int i = 1; i < len; ++i) - { - zz[i + len] = (uint)MulWordAddTo(len, x[i], y, 0, zz, i); - } - } - - public static void Mul(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - zz[zzOff + len] = (uint)MulWord(len, x[xOff], y, yOff, zz, zzOff); - - for (int i = 1; i < len; ++i) - { - zz[zzOff + i + len] = (uint)MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i); - } - } - - public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff) - { - ulong c = 0, aVal = (ulong)a, bVal = (ulong)b; - int i = 0; - do - { - c += aVal * x[i] + bVal * y[i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWord(int len, uint x, uint[] y, uint[] z) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[i]; - z[i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWord(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWordAddTo(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = (ulong)x; - int i = 0; - do - { - c += xVal * y[yOff + i] + z[zOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < len); - return (uint)c; - } - - public static uint MulWordDwordAddAt(int len, uint x, ulong y, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 3)); - ulong c = 0, xVal = (ulong)x; - c += xVal * (uint)y + z[zPos + 0]; - z[zPos + 0] = (uint)c; - c >>= 32; - c += xVal * (y >> 32) + z[zPos + 1]; - z[zPos + 1] = (uint)c; - c >>= 32; - c += (ulong)z[zPos + 2]; - z[zPos + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : IncAt(len, z, zPos + 3); - } - - public static uint ShiftDownBit(int len, uint[] z, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] z, int zOff, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[zOff + i]; - z[zOff + i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] x, uint c, uint[] z) - { - int i = len; - while (--i >= 0) - { - uint next = x[i]; - z[i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) - { - int i = len; - while (--i >= 0) - { - uint next = x[xOff + i]; - z[zOff + i] = (next >> 1) | (c << 31); - c = next; - } - return c << 31; - } - - public static uint ShiftDownBits(int len, uint[] z, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] z, int zOff, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = z[zOff + i]; - z[zOff + i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] x, int bits, uint c, uint[] z) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = x[i]; - z[i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) - { - Debug.Assert(bits > 0 && bits < 32); - int i = len; - while (--i >= 0) - { - uint next = x[xOff + i]; - z[zOff + i] = (next >> bits) | (c << -bits); - c = next; - } - return c << -bits; - } - - public static uint ShiftDownWord(int len, uint[] z, uint c) - { - int i = len; - while (--i >= 0) - { - uint next = z[i]; - z[i] = c; - c = next; - } - return c; - } - - public static uint ShiftUpBit(int len, uint[] z, uint c) - { - for (int i = 0; i < len; ++i) - { - uint next = z[i]; - z[i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] z, int zOff, uint c) - { - for (int i = 0; i < len; ++i) - { - uint next = z[zOff + i]; - z[zOff + i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] x, uint c, uint[] z) - { - for (int i = 0; i < len; ++i) - { - uint next = x[i]; - z[i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) - { - for (int i = 0; i < len; ++i) - { - uint next = x[xOff + i]; - z[zOff + i] = (next << 1) | (c >> 31); - c = next; - } - return c >> 31; - } - - public static uint ShiftUpBits(int len, uint[] z, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = z[i]; - z[i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] z, int zOff, int bits, uint c) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = z[zOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] x, int bits, uint c, uint[] z) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = x[i]; - z[i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static uint ShiftUpBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) - { - Debug.Assert(bits > 0 && bits < 32); - for (int i = 0; i < len; ++i) - { - uint next = x[xOff + i]; - z[zOff + i] = (next << bits) | (c >> -bits); - c = next; - } - return c >> -bits; - } - - public static void Square(int len, uint[] x, uint[] zz) - { - int extLen = len << 1; - uint c = 0; - int j = len, k = extLen; - do - { - ulong xVal = (ulong)x[--j]; - ulong p = xVal * xVal; - zz[--k] = (c << 31) | (uint)(p >> 33); - zz[--k] = (uint)(p >> 1); - c = (uint)p; - } - while (j > 0); - - for (int i = 1; i < len; ++i) - { - c = SquareWordAdd(x, i, zz); - AddWordAt(extLen, c, zz, i << 1); - } - - ShiftUpBit(extLen, zz, x[0] << 31); - } - - public static void Square(int len, uint[] x, int xOff, uint[] zz, int zzOff) - { - int extLen = len << 1; - uint c = 0; - int j = len, k = extLen; - do - { - ulong xVal = (ulong)x[xOff + --j]; - ulong p = xVal * xVal; - zz[zzOff + --k] = (c << 31) | (uint)(p >> 33); - zz[zzOff + --k] = (uint)(p >> 1); - c = (uint)p; - } - while (j > 0); - - for (int i = 1; i < len; ++i) - { - c = SquareWordAdd(x, xOff, i, zz, zzOff); - AddWordAt(extLen, c, zz, zzOff, i << 1); - } - - ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31); - } - - public static uint SquareWordAdd(uint[] x, int xPos, uint[] z) - { - ulong c = 0, xVal = (ulong)x[xPos]; - int i = 0; - do - { - c += xVal * x[i] + z[xPos + i]; - z[xPos + i] = (uint)c; - c >>= 32; - } - while (++i < xPos); - return (uint)c; - } - - public static uint SquareWordAdd(uint[] x, int xOff, int xPos, uint[] z, int zOff) - { - ulong c = 0, xVal = (ulong)x[xOff + xPos]; - int i = 0; - do - { - c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M); - z[xPos + zOff] = (uint)c; - c >>= 32; - ++zOff; - } - while (++i < xPos); - return (uint)c; - } - - public static int Sub(int len, uint[] x, uint[] y, uint[] z) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)x[i] - y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int Sub(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)x[xOff + i] - y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - public static int Sub33At(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zPos + 0] - x; - z[zPos + 0] = (uint)c; - c >>= 32; - c += (long)z[zPos + 1] - 1; - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 2); - } - - public static int Sub33At(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zOff + zPos] - x; - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (long)z[zOff + zPos + 1] - 1; - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); - } - - public static int Sub33From(int len, uint x, uint[] z) - { - long c = (long)z[0] - x; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - 1; - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 2); - } - - public static int Sub33From(int len, uint x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - x; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - 1; - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 2); - } - - public static int SubBothFrom(int len, uint[] x, uint[] y, uint[] z) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[i] - x[i] - y[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubBothFrom(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[zOff + i] - x[xOff + i] - y[yOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubDWordAt(int len, ulong x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zPos + 0] - (long)(x & M); - z[zPos + 0] = (uint)c; - c >>= 32; - c += (long)z[zPos + 1] - (long)(x >> 32); - z[zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 2); - } - - public static int SubDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 2)); - long c = (long)z[zOff + zPos] - (long)(x & M); - z[zOff + zPos] = (uint)c; - c >>= 32; - c += (long)z[zOff + zPos + 1] - (long)(x >> 32); - z[zOff + zPos + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); - } - - public static int SubDWordFrom(int len, ulong x, uint[] z) - { - long c = (long)z[0] - (long)(x & M); - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - (long)(x >> 32); - z[1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 2); - } - - public static int SubDWordFrom(int len, ulong x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - (long)(x & M); - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - (long)(x >> 32); - z[zOff + 1] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 2); - } - - public static int SubFrom(int len, uint[] x, uint[] z) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[i] - x[i]; - z[i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubFrom(int len, uint[] x, int xOff, uint[] z, int zOff) - { - long c = 0; - for (int i = 0; i < len; ++i) - { - c += (long)z[zOff + i] - x[xOff + i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - return (int)c; - } - - public static int SubWordAt(int len, uint x, uint[] z, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - long c = (long)z[zPos] - x; - z[zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zPos + 1); - } - - public static int SubWordAt(int len, uint x, uint[] z, int zOff, int zPos) - { - Debug.Assert(zPos <= (len - 1)); - long c = (long)z[zOff + zPos] - x; - z[zOff + zPos] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 1); - } - - public static int SubWordFrom(int len, uint x, uint[] z) - { - long c = (long)z[0] - x; - z[0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, 1); - } - - public static int SubWordFrom(int len, uint x, uint[] z, int zOff) - { - long c = (long)z[zOff + 0] - x; - z[zOff + 0] = (uint)c; - c >>= 32; - return c == 0 ? 0 : DecAt(len, z, zOff, 1); - } - - public static BigInteger ToBigInteger(int len, uint[] x) - { - byte[] bs = new byte[len << 2]; - for (int i = 0; i < len; ++i) - { - uint x_i = x[i]; - if (x_i != 0) - { - Pack.UInt32_To_BE(x_i, bs, (len - 1 - i) << 2); - } - } - return new BigInteger(1, bs); - } - - public static void Zero(int len, uint[] z) - { - for (int i = 0; i < len; ++i) - { - z[i] = 0; - } - } - } -} diff --git a/crypto/src/math/ec/custom/djb/Curve25519.cs b/crypto/src/math/ec/custom/djb/Curve25519.cs index 712b68f29..6ed7c0648 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519.cs @@ -1,6 +1,6 @@ using System; -using Org.BouncyCastle.Math.EC.Custom.Sec; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities.Encoders; namespace Org.BouncyCastle.Math.EC.Custom.Djb diff --git a/crypto/src/math/ec/custom/djb/Curve25519Field.cs b/crypto/src/math/ec/custom/djb/Curve25519Field.cs index 809e51b80..837821e1a 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519Field.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519Field.cs @@ -1,7 +1,7 @@ using System; using System.Diagnostics; -using Org.BouncyCastle.Math.EC.Custom.Sec; +using Org.BouncyCastle.Math.Raw; namespace Org.BouncyCastle.Math.EC.Custom.Djb { diff --git a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs index 8d5a80326..732e9e468 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519FieldElement.cs @@ -1,6 +1,6 @@ using System; -using Org.BouncyCastle.Math.EC.Custom.Sec; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Djb diff --git a/crypto/src/math/ec/custom/djb/Curve25519Point.cs b/crypto/src/math/ec/custom/djb/Curve25519Point.cs index bfec1d11d..eb8fc12f2 100644 --- a/crypto/src/math/ec/custom/djb/Curve25519Point.cs +++ b/crypto/src/math/ec/custom/djb/Curve25519Point.cs @@ -1,6 +1,6 @@ using System; -using Org.BouncyCastle.Math.EC.Custom.Sec; +using Org.BouncyCastle.Math.Raw; namespace Org.BouncyCastle.Math.EC.Custom.Djb { diff --git a/crypto/src/math/ec/custom/sec/Nat192.cs b/crypto/src/math/ec/custom/sec/Nat192.cs deleted file mode 100644 index 94d7ed17c..000000000 --- a/crypto/src/math/ec/custom/sec/Nat192.cs +++ /dev/null @@ -1,962 +0,0 @@ -using System; -using System.Diagnostics; - -using Org.BouncyCastle.Crypto.Utilities; - -namespace Org.BouncyCastle.Math.EC.Custom.Sec -{ - internal abstract class Nat192 - { - private const ulong M = 0xFFFFFFFFUL; - - public static uint Add(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5]; - z[5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddBothTo(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) - { - ulong c = cIn; - c += (ulong)x[xOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) - { - ulong c = 0; - c += (ulong)u[uOff + 0] + v[vOff + 0]; - u[uOff + 0] = (uint)c; - v[vOff + 0] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 1] + v[vOff + 1]; - u[uOff + 1] = (uint)c; - v[vOff + 1] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 2] + v[vOff + 2]; - u[uOff + 2] = (uint)c; - v[vOff + 2] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 3] + v[vOff + 3]; - u[uOff + 3] = (uint)c; - v[vOff + 3] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 4] + v[vOff + 4]; - u[uOff + 4] = (uint)c; - v[vOff + 4] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 5] + v[vOff + 5]; - u[uOff + 5] = (uint)c; - v[vOff + 5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static void Copy(uint[] x, uint[] z) - { - z[0] = x[0]; - z[1] = x[1]; - z[2] = x[2]; - z[3] = x[3]; - z[4] = x[4]; - z[5] = x[5]; - } - - public static uint[] Create() - { - return new uint[6]; - } - - public static uint[] CreateExt() - { - return new uint[12]; - } - - public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - bool pos = Gte(x, xOff, y, yOff); - if (pos) - { - Sub(x, xOff, y, yOff, z, zOff); - } - else - { - Sub(y, yOff, x, xOff, z, zOff); - } - return pos; - } - - public static bool Eq(uint[] x, uint[] y) - { - for (int i = 5; i >= 0; --i) - { - if (x[i] != y[i]) - return false; - } - return true; - } - - public static uint[] FromBigInteger(BigInteger x) - { - if (x.SignValue < 0 || x.BitLength > 192) - throw new ArgumentException(); - - uint[] z = Create(); - int i = 0; - while (x.SignValue != 0) - { - z[i++] = (uint)x.IntValue; - x = x.ShiftRight(32); - } - return z; - } - - public static uint GetBit(uint[] x, int bit) - { - if (bit == 0) - { - return x[0] & 1; - } - int w = bit >> 5; - if (w < 0 || w >= 6) - { - return 0; - } - int b = bit & 31; - return (x[w] >> b) & 1; - } - - public static bool Gte(uint[] x, uint[] y) - { - for (int i = 5; i >= 0; --i) - { - uint x_i = x[i], y_i = y[i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) - { - for (int i = 5; i >= 0; --i) - { - uint x_i = x[xOff + i], y_i = y[yOff + i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool IsOne(uint[] x) - { - if (x[0] != 1) - { - return false; - } - for (int i = 1; i < 6; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static bool IsZero(uint[] x) - { - for (int i = 0; i < 6; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static void Mul(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - - { - ulong c = 0, x_0 = x[0]; - c += x_0 * y_0; - zz[0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[5] = (uint)c; - c >>= 32; - zz[6] = (uint)c; - } - - for (int i = 1; i < 6; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - zz[i + 6] = (uint)c; - } - } - - public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - - { - ulong c = 0, x_0 = x[xOff + 0]; - c += x_0 * y_0; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[zzOff + 5] = (uint)c; - c >>= 32; - zz[zzOff + 6] = (uint)c; - } - - for (int i = 1; i < 6; ++i) - { - ++zzOff; - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - zz[zzOff + 6] = (uint)c; - } - } - - public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - - ulong zc = 0; - for (int i = 0; i < 6; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - c += zc + zz[i + 6]; - zz[i + 6] = (uint)c; - zc = c >> 32; - } - return (uint)zc; - } - - public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - - ulong zc = 0; - for (int i = 0; i < 6; ++i) - { - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += zc + zz[zzOff + 6]; - zz[zzOff + 6] = (uint)c; - zc = c >> 32; - ++zzOff; - } - return (uint)zc; - } - - public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - Debug.Assert(w >> 31 == 0); - - ulong c = 0, wVal = w; - ulong x0 = x[xOff + 0]; - c += wVal * x0 + y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong x1 = x[xOff + 1]; - c += wVal * x1 + x0 + y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - ulong x2 = x[xOff + 2]; - c += wVal * x2 + x1 + y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - ulong x3 = x[xOff + 3]; - c += wVal * x3 + x2 + y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - ulong x4 = x[xOff + 4]; - c += wVal * x4 + x3 + y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - ulong x5 = x[xOff + 5]; - c += wVal * x5 + x4 + y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += x5; - return c; - } - - public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff) - { - Debug.Assert(yyOff <= 6); - Debug.Assert(zzOff <= 6); - ulong c = 0, xVal = x; - c += xVal * yy[yyOff + 0] + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += xVal * yy[yyOff + 1] + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += xVal * yy[yyOff + 2] + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += xVal * yy[yyOff + 3] + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += xVal * yy[yyOff + 4] + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += xVal * yy[yyOff + 5] + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <= 2); - ulong c = 0, xVal = x; - ulong y00 = y & M; - c += xVal * y00 + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong y01 = y >> 32; - c += xVal * y01 + y00 + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += y01 + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 4); - } - - public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <=3); - ulong c = 0, yVal = y; - c += yVal * x + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += yVal + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3); - } - - public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(zOff <= 3); - ulong c = 0, xVal = x; - c += xVal * y + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += xVal * (y >> 32) + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3); - } - - public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) - { - ulong c = 0, xVal = x; - int i = 0; - do - { - c += xVal * y[i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < 6); - return (uint)c; - } - - public static void Square(uint[] x, uint[] zz) - { - ulong x_0 = x[0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 5, j = 12; - do - { - ulong xVal = x[i--]; - ulong p = xVal * xVal; - zz[--j] = (c << 31) | (uint)(p >> 33); - zz[--j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[1]; - ulong zz_2 = zz[2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[2]; - ulong zz_3 = zz[3]; - ulong zz_4 = zz[4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[3]; - ulong zz_5 = zz[5]; - ulong zz_6 = zz[6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[4]; - ulong zz_7 = zz[7]; - ulong zz_8 = zz[8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[5]; - ulong zz_9 = zz[9]; - ulong zz_10 = zz[10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_10 += zz_9 >> 32; - } - - w = (uint)zz_6; - zz[6] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_7; - zz[7] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_8; - zz[8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[10] = (w << 1) | c; - c = w >> 31; - w = zz[11] + (uint)(zz_10 >> 32); - zz[11] = (w << 1) | c; - } - - public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) - { - ulong x_0 = x[xOff + 0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 5, j = 12; - do - { - ulong xVal = x[xOff + i--]; - ulong p = xVal * xVal; - zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); - zz[zzOff + --j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[zzOff + 0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[xOff + 1]; - ulong zz_2 = zz[zzOff + 2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[zzOff + 1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[xOff + 2]; - ulong zz_3 = zz[zzOff + 3]; - ulong zz_4 = zz[zzOff + 4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[zzOff + 2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[xOff + 3]; - ulong zz_5 = zz[zzOff + 5]; - ulong zz_6 = zz[zzOff + 6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[zzOff + 3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[xOff + 4]; - ulong zz_7 = zz[zzOff + 7]; - ulong zz_8 = zz[zzOff + 8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[zzOff + 4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[xOff + 5]; - ulong zz_9 = zz[zzOff + 9]; - ulong zz_10 = zz[zzOff + 10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[zzOff + 5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_10 += zz_9 >> 32; - } - - w = (uint)zz_6; - zz[zzOff + 6] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_7; - zz[zzOff + 7] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_8; - zz[zzOff + 8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[zzOff + 9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[zzOff + 10] = (w << 1) | c; - c = w >> 31; - w = zz[zzOff + 11] + (uint)(zz_10 >> 32); - zz[zzOff + 11] = (w << 1) | c; - } - - public static int Sub(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - c += (long)x[xOff + 0] - y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)x[xOff + 1] - y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)x[xOff + 2] - y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)x[xOff + 3] - y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)x[xOff + 4] - y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)x[xOff + 5] - y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubBothFrom(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5]; - z[5] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) - { - long c = 0; - c += (long)z[zOff + 0] - x[xOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - x[xOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)z[zOff + 2] - x[xOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)z[zOff + 3] - x[xOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)z[zOff + 4] - x[xOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)z[zOff + 5] - x[xOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - return (int)c; - } - - public static BigInteger ToBigInteger(uint[] x) - { - byte[] bs = new byte[24]; - for (int i = 0; i < 6; ++i) - { - uint x_i = x[i]; - if (x_i != 0) - { - Pack.UInt32_To_BE(x_i, bs, (5 - i) << 2); - } - } - return new BigInteger(1, bs); - } - - public static void Zero(uint[] z) - { - z[0] = 0; - z[1] = 0; - z[2] = 0; - z[3] = 0; - z[4] = 0; - z[5] = 0; - } - } -} diff --git a/crypto/src/math/ec/custom/sec/Nat224.cs b/crypto/src/math/ec/custom/sec/Nat224.cs deleted file mode 100644 index d5b916a54..000000000 --- a/crypto/src/math/ec/custom/sec/Nat224.cs +++ /dev/null @@ -1,1176 +0,0 @@ -using System; -using System.Diagnostics; - -using Org.BouncyCastle.Crypto.Utilities; - -namespace Org.BouncyCastle.Math.EC.Custom.Sec -{ - internal abstract class Nat224 - { - private const ulong M = 0xFFFFFFFFUL; - - public static uint Add(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + y[6]; - z[6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - c += (ulong)x[xOff + 0] + y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddBothTo(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + y[6] + z[6]; - z[6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + z[6]; - z[6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) - { - ulong c = cIn; - c += (ulong)x[xOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) - { - ulong c = 0; - c += (ulong)u[uOff + 0] + v[vOff + 0]; - u[uOff + 0] = (uint)c; - v[vOff + 0] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 1] + v[vOff + 1]; - u[uOff + 1] = (uint)c; - v[vOff + 1] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 2] + v[vOff + 2]; - u[uOff + 2] = (uint)c; - v[vOff + 2] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 3] + v[vOff + 3]; - u[uOff + 3] = (uint)c; - v[vOff + 3] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 4] + v[vOff + 4]; - u[uOff + 4] = (uint)c; - v[vOff + 4] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 5] + v[vOff + 5]; - u[uOff + 5] = (uint)c; - v[vOff + 5] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 6] + v[vOff + 6]; - u[uOff + 6] = (uint)c; - v[vOff + 6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static void Copy(uint[] x, uint[] z) - { - z[0] = x[0]; - z[1] = x[1]; - z[2] = x[2]; - z[3] = x[3]; - z[4] = x[4]; - z[5] = x[5]; - z[6] = x[6]; - } - - public static uint[] Create() - { - return new uint[7]; - } - - public static uint[] CreateExt() - { - return new uint[14]; - } - - public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - bool pos = Gte(x, xOff, y, yOff); - if (pos) - { - Sub(x, xOff, y, yOff, z, zOff); - } - else - { - Sub(y, yOff, x, xOff, z, zOff); - } - return pos; - } - - public static bool Eq(uint[] x, uint[] y) - { - for (int i = 6; i >= 0; --i) - { - if (x[i] != y[i]) - return false; - } - return true; - } - - public static uint[] FromBigInteger(BigInteger x) - { - if (x.SignValue < 0 || x.BitLength > 224) - throw new ArgumentException(); - - uint[] z = Create(); - int i = 0; - while (x.SignValue != 0) - { - z[i++] = (uint)x.IntValue; - x = x.ShiftRight(32); - } - return z; - } - - public static uint GetBit(uint[] x, int bit) - { - if (bit == 0) - { - return x[0] & 1; - } - int w = bit >> 5; - if (w < 0 || w >= 7) - { - return 0; - } - int b = bit & 31; - return (x[w] >> b) & 1; - } - - public static bool Gte(uint[] x, uint[] y) - { - for (int i = 6; i >= 0; --i) - { - uint x_i = x[i], y_i = y[i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) - { - for (int i = 6; i >= 0; --i) - { - uint x_i = x[xOff + i], y_i = y[yOff + i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool IsOne(uint[] x) - { - if (x[0] != 1) - { - return false; - } - for (int i = 1; i < 7; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static bool IsZero(uint[] x) - { - for (int i = 0; i < 7; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static void Mul(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - ulong y_6 = y[6]; - - { - ulong c = 0, x_0 = x[0]; - c += x_0 * y_0; - zz[0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[5] = (uint)c; - c >>= 32; - c += x_0 * y_6; - zz[6] = (uint)c; - c >>= 32; - zz[7] = (uint)c; - } - - for (int i = 1; i < 7; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[i + 6]; - zz[i + 6] = (uint)c; - c >>= 32; - zz[i + 7] = (uint)c; - } - } - - public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - ulong y_6 = y[yOff + 6]; - - { - ulong c = 0, x_0 = x[xOff + 0]; - c += x_0 * y_0; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_0 * y_6; - zz[zzOff + 6] = (uint)c; - c >>= 32; - zz[zzOff + 7] = (uint)c; - } - - for (int i = 1; i < 7; ++i) - { - ++zzOff; - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[zzOff + 6]; - zz[zzOff + 6] = (uint)c; - c >>= 32; - zz[zzOff + 7] = (uint)c; - } - } - - public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - ulong y_6 = y[6]; - - ulong zc = 0; - for (int i = 0; i < 7; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[i + 6]; - zz[i + 6] = (uint)c; - c >>= 32; - c += zc + zz[i + 7]; - zz[i + 7] = (uint)c; - zc = c >> 32; - } - return (uint)zc; - } - - public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - ulong y_6 = y[yOff + 6]; - - ulong zc = 0; - for (int i = 0; i < 7; ++i) - { - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[zzOff + 6]; - zz[zzOff + 6] = (uint)c; - c >>= 32; - c += zc + zz[zzOff + 7]; - zz[zzOff + 7] = (uint)c; - zc = c >> 32; - ++zzOff; - } - return (uint)zc; - } - - public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - Debug.Assert(w >> 31 == 0); - - ulong c = 0, wVal = w; - ulong x0 = x[xOff + 0]; - c += wVal * x0 + y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong x1 = x[xOff + 1]; - c += wVal * x1 + x0 + y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - ulong x2 = x[xOff + 2]; - c += wVal * x2 + x1 + y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - ulong x3 = x[xOff + 3]; - c += wVal * x3 + x2 + y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - ulong x4 = x[xOff + 4]; - c += wVal * x4 + x3 + y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - ulong x5 = x[xOff + 5]; - c += wVal * x5 + x4 + y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - ulong x6 = x[xOff + 6]; - c += wVal * x6 + x5 + y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += x6; - return c; - } - - public static uint MulByWord(uint x, uint[] z) - { - ulong c = 0, xVal = x; - c += xVal * (ulong)z[0]; - z[0] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[1]; - z[1] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[2]; - z[2] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[3]; - z[3] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[4]; - z[4] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[5]; - z[5] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[6]; - z[6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint MulByWordAddTo(uint x, uint[] y, uint[] z) - { - ulong c = 0, xVal = x; - c += xVal * (ulong)z[0] + y[0]; - z[0] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[1] + y[1]; - z[1] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[2] + y[2]; - z[2] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[3] + y[3]; - z[3] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[4] + y[4]; - z[4] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[5] + y[5]; - z[5] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[6] + y[6]; - z[6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = x; - c += xVal * y[yOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <= 3); - ulong c = 0, xVal = x; - ulong y00 = y & M; - c += xVal * y00 + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong y01 = y >> 32; - c += xVal * y01 + y00 + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += y01 + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 4); - } - - public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <= 4); - ulong c = 0, yVal = y; - c += yVal * x + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += yVal + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3); - } - - public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(zOff <= 4); - ulong c = 0, xVal = x; - c += xVal * y + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += xVal * (y >> 32) + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3); - } - - public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) - { - ulong c = 0, xVal = x; - int i = 0; - do - { - c += xVal * y[i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < 7); - return (uint)c; - } - - public static void Square(uint[] x, uint[] zz) - { - ulong x_0 = x[0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 6, j = 14; - do - { - ulong xVal = x[i--]; - ulong p = xVal * xVal; - zz[--j] = (c << 31) | (uint)(p >> 33); - zz[--j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[1]; - ulong zz_2 = zz[2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[2]; - ulong zz_3 = zz[3]; - ulong zz_4 = zz[4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[3]; - ulong zz_5 = zz[5]; - ulong zz_6 = zz[6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[4]; - ulong zz_7 = zz[7]; - ulong zz_8 = zz[8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[5]; - ulong zz_9 = zz[9]; - ulong zz_10 = zz[10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_6 &= M; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_8 &= M; - zz_10 += zz_9 >> 32; - zz_9 &= M; - } - - ulong x_6 = x[6]; - ulong zz_11 = zz[11]; - ulong zz_12 = zz[12]; - { - zz_6 += x_6 * x_0; - w = (uint)zz_6; - zz[6] = (w << 1) | c; - c = w >> 31; - zz_7 += (zz_6 >> 32) + x_6 * x_1; - zz_8 += (zz_7 >> 32) + x_6 * x_2; - zz_9 += (zz_8 >> 32) + x_6 * x_3; - zz_10 += (zz_9 >> 32) + x_6 * x_4; - zz_11 += (zz_10 >> 32) + x_6 * x_5; - zz_12 += zz_11 >> 32; - } - - w = (uint)zz_7; - zz[7] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_8; - zz[8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[10] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_11; - zz[11] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_12; - zz[12] = (w << 1) | c; - c = w >> 31; - w = zz[13] + (uint)(zz_12 >> 32); - zz[13] = (w << 1) | c; - } - - public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) - { - ulong x_0 = x[xOff + 0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 6, j = 14; - do - { - ulong xVal = x[xOff + i--]; - ulong p = xVal * xVal; - zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); - zz[zzOff + --j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[zzOff + 0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[xOff + 1]; - ulong zz_2 = zz[zzOff + 2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[zzOff + 1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[xOff + 2]; - ulong zz_3 = zz[zzOff + 3]; - ulong zz_4 = zz[zzOff + 4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[zzOff + 2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[xOff + 3]; - ulong zz_5 = zz[zzOff + 5]; - ulong zz_6 = zz[zzOff + 6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[zzOff + 3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[xOff + 4]; - ulong zz_7 = zz[zzOff + 7]; - ulong zz_8 = zz[zzOff + 8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[zzOff + 4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[xOff + 5]; - ulong zz_9 = zz[zzOff + 9]; - ulong zz_10 = zz[zzOff + 10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[zzOff + 5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_6 &= M; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_8 &= M; - zz_10 += zz_9 >> 32; - zz_9 &= M; - } - - ulong x_6 = x[xOff + 6]; - ulong zz_11 = zz[zzOff + 11]; - ulong zz_12 = zz[zzOff + 12]; - { - zz_6 += x_6 * x_0; - w = (uint)zz_6; - zz[zzOff + 6] = (w << 1) | c; - c = w >> 31; - zz_7 += (zz_6 >> 32) + x_6 * x_1; - zz_8 += (zz_7 >> 32) + x_6 * x_2; - zz_9 += (zz_8 >> 32) + x_6 * x_3; - zz_10 += (zz_9 >> 32) + x_6 * x_4; - zz_11 += (zz_10 >> 32) + x_6 * x_5; - zz_12 += zz_11 >> 32; - } - - w = (uint)zz_7; - zz[zzOff + 7] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_8; - zz[zzOff + 8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[zzOff + 9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[zzOff + 10] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_11; - zz[zzOff + 11] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_12; - zz[zzOff + 12] = (w << 1) | c; - c = w >> 31; - w = zz[zzOff + 13] + (uint)(zz_12 >> 32); - zz[zzOff + 13] = (w << 1) | c; - } - - public static int Sub(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)x[6] - y[6]; - z[6] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - c += (long)x[xOff + 0] - y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)x[xOff + 1] - y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)x[xOff + 2] - y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)x[xOff + 3] - y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)x[xOff + 4] - y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)x[xOff + 5] - y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (long)x[xOff + 6] - y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubBothFrom(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)z[6] - x[6] - y[6]; - z[6] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)z[6] - x[6]; - z[6] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) - { - long c = 0; - c += (long)z[zOff + 0] - x[xOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - x[xOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)z[zOff + 2] - x[xOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)z[zOff + 3] - x[xOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)z[zOff + 4] - x[xOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)z[zOff + 5] - x[xOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (long)z[zOff + 6] - x[xOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - return (int)c; - } - - public static BigInteger ToBigInteger(uint[] x) - { - byte[] bs = new byte[28]; - for (int i = 0; i < 7; ++i) - { - uint x_i = x[i]; - if (x_i != 0) - { - Pack.UInt32_To_BE(x_i, bs, (6 - i) << 2); - } - } - return new BigInteger(1, bs); - } - - public static void Zero(uint[] z) - { - z[0] = 0; - z[1] = 0; - z[2] = 0; - z[3] = 0; - z[4] = 0; - z[5] = 0; - z[6] = 0; - } - } -} diff --git a/crypto/src/math/ec/custom/sec/Nat256.cs b/crypto/src/math/ec/custom/sec/Nat256.cs deleted file mode 100644 index bd2d6da47..000000000 --- a/crypto/src/math/ec/custom/sec/Nat256.cs +++ /dev/null @@ -1,1300 +0,0 @@ -using System; -using System.Diagnostics; - -using Org.BouncyCastle.Crypto.Utilities; - -namespace Org.BouncyCastle.Math.EC.Custom.Sec -{ - internal abstract class Nat256 - { - private const ulong M = 0xFFFFFFFFUL; - - public static uint Add(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + y[6]; - z[6] = (uint)c; - c >>= 32; - c += (ulong)x[7] + y[7]; - z[7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - c += (ulong)x[xOff + 0] + y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 7] + y[yOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddBothTo(uint[] x, uint[] y, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + y[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + y[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + y[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + y[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + y[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + y[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + y[6] + z[6]; - z[6] = (uint)c; - c >>= 32; - c += (ulong)x[7] + y[7] + z[7]; - z[7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0; - c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 7] + y[yOff + 7] + z[zOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, uint[] z) - { - ulong c = 0; - c += (ulong)x[0] + z[0]; - z[0] = (uint)c; - c >>= 32; - c += (ulong)x[1] + z[1]; - z[1] = (uint)c; - c >>= 32; - c += (ulong)x[2] + z[2]; - z[2] = (uint)c; - c >>= 32; - c += (ulong)x[3] + z[3]; - z[3] = (uint)c; - c >>= 32; - c += (ulong)x[4] + z[4]; - z[4] = (uint)c; - c >>= 32; - c += (ulong)x[5] + z[5]; - z[5] = (uint)c; - c >>= 32; - c += (ulong)x[6] + z[6]; - z[6] = (uint)c; - c >>= 32; - c += (ulong)x[7] + z[7]; - z[7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) - { - ulong c = cIn; - c += (ulong)x[xOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += (ulong)x[xOff + 7] + z[zOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) - { - ulong c = 0; - c += (ulong)u[uOff + 0] + v[vOff + 0]; - u[uOff + 0] = (uint)c; - v[vOff + 0] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 1] + v[vOff + 1]; - u[uOff + 1] = (uint)c; - v[vOff + 1] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 2] + v[vOff + 2]; - u[uOff + 2] = (uint)c; - v[vOff + 2] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 3] + v[vOff + 3]; - u[uOff + 3] = (uint)c; - v[vOff + 3] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 4] + v[vOff + 4]; - u[uOff + 4] = (uint)c; - v[vOff + 4] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 5] + v[vOff + 5]; - u[uOff + 5] = (uint)c; - v[vOff + 5] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 6] + v[vOff + 6]; - u[uOff + 6] = (uint)c; - v[vOff + 6] = (uint)c; - c >>= 32; - c += (ulong)u[uOff + 7] + v[vOff + 7]; - u[uOff + 7] = (uint)c; - v[vOff + 7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static void Copy(uint[] x, uint[] z) - { - z[0] = x[0]; - z[1] = x[1]; - z[2] = x[2]; - z[3] = x[3]; - z[4] = x[4]; - z[5] = x[5]; - z[6] = x[6]; - z[7] = x[7]; - } - - public static uint[] Create() - { - return new uint[8]; - } - - public static uint[] CreateExt() - { - return new uint[16]; - } - - public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - bool pos = Gte(x, xOff, y, yOff); - if (pos) - { - Sub(x, xOff, y, yOff, z, zOff); - } - else - { - Sub(y, yOff, x, xOff, z, zOff); - } - return pos; - } - - public static bool Eq(uint[] x, uint[] y) - { - for (int i = 7; i >= 0; --i) - { - if (x[i] != y[i]) - return false; - } - return true; - } - - public static uint[] FromBigInteger(BigInteger x) - { - if (x.SignValue < 0 || x.BitLength > 256) - throw new ArgumentException(); - - uint[] z = Create(); - int i = 0; - while (x.SignValue != 0) - { - z[i++] = (uint)x.IntValue; - x = x.ShiftRight(32); - } - return z; - } - - public static uint GetBit(uint[] x, int bit) - { - if (bit == 0) - { - return x[0] & 1; - } - if ((bit & 255) != bit) - { - return 0; - } - int w = bit >> 5; - int b = bit & 31; - return (x[w] >> b) & 1; - } - - public static bool Gte(uint[] x, uint[] y) - { - for (int i = 7; i >= 0; --i) - { - uint x_i = x[i], y_i = y[i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) - { - for (int i = 7; i >= 0; --i) - { - uint x_i = x[xOff + i], y_i = y[yOff + i]; - if (x_i < y_i) - return false; - if (x_i > y_i) - return true; - } - return true; - } - - public static bool IsOne(uint[] x) - { - if (x[0] != 1) - { - return false; - } - for (int i = 1; i < 8; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static bool IsZero(uint[] x) - { - for (int i = 0; i < 8; ++i) - { - if (x[i] != 0) - { - return false; - } - } - return true; - } - - public static void Mul(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - ulong y_6 = y[6]; - ulong y_7 = y[7]; - - { - ulong c = 0, x_0 = x[0]; - c += x_0 * y_0; - zz[0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[5] = (uint)c; - c >>= 32; - c += x_0 * y_6; - zz[6] = (uint)c; - c >>= 32; - c += x_0 * y_7; - zz[7] = (uint)c; - c >>= 32; - zz[8] = (uint)c; - } - - for (int i = 1; i < 8; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[i + 6]; - zz[i + 6] = (uint)c; - c >>= 32; - c += x_i * y_7 + zz[i + 7]; - zz[i + 7] = (uint)c; - c >>= 32; - zz[i + 8] = (uint)c; - } - } - - public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - ulong y_6 = y[yOff + 6]; - ulong y_7 = y[yOff + 7]; - - { - ulong c = 0, x_0 = x[xOff + 0]; - c += x_0 * y_0; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_0 * y_1; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_0 * y_2; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_0 * y_3; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_0 * y_4; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_0 * y_5; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_0 * y_6; - zz[zzOff + 6] = (uint)c; - c >>= 32; - c += x_0 * y_7; - zz[zzOff + 7] = (uint)c; - c >>= 32; - zz[zzOff + 8] = (uint)c; - } - - for (int i = 1; i < 8; ++i) - { - ++zzOff; - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[zzOff + 6]; - zz[zzOff + 6] = (uint)c; - c >>= 32; - c += x_i * y_7 + zz[zzOff + 7]; - zz[zzOff + 7] = (uint)c; - c >>= 32; - zz[zzOff + 8] = (uint)c; - } - } - - public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) - { - ulong y_0 = y[0]; - ulong y_1 = y[1]; - ulong y_2 = y[2]; - ulong y_3 = y[3]; - ulong y_4 = y[4]; - ulong y_5 = y[5]; - ulong y_6 = y[6]; - ulong y_7 = y[7]; - - ulong zc = 0; - for (int i = 0; i < 8; ++i) - { - ulong c = 0, x_i = x[i]; - c += x_i * y_0 + zz[i + 0]; - zz[i + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[i + 1]; - zz[i + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[i + 2]; - zz[i + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[i + 3]; - zz[i + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[i + 4]; - zz[i + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[i + 5]; - zz[i + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[i + 6]; - zz[i + 6] = (uint)c; - c >>= 32; - c += x_i * y_7 + zz[i + 7]; - zz[i + 7] = (uint)c; - c >>= 32; - c += zc + zz[i + 8]; - zz[i + 8] = (uint)c; - zc = c >> 32; - } - return (uint)zc; - } - - public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) - { - ulong y_0 = y[yOff + 0]; - ulong y_1 = y[yOff + 1]; - ulong y_2 = y[yOff + 2]; - ulong y_3 = y[yOff + 3]; - ulong y_4 = y[yOff + 4]; - ulong y_5 = y[yOff + 5]; - ulong y_6 = y[yOff + 6]; - ulong y_7 = y[yOff + 7]; - - ulong zc = 0; - for (int i = 0; i < 8; ++i) - { - ulong c = 0, x_i = x[xOff + i]; - c += x_i * y_0 + zz[zzOff + 0]; - zz[zzOff + 0] = (uint)c; - c >>= 32; - c += x_i * y_1 + zz[zzOff + 1]; - zz[zzOff + 1] = (uint)c; - c >>= 32; - c += x_i * y_2 + zz[zzOff + 2]; - zz[zzOff + 2] = (uint)c; - c >>= 32; - c += x_i * y_3 + zz[zzOff + 3]; - zz[zzOff + 3] = (uint)c; - c >>= 32; - c += x_i * y_4 + zz[zzOff + 4]; - zz[zzOff + 4] = (uint)c; - c >>= 32; - c += x_i * y_5 + zz[zzOff + 5]; - zz[zzOff + 5] = (uint)c; - c >>= 32; - c += x_i * y_6 + zz[zzOff + 6]; - zz[zzOff + 6] = (uint)c; - c >>= 32; - c += x_i * y_7 + zz[zzOff + 7]; - zz[zzOff + 7] = (uint)c; - c >>= 32; - c += zc + zz[zzOff + 8]; - zz[zzOff + 8] = (uint)c; - zc = c >> 32; - ++zzOff; - } - return (uint)zc; - } - - public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - Debug.Assert(w >> 31 == 0); - - ulong c = 0, wVal = w; - ulong x0 = x[xOff + 0]; - c += wVal * x0 + y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong x1 = x[xOff + 1]; - c += wVal * x1 + x0 + y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - ulong x2 = x[xOff + 2]; - c += wVal * x2 + x1 + y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - ulong x3 = x[xOff + 3]; - c += wVal * x3 + x2 + y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - ulong x4 = x[xOff + 4]; - c += wVal * x4 + x3 + y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - ulong x5 = x[xOff + 5]; - c += wVal * x5 + x4 + y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - ulong x6 = x[xOff + 6]; - c += wVal * x6 + x5 + y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - ulong x7 = x[xOff + 7]; - c += wVal * x7 + x6 + y[yOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - c += x7; - return c; - } - - public static uint MulByWord(uint x, uint[] z) - { - ulong c = 0, xVal = x; - c += xVal * (ulong)z[0]; - z[0] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[1]; - z[1] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[2]; - z[2] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[3]; - z[3] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[4]; - z[4] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[5]; - z[5] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[6]; - z[6] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[7]; - z[7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint MulByWordAddTo(uint x, uint[] y, uint[] z) - { - ulong c = 0, xVal = x; - c += xVal * (ulong)z[0] + y[0]; - z[0] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[1] + y[1]; - z[1] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[2] + y[2]; - z[2] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[3] + y[3]; - z[3] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[4] + y[4]; - z[4] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[5] + y[5]; - z[5] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[6] + y[6]; - z[6] = (uint)c; - c >>= 32; - c += xVal * (ulong)z[7] + y[7]; - z[7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff) - { - ulong c = 0, xVal = x; - c += xVal * y[yOff + 0] + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 1] + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 2] + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 3] + z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 4] + z[zOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 5] + z[zOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 6] + z[zOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += xVal * y[yOff + 7] + z[zOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (uint)c; - } - - public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <= 4); - ulong c = 0, xVal = x; - ulong y00 = y & M; - c += xVal * y00 + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - ulong y01 = y >> 32; - c += xVal * y01 + y00 + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += y01 + z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += z[zOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 4); - } - - public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) - { - Debug.Assert(x >> 31 == 0); - Debug.Assert(zOff <= 5); - ulong c = 0, yVal = y; - c += yVal * x + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += yVal + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3); - } - - public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) - { - Debug.Assert(zOff <= 5); - ulong c = 0, xVal = x; - c += xVal * y + z[zOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += xVal * (y >> 32) + z[zOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += z[zOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3); - } - - public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) - { - ulong c = 0, xVal = x; - int i = 0; - do - { - c += xVal * y[i]; - z[zOff + i] = (uint)c; - c >>= 32; - } - while (++i < 8); - return (uint)c; - } - - public static void Square(uint[] x, uint[] zz) - { - ulong x_0 = x[0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 7, j = 16; - do - { - ulong xVal = x[i--]; - ulong p = xVal * xVal; - zz[--j] = (c << 31) | (uint)(p >> 33); - zz[--j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[1]; - ulong zz_2 = zz[2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[2]; - ulong zz_3 = zz[3]; - ulong zz_4 = zz[4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[3]; - ulong zz_5 = zz[5]; - ulong zz_6 = zz[6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[4]; - ulong zz_7 = zz[7]; - ulong zz_8 = zz[8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[5]; - ulong zz_9 = zz[9]; - ulong zz_10 = zz[10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_6 &= M; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_8 &= M; - zz_10 += zz_9 >> 32; - zz_9 &= M; - } - - ulong x_6 = x[6]; - ulong zz_11 = zz[11]; - ulong zz_12 = zz[12]; - { - zz_6 += x_6 * x_0; - w = (uint)zz_6; - zz[6] = (w << 1) | c; - c = w >> 31; - zz_7 += (zz_6 >> 32) + x_6 * x_1; - zz_8 += (zz_7 >> 32) + x_6 * x_2; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_6 * x_3; - zz_8 &= M; - zz_10 += (zz_9 >> 32) + x_6 * x_4; - zz_9 &= M; - zz_11 += (zz_10 >> 32) + x_6 * x_5; - zz_10 &= M; - zz_12 += zz_11 >> 32; - zz_11 &= M; - } - - ulong x_7 = x[7]; - ulong zz_13 = zz[13]; - ulong zz_14 = zz[14]; - { - zz_7 += x_7 * x_0; - w = (uint)zz_7; - zz[7] = (w << 1) | c; - c = w >> 31; - zz_8 += (zz_7 >> 32) + x_7 * x_1; - zz_9 += (zz_8 >> 32) + x_7 * x_2; - zz_10 += (zz_9 >> 32) + x_7 * x_3; - zz_11 += (zz_10 >> 32) + x_7 * x_4; - zz_12 += (zz_11 >> 32) + x_7 * x_5; - zz_13 += (zz_12 >> 32) + x_7 * x_6; - zz_14 += zz_13 >> 32; - } - - w = (uint)zz_8; - zz[8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[10] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_11; - zz[11] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_12; - zz[12] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_13; - zz[13] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_14; - zz[14] = (w << 1) | c; - c = w >> 31; - w = zz[15] + (uint)(zz_14 >> 32); - zz[15] = (w << 1) | c; - } - - public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) - { - ulong x_0 = x[xOff + 0]; - ulong zz_1; - - uint c = 0, w; - { - int i = 7, j = 16; - do - { - ulong xVal = x[xOff + i--]; - ulong p = xVal * xVal; - zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); - zz[zzOff + --j] = (uint)(p >> 1); - c = (uint)p; - } - while (i > 0); - - { - ulong p = x_0 * x_0; - zz_1 = (ulong)(c << 31) | (p >> 33); - zz[zzOff + 0] = (uint)p; - c = (uint)(p >> 32) & 1; - } - } - - ulong x_1 = x[xOff + 1]; - ulong zz_2 = zz[zzOff + 2]; - - { - zz_1 += x_1 * x_0; - w = (uint)zz_1; - zz[zzOff + 1] = (w << 1) | c; - c = w >> 31; - zz_2 += zz_1 >> 32; - } - - ulong x_2 = x[xOff + 2]; - ulong zz_3 = zz[zzOff + 3]; - ulong zz_4 = zz[zzOff + 4]; - { - zz_2 += x_2 * x_0; - w = (uint)zz_2; - zz[zzOff + 2] = (w << 1) | c; - c = w >> 31; - zz_3 += (zz_2 >> 32) + x_2 * x_1; - zz_4 += zz_3 >> 32; - zz_3 &= M; - } - - ulong x_3 = x[xOff + 3]; - ulong zz_5 = zz[zzOff + 5]; - ulong zz_6 = zz[zzOff + 6]; - { - zz_3 += x_3 * x_0; - w = (uint)zz_3; - zz[zzOff + 3] = (w << 1) | c; - c = w >> 31; - zz_4 += (zz_3 >> 32) + x_3 * x_1; - zz_5 += (zz_4 >> 32) + x_3 * x_2; - zz_4 &= M; - zz_6 += zz_5 >> 32; - zz_5 &= M; - } - - ulong x_4 = x[xOff + 4]; - ulong zz_7 = zz[zzOff + 7]; - ulong zz_8 = zz[zzOff + 8]; - { - zz_4 += x_4 * x_0; - w = (uint)zz_4; - zz[zzOff + 4] = (w << 1) | c; - c = w >> 31; - zz_5 += (zz_4 >> 32) + x_4 * x_1; - zz_6 += (zz_5 >> 32) + x_4 * x_2; - zz_5 &= M; - zz_7 += (zz_6 >> 32) + x_4 * x_3; - zz_6 &= M; - zz_8 += zz_7 >> 32; - zz_7 &= M; - } - - ulong x_5 = x[xOff + 5]; - ulong zz_9 = zz[zzOff + 9]; - ulong zz_10 = zz[zzOff + 10]; - { - zz_5 += x_5 * x_0; - w = (uint)zz_5; - zz[zzOff + 5] = (w << 1) | c; - c = w >> 31; - zz_6 += (zz_5 >> 32) + x_5 * x_1; - zz_7 += (zz_6 >> 32) + x_5 * x_2; - zz_6 &= M; - zz_8 += (zz_7 >> 32) + x_5 * x_3; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_5 * x_4; - zz_8 &= M; - zz_10 += zz_9 >> 32; - zz_9 &= M; - } - - ulong x_6 = x[xOff + 6]; - ulong zz_11 = zz[zzOff + 11]; - ulong zz_12 = zz[zzOff + 12]; - { - zz_6 += x_6 * x_0; - w = (uint)zz_6; - zz[zzOff + 6] = (w << 1) | c; - c = w >> 31; - zz_7 += (zz_6 >> 32) + x_6 * x_1; - zz_8 += (zz_7 >> 32) + x_6 * x_2; - zz_7 &= M; - zz_9 += (zz_8 >> 32) + x_6 * x_3; - zz_8 &= M; - zz_10 += (zz_9 >> 32) + x_6 * x_4; - zz_9 &= M; - zz_11 += (zz_10 >> 32) + x_6 * x_5; - zz_10 &= M; - zz_12 += zz_11 >> 32; - zz_11 &= M; - } - - ulong x_7 = x[xOff + 7]; - ulong zz_13 = zz[zzOff + 13]; - ulong zz_14 = zz[zzOff + 14]; - { - zz_7 += x_7 * x_0; - w = (uint)zz_7; - zz[zzOff + 7] = (w << 1) | c; - c = w >> 31; - zz_8 += (zz_7 >> 32) + x_7 * x_1; - zz_9 += (zz_8 >> 32) + x_7 * x_2; - zz_10 += (zz_9 >> 32) + x_7 * x_3; - zz_11 += (zz_10 >> 32) + x_7 * x_4; - zz_12 += (zz_11 >> 32) + x_7 * x_5; - zz_13 += (zz_12 >> 32) + x_7 * x_6; - zz_14 += zz_13 >> 32; - } - - w = (uint)zz_8; - zz[zzOff + 8] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_9; - zz[zzOff + 9] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_10; - zz[zzOff + 10] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_11; - zz[zzOff + 11] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_12; - zz[zzOff + 12] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_13; - zz[zzOff + 13] = (w << 1) | c; - c = w >> 31; - w = (uint)zz_14; - zz[zzOff + 14] = (w << 1) | c; - c = w >> 31; - w = zz[zzOff + 15] + (uint)(zz_14 >> 32); - zz[zzOff + 15] = (w << 1) | c; - } - - public static int Sub(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)x[6] - y[6]; - z[6] = (uint)c; - c >>= 32; - c += (long)x[7] - y[7]; - z[7] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) - { - long c = 0; - c += (long)x[xOff + 0] - y[yOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)x[xOff + 1] - y[yOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)x[xOff + 2] - y[yOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)x[xOff + 3] - y[yOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)x[xOff + 4] - y[yOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)x[xOff + 5] - y[yOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (long)x[xOff + 6] - y[yOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += (long)x[xOff + 7] - y[yOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubBothFrom(uint[] x, uint[] y, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0] - y[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1] - y[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2] - y[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3] - y[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4] - y[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5] - y[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)z[6] - x[6] - y[6]; - z[6] = (uint)c; - c >>= 32; - c += (long)z[7] - x[7] - y[7]; - z[7] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, uint[] z) - { - long c = 0; - c += (long)z[0] - x[0]; - z[0] = (uint)c; - c >>= 32; - c += (long)z[1] - x[1]; - z[1] = (uint)c; - c >>= 32; - c += (long)z[2] - x[2]; - z[2] = (uint)c; - c >>= 32; - c += (long)z[3] - x[3]; - z[3] = (uint)c; - c >>= 32; - c += (long)z[4] - x[4]; - z[4] = (uint)c; - c >>= 32; - c += (long)z[5] - x[5]; - z[5] = (uint)c; - c >>= 32; - c += (long)z[6] - x[6]; - z[6] = (uint)c; - c >>= 32; - c += (long)z[7] - x[7]; - z[7] = (uint)c; - c >>= 32; - return (int)c; - } - - public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) - { - long c = 0; - c += (long)z[zOff + 0] - x[xOff + 0]; - z[zOff + 0] = (uint)c; - c >>= 32; - c += (long)z[zOff + 1] - x[xOff + 1]; - z[zOff + 1] = (uint)c; - c >>= 32; - c += (long)z[zOff + 2] - x[xOff + 2]; - z[zOff + 2] = (uint)c; - c >>= 32; - c += (long)z[zOff + 3] - x[xOff + 3]; - z[zOff + 3] = (uint)c; - c >>= 32; - c += (long)z[zOff + 4] - x[xOff + 4]; - z[zOff + 4] = (uint)c; - c >>= 32; - c += (long)z[zOff + 5] - x[xOff + 5]; - z[zOff + 5] = (uint)c; - c >>= 32; - c += (long)z[zOff + 6] - x[xOff + 6]; - z[zOff + 6] = (uint)c; - c >>= 32; - c += (long)z[zOff + 7] - x[xOff + 7]; - z[zOff + 7] = (uint)c; - c >>= 32; - return (int)c; - } - - public static BigInteger ToBigInteger(uint[] x) - { - byte[] bs = new byte[32]; - for (int i = 0; i < 8; ++i) - { - uint x_i = x[i]; - if (x_i != 0) - { - Pack.UInt32_To_BE(x_i, bs, (7 - i) << 2); - } - } - return new BigInteger(1, bs); - } - - public static void Zero(uint[] z) - { - z[0] = 0; - z[1] = 0; - z[2] = 0; - z[3] = 0; - z[4] = 0; - z[5] = 0; - z[6] = 0; - z[7] = 0; - } - } -} diff --git a/crypto/src/math/ec/custom/sec/Nat384.cs b/crypto/src/math/ec/custom/sec/Nat384.cs deleted file mode 100644 index dd93e68b6..000000000 --- a/crypto/src/math/ec/custom/sec/Nat384.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Diagnostics; - -namespace Org.BouncyCastle.Math.EC.Custom.Sec -{ - internal abstract class Nat384 - { - public static void Mul(uint[] x, uint[] y, uint[] zz) - { - Nat192.Mul(x, y, zz); - Nat192.Mul(x, 6, y, 6, zz, 12); - - uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12); - uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0); - c18 += Nat192.AddTo(zz, 18, zz, 12, c12); - - uint[] dx = Nat192.Create(), dy = Nat192.Create(); - bool neg = Nat192.Diff(x, 6, x, 0, dx, 0) != Nat192.Diff(y, 6, y, 0, dy, 0); - - uint[] tt = Nat192.CreateExt(); - Nat192.Mul(dx, dy, tt); - - c18 += neg ? Nat.AddTo(12, tt, 0, zz, 6) : (uint)Nat.SubFrom(12, tt, 0, zz, 6); - Nat.AddWordAt(24, c18, zz, 18); - } - - public static void Square(uint[] x, uint[] zz) - { - Nat192.Square(x, zz); - Nat192.Square(x, 6, zz, 12); - - uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12); - uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0); - c18 += Nat192.AddTo(zz, 18, zz, 12, c12); - - uint[] dx = Nat192.Create(); - Nat192.Diff(x, 6, x, 0, dx, 0); - - uint[] m = Nat192.CreateExt(); - Nat192.Square(dx, m); - - c18 += (uint)Nat.SubFrom(12, m, 0, zz, 6); - Nat.AddWordAt(24, c18, zz, 18); - } - } -} diff --git a/crypto/src/math/ec/custom/sec/Nat512.cs b/crypto/src/math/ec/custom/sec/Nat512.cs deleted file mode 100644 index 46e10f995..000000000 --- a/crypto/src/math/ec/custom/sec/Nat512.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Diagnostics; - -namespace Org.BouncyCastle.Math.EC.Custom.Sec -{ - internal abstract class Nat512 - { - public static void Mul(uint[] x, uint[] y, uint[] zz) - { - Nat256.Mul(x, y, zz); - Nat256.Mul(x, 8, y, 8, zz, 16); - - uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16); - uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0); - c24 += Nat256.AddTo(zz, 24, zz, 16, c16); - - uint[] dx = Nat256.Create(), dy = Nat256.Create(); - bool neg = Nat256.Diff(x, 8, x, 0, dx, 0) != Nat256.Diff(y, 8, y, 0, dy, 0); - - uint[] tt = Nat256.CreateExt(); - Nat256.Mul(dx, dy, tt); - - c24 += neg ? Nat.AddTo(16, tt, 0, zz, 8) : (uint)Nat.SubFrom(16, tt, 0, zz, 8); - Nat.AddWordAt(32, c24, zz, 24); - } - - public static void Square(uint[] x, uint[] zz) - { - Nat256.Square(x, zz); - Nat256.Square(x, 8, zz, 16); - - uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16); - uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0); - c24 += Nat256.AddTo(zz, 24, zz, 16, c16); - - uint[] dx = Nat256.Create(); - Nat256.Diff(x, 8, x, 0, dx, 0); - - uint[] m = Nat256.CreateExt(); - Nat256.Square(dx, m); - - c24 += (uint)Nat.SubFrom(16, m, 0, zz, 8); - Nat.AddWordAt(32, c24, zz, 24); - } - } -} diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Field.cs b/crypto/src/math/ec/custom/sec/SecP192K1Field.cs index d5ca903d1..a00360360 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192K1Field diff --git a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs index 78886dd8c..dce377035 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1FieldElement.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs index 648aca502..58eb09102 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192K1Point diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Field.cs b/crypto/src/math/ec/custom/sec/SecP192R1Field.cs index 85e3a0394..096c2b51f 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192R1Field diff --git a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs index 020c5cdbb..45bcb00f0 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1FieldElement.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs index 797a8de35..3b53e341e 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP192R1Point diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Field.cs b/crypto/src/math/ec/custom/sec/SecP224K1Field.cs index a55810c6d..98cf777a5 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224K1Field diff --git a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs index 72ff4b099..fec07436a 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1FieldElement.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs index 8cbd29699..98cb29274 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224K1Point diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Field.cs b/crypto/src/math/ec/custom/sec/SecP224R1Field.cs index 559593c66..4f5c3bbda 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224R1Field diff --git a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs index 06f47cded..2b9a06564 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1FieldElement.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs index c3f4efb59..73c4f1948 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP224R1Point diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Field.cs b/crypto/src/math/ec/custom/sec/SecP256K1Field.cs index ba3a070a9..b0646e93f 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256K1Field diff --git a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs index d9a039a4f..473113d0f 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1FieldElement.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs index 3165682fa..072a0b969 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256K1Point diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Field.cs b/crypto/src/math/ec/custom/sec/SecP256R1Field.cs index 9ed9dcd41..11594b2ba 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256R1Field diff --git a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs index b22763cfa..d7838aead 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1FieldElement.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs index 1de4a0b4a..83320824d 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP256R1Point diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Field.cs b/crypto/src/math/ec/custom/sec/SecP384R1Field.cs index 508b01e3c..7820775ee 100644 --- a/crypto/src/math/ec/custom/sec/SecP384R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP384R1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP384R1Field diff --git a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs index 40086978d..18d48a57d 100644 --- a/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP384R1FieldElement.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Point.cs b/crypto/src/math/ec/custom/sec/SecP384R1Point.cs index 68c601611..83159ce61 100644 --- a/crypto/src/math/ec/custom/sec/SecP384R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP384R1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP384R1Point diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Field.cs b/crypto/src/math/ec/custom/sec/SecP521R1Field.cs index 3568156d8..b7f8eb146 100644 --- a/crypto/src/math/ec/custom/sec/SecP521R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP521R1Field.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP521R1Field diff --git a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs index 83a615928..6f02a7eb5 100644 --- a/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecP521R1FieldElement.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Custom.Sec diff --git a/crypto/src/math/ec/custom/sec/SecP521R1Point.cs b/crypto/src/math/ec/custom/sec/SecP521R1Point.cs index fb1996cfd..7ad97f76f 100644 --- a/crypto/src/math/ec/custom/sec/SecP521R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP521R1Point.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math.Raw; + namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal class SecP521R1Point diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs new file mode 100644 index 000000000..9755c9d6f --- /dev/null +++ b/crypto/src/math/raw/Interleave.cs @@ -0,0 +1,70 @@ +using System; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Interleave + { + /* + * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits. + * In a binary field, this operation is the same as squaring an 8 bit number. + */ + private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[] + { + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 + }; + + internal static uint Expand8to16(uint x) + { + return INTERLEAVE2_TABLE[x & 0xFF]; + } + + internal static uint Expand16to32(uint x) + { + return (uint)(INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >> 8) & 0xFF] << 16); + } + + internal static ulong Expand32to64(uint x) + { + uint r00 = (uint)(INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >> 8) & 0xFF] << 16); + uint r32 = (uint)(INTERLEAVE2_TABLE[(x >> 16) & 0xFF] | INTERLEAVE2_TABLE[x >> 24] << 16); + return (ulong)r32 << 32 | (ulong)r00; + } + + internal static void Expand64To128(ulong x, ulong[] z, int zOff) + { + z[zOff ] = Expand32to64((uint)x); + z[zOff + 1] = Expand32to64((uint)(x >> 32)); + } + } +} diff --git a/crypto/src/math/raw/Mod.cs b/crypto/src/math/raw/Mod.cs new file mode 100644 index 000000000..63467e668 --- /dev/null +++ b/crypto/src/math/raw/Mod.cs @@ -0,0 +1,184 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Mod + { + public static void Invert(uint[] p, uint[] x, uint[] z) + { + int len = p.Length; + if (Nat.IsZero(len, x)) + throw new ArgumentException("cannot be 0", "x"); + if (Nat.IsOne(len, x)) + { + Array.Copy(x, 0, z, 0, len); + return; + } + + uint[] u = Nat.Copy(len, x); + uint[] a = Nat.Create(len); + a[0] = 1; + int ac = 0; + + if ((u[0] & 1) == 0) + { + InversionStep(p, u, len, a, ref ac); + } + if (Nat.IsOne(len, u)) + { + InversionResult(p, ac, a, z); + return; + } + + uint[] v = Nat.Copy(len, p); + uint[] b = Nat.Create(len); + int bc = 0; + + int uvLen = len; + + for (;;) + { + while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0) + { + --uvLen; + } + + if (Nat.Gte(len, u, v)) + { + Nat.SubFrom(len, v, u); + Debug.Assert((u[0] & 1) == 0); + ac += Nat.SubFrom(len, b, a) - bc; + InversionStep(p, u, uvLen, a, ref ac); + if (Nat.IsOne(len, u)) + { + InversionResult(p, ac, a, z); + return; + } + } + else + { + Nat.SubFrom(len, u, v); + Debug.Assert((v[0] & 1) == 0); + bc += Nat.SubFrom(len, a, b) - ac; + InversionStep(p, v, uvLen, b, ref bc); + if (Nat.IsOne(len, v)) + { + InversionResult(p, bc, b, z); + return; + } + } + } + } + + public static uint[] Random(uint[] p) + { + int len = p.Length; + Random rand = new Random(); + uint[] s = Nat.Create(len); + + uint m = p[len - 1]; + m |= m >> 1; + m |= m >> 2; + m |= m >> 4; + m |= m >> 8; + m |= m >> 16; + + do + { + byte[] bytes = new byte[len << 2]; + rand.NextBytes(bytes); + Pack.BE_To_UInt32(bytes, 0, s); + s[len - 1] &= m; + } + while (Nat.Gte(len, s, p)); + + return s; + } + + public static void Add(uint[] p, uint[] x, uint[] y, uint[] z) + { + int len = p.Length; + uint c = Nat.Add(len, x, y, z); + if (c != 0) + { + Nat.SubFrom(len, p, z); + } + } + + public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z) + { + int len = p.Length; + int c = Nat.Sub(len, x, y, z); + if (c != 0) + { + Nat.AddTo(len, p, z); + } + } + + private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z) + { + if (ac < 0) + { + Nat.Add(p.Length, a, p, z); + } + else + { + Array.Copy(a, 0, z, 0, p.Length); + } + } + + private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc) + { + int len = p.Length; + int count = 0; + while (u[0] == 0) + { + Nat.ShiftDownWord(uLen, u, 0); + count += 32; + } + + { + int zeroes = GetTrailingZeroes(u[0]); + if (zeroes > 0) + { + Nat.ShiftDownBits(uLen, u, zeroes, 0); + count += zeroes; + } + } + + for (int i = 0; i < count; ++i) + { + if ((x[0] & 1) != 0) + { + if (xc < 0) + { + xc += (int)Nat.AddTo(len, p, x); + } + else + { + xc += Nat.SubFrom(len, p, x); + } + } + + Debug.Assert(xc == 0 || xc == -1); + Nat.ShiftDownBit(len, x, (uint)xc); + } + } + + private static int GetTrailingZeroes(uint x) + { + Debug.Assert(x != 0); + int count = 0; + while ((x & 1) == 0) + { + x >>= 1; + ++count; + } + return count; + } + } +} diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs new file mode 100644 index 000000000..1f9ab00ec --- /dev/null +++ b/crypto/src/math/raw/Nat.cs @@ -0,0 +1,1053 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(int len, uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + for (int i = 0; i < len; ++i) + { + c += (ulong)x[i] + y[i]; + z[i] = (uint)c; + c >>= 32; + } + return (uint)c; + } + + public static uint Add33At(int len, uint x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + ulong c = (ulong)z[zPos + 0] + x; + z[zPos + 0] = (uint)c; + c >>= 32; + c += (ulong)z[zPos + 1] + 1; + z[zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zPos + 2); + } + + public static uint Add33At(int len, uint x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + ulong c = (ulong)z[zOff + zPos] + x; + z[zOff + zPos] = (uint)c; + c >>= 32; + c += (ulong)z[zOff + zPos + 1] + 1; + z[zOff + zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); + } + + public static uint Add33To(int len, uint x, uint[] z) + { + ulong c = (ulong)z[0] + x; + z[0] = (uint)c; + c >>= 32; + c += (ulong)z[1] + 1; + z[1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, 2); + } + + public static uint Add33To(int len, uint x, uint[] z, int zOff) + { + ulong c = (ulong)z[zOff + 0] + x; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)z[zOff + 1] + 1; + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, 2); + } + + public static uint AddBothTo(int len, uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + for (int i = 0; i < len; ++i) + { + c += (ulong)x[i] + y[i] + z[i]; + z[i] = (uint)c; + c >>= 32; + } + return (uint)c; + } + + public static uint AddBothTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0; + for (int i = 0; i < len; ++i) + { + c += (ulong)x[xOff + i] + y[yOff + i] + z[zOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + return (uint)c; + } + + public static uint AddDWordAt(int len, ulong x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + ulong c = (ulong)z[zPos + 0] + (x & M); + z[zPos + 0] = (uint)c; + c >>= 32; + c += (ulong)z[zPos + 1] + (x >> 32); + z[zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zPos + 2); + } + + public static uint AddDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + ulong c = (ulong)z[zOff + zPos] + (x & M); + z[zOff + zPos] = (uint)c; + c >>= 32; + c += (ulong)z[zOff + zPos + 1] + (x >> 32); + z[zOff + zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2); + } + + public static uint AddDWordTo(int len, ulong x, uint[] z) + { + ulong c = (ulong)z[0] + (x & M); + z[0] = (uint)c; + c >>= 32; + c += (ulong)z[1] + (x >> 32); + z[1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, 2); + } + + public static uint AddDWordTo(int len, ulong x, uint[] z, int zOff) + { + ulong c = (ulong)z[zOff + 0] + (x & M); + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)z[zOff + 1] + (x >> 32); + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, 2); + } + + public static uint AddTo(int len, uint[] x, uint[] z) + { + ulong c = 0; + for (int i = 0; i < len; ++i) + { + c += (ulong)x[i] + z[i]; + z[i] = (uint)c; + c >>= 32; + } + return (uint)c; + } + + public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff) + { + ulong c = 0; + for (int i = 0; i < len; ++i) + { + c += (ulong)x[xOff + i] + z[zOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + return (uint)c; + } + + public static uint AddWordAt(int len, uint x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 1)); + ulong c = (ulong)x + z[zPos]; + z[zPos] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zPos + 1); + } + + public static uint AddWordAt(int len, uint x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 1)); + ulong c = (ulong)x + z[zOff + zPos]; + z[zOff + zPos] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 1); + } + + public static uint AddWordTo(int len, uint x, uint[] z) + { + ulong c = (ulong)x + z[0]; + z[0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, 1); + } + + public static uint AddWordTo(int len, uint x, uint[] z, int zOff) + { + ulong c = (ulong)x + z[zOff]; + z[zOff] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zOff, 1); + } + + public static void Copy(int len, uint[] x, uint[] z) + { + Array.Copy(x, 0, z, 0, len); + } + + public static uint[] Copy(int len, uint[] x) + { + uint[] z = new uint[len]; + Array.Copy(x, 0, z, 0, len); + return z; + } + + public static uint[] Create(int len) + { + return new uint[len]; + } + + public static ulong[] Create64(int len) + { + return new ulong[len]; + } + + public static int Dec(int len, uint[] z) + { + for (int i = 0; i < len; ++i) + { + if (--z[i] != uint.MaxValue) + { + return 0; + } + } + return -1; + } + + public static int Dec(int len, uint[] x, uint[] z) + { + int i = 0; + while (i < len) + { + uint c = x[i] - 1; + z[i] = c; + ++i; + if (c != uint.MaxValue) + { + while (i < len) + { + z[i] = x[i]; + ++i; + } + return 0; + } + } + return -1; + } + + public static int DecAt(int len, uint[] z, int zPos) + { + Debug.Assert(zPos <= len); + for (int i = zPos; i < len; ++i) + { + if (--z[i] != uint.MaxValue) + { + return 0; + } + } + return -1; + } + + public static int DecAt(int len, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= len); + for (int i = zPos; i < len; ++i) + { + if (--z[zOff + i] != uint.MaxValue) + { + return 0; + } + } + return -1; + } + + public static bool Eq(int len, uint[] x, uint[] y) + { + for (int i = len - 1; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static uint[] FromBigInteger(int bits, BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > bits) + throw new ArgumentException(); + + int len = (bits + 31) >> 5; + uint[] z = Create(len); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= x.Length) + { + return 0; + } + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(int len, uint[] x, uint[] y) + { + for (int i = len - 1; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static uint Inc(int len, uint[] z) + { + for (int i = 0; i < len; ++i) + { + if (++z[i] != uint.MinValue) + { + return 0; + } + } + return 1; + } + + public static uint Inc(int len, uint[] x, uint[] z) + { + int i = 0; + while (i < len) + { + uint c = x[i] + 1; + z[i] = c; + ++i; + if (c != 0) + { + while (i < len) + { + z[i] = x[i]; + ++i; + } + return 0; + } + } + return 1; + } + + public static uint IncAt(int len, uint[] z, int zPos) + { + Debug.Assert(zPos <= len); + for (int i = zPos; i < len; ++i) + { + if (++z[i] != uint.MinValue) + { + return 0; + } + } + return 1; + } + + public static uint IncAt(int len, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= len); + for (int i = zPos; i < len; ++i) + { + if (++z[zOff + i] != uint.MinValue) + { + return 0; + } + } + return 1; + } + + public static bool IsOne(int len, uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < len; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero(int len, uint[] x) + { + if (x[0] != 0) + { + return false; + } + for (int i = 1; i < len; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void Mul(int len, uint[] x, uint[] y, uint[] zz) + { + zz[len] = (uint)MulWord(len, x[0], y, zz); + + for (int i = 1; i < len; ++i) + { + zz[i + len] = (uint)MulWordAddTo(len, x[i], y, 0, zz, i); + } + } + + public static void Mul(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + zz[zzOff + len] = (uint)MulWord(len, x[xOff], y, yOff, zz, zzOff); + + for (int i = 1; i < len; ++i) + { + zz[zzOff + i + len] = (uint)MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i); + } + } + + public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff) + { + ulong c = 0, aVal = (ulong)a, bVal = (ulong)b; + int i = 0; + do + { + c += aVal * x[i] + bVal * y[i] + z[zOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < len); + return (uint)c; + } + + public static uint MulWord(int len, uint x, uint[] y, uint[] z) + { + ulong c = 0, xVal = (ulong)x; + int i = 0; + do + { + c += xVal * y[i]; + z[i] = (uint)c; + c >>= 32; + } + while (++i < len); + return (uint)c; + } + + public static uint MulWord(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0, xVal = (ulong)x; + int i = 0; + do + { + c += xVal * y[yOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < len); + return (uint)c; + } + + public static uint MulWordAddTo(int len, uint x, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0, xVal = (ulong)x; + int i = 0; + do + { + c += xVal * y[yOff + i] + z[zOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < len); + return (uint)c; + } + + public static uint MulWordDwordAddAt(int len, uint x, ulong y, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 3)); + ulong c = 0, xVal = (ulong)x; + c += xVal * (uint)y + z[zPos + 0]; + z[zPos + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zPos + 1]; + z[zPos + 1] = (uint)c; + c >>= 32; + c += (ulong)z[zPos + 2]; + z[zPos + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : IncAt(len, z, zPos + 3); + } + + public static uint ShiftDownBit(int len, uint[] z, uint c) + { + int i = len; + while (--i >= 0) + { + uint next = z[i]; + z[i] = (next >> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static uint ShiftDownBit(int len, uint[] z, int zOff, uint c) + { + int i = len; + while (--i >= 0) + { + uint next = z[zOff + i]; + z[zOff + i] = (next >> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static uint ShiftDownBit(int len, uint[] x, uint c, uint[] z) + { + int i = len; + while (--i >= 0) + { + uint next = x[i]; + z[i] = (next >> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static uint ShiftDownBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) + { + int i = len; + while (--i >= 0) + { + uint next = x[xOff + i]; + z[zOff + i] = (next >> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static uint ShiftDownBits(int len, uint[] z, int bits, uint c) + { + Debug.Assert(bits > 0 && bits < 32); + int i = len; + while (--i >= 0) + { + uint next = z[i]; + z[i] = (next >> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static uint ShiftDownBits(int len, uint[] z, int zOff, int bits, uint c) + { + Debug.Assert(bits > 0 && bits < 32); + int i = len; + while (--i >= 0) + { + uint next = z[zOff + i]; + z[zOff + i] = (next >> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static uint ShiftDownBits(int len, uint[] x, int bits, uint c, uint[] z) + { + Debug.Assert(bits > 0 && bits < 32); + int i = len; + while (--i >= 0) + { + uint next = x[i]; + z[i] = (next >> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static uint ShiftDownBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) + { + Debug.Assert(bits > 0 && bits < 32); + int i = len; + while (--i >= 0) + { + uint next = x[xOff + i]; + z[zOff + i] = (next >> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static uint ShiftDownWord(int len, uint[] z, uint c) + { + int i = len; + while (--i >= 0) + { + uint next = z[i]; + z[i] = c; + c = next; + } + return c; + } + + public static uint ShiftUpBit(int len, uint[] z, uint c) + { + for (int i = 0; i < len; ++i) + { + uint next = z[i]; + z[i] = (next << 1) | (c >> 31); + c = next; + } + return c >> 31; + } + + public static uint ShiftUpBit(int len, uint[] z, int zOff, uint c) + { + for (int i = 0; i < len; ++i) + { + uint next = z[zOff + i]; + z[zOff + i] = (next << 1) | (c >> 31); + c = next; + } + return c >> 31; + } + + public static uint ShiftUpBit(int len, uint[] x, uint c, uint[] z) + { + for (int i = 0; i < len; ++i) + { + uint next = x[i]; + z[i] = (next << 1) | (c >> 31); + c = next; + } + return c >> 31; + } + + public static uint ShiftUpBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + uint next = x[xOff + i]; + z[zOff + i] = (next << 1) | (c >> 31); + c = next; + } + return c >> 31; + } + + public static ulong ShiftUpBit64(int len, ulong[] x, int xOff, ulong c, ulong[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + ulong next = x[xOff + i]; + z[zOff + i] = (next << 1) | (c >> 63); + c = next; + } + return c >> 63; + } + + public static uint ShiftUpBits(int len, uint[] z, int bits, uint c) + { + Debug.Assert(bits > 0 && bits < 32); + for (int i = 0; i < len; ++i) + { + uint next = z[i]; + z[i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static uint ShiftUpBits(int len, uint[] z, int zOff, int bits, uint c) + { + Debug.Assert(bits > 0 && bits < 32); + for (int i = 0; i < len; ++i) + { + uint next = z[zOff + i]; + z[zOff + i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static ulong ShiftUpBits64(int len, ulong[] z, int zOff, int bits, ulong c) + { + Debug.Assert(bits > 0 && bits < 64); + for (int i = 0; i < len; ++i) + { + ulong next = z[zOff + i]; + z[zOff + i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static uint ShiftUpBits(int len, uint[] x, int bits, uint c, uint[] z) + { + Debug.Assert(bits > 0 && bits < 32); + for (int i = 0; i < len; ++i) + { + uint next = x[i]; + z[i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static uint ShiftUpBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff) + { + Debug.Assert(bits > 0 && bits < 32); + for (int i = 0; i < len; ++i) + { + uint next = x[xOff + i]; + z[zOff + i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static ulong ShiftUpBits64(int len, ulong[] x, int xOff, int bits, ulong c, ulong[] z, int zOff) + { + Debug.Assert(bits > 0 && bits < 64); + for (int i = 0; i < len; ++i) + { + ulong next = x[xOff + i]; + z[zOff + i] = (next << bits) | (c >> -bits); + c = next; + } + return c >> -bits; + } + + public static void Square(int len, uint[] x, uint[] zz) + { + int extLen = len << 1; + uint c = 0; + int j = len, k = extLen; + do + { + ulong xVal = (ulong)x[--j]; + ulong p = xVal * xVal; + zz[--k] = (c << 31) | (uint)(p >> 33); + zz[--k] = (uint)(p >> 1); + c = (uint)p; + } + while (j > 0); + + for (int i = 1; i < len; ++i) + { + c = SquareWordAdd(x, i, zz); + AddWordAt(extLen, c, zz, i << 1); + } + + ShiftUpBit(extLen, zz, x[0] << 31); + } + + public static void Square(int len, uint[] x, int xOff, uint[] zz, int zzOff) + { + int extLen = len << 1; + uint c = 0; + int j = len, k = extLen; + do + { + ulong xVal = (ulong)x[xOff + --j]; + ulong p = xVal * xVal; + zz[zzOff + --k] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --k] = (uint)(p >> 1); + c = (uint)p; + } + while (j > 0); + + for (int i = 1; i < len; ++i) + { + c = SquareWordAdd(x, xOff, i, zz, zzOff); + AddWordAt(extLen, c, zz, zzOff, i << 1); + } + + ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31); + } + + public static uint SquareWordAdd(uint[] x, int xPos, uint[] z) + { + ulong c = 0, xVal = (ulong)x[xPos]; + int i = 0; + do + { + c += xVal * x[i] + z[xPos + i]; + z[xPos + i] = (uint)c; + c >>= 32; + } + while (++i < xPos); + return (uint)c; + } + + public static uint SquareWordAdd(uint[] x, int xOff, int xPos, uint[] z, int zOff) + { + ulong c = 0, xVal = (ulong)x[xOff + xPos]; + int i = 0; + do + { + c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M); + z[xPos + zOff] = (uint)c; + c >>= 32; + ++zOff; + } + while (++i < xPos); + return (uint)c; + } + + public static int Sub(int len, uint[] x, uint[] y, uint[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)x[i] - y[i]; + z[i] = (uint)c; + c >>= 32; + } + return (int)c; + } + + public static int Sub(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)x[xOff + i] - y[yOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + return (int)c; + } + public static int Sub33At(int len, uint x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + long c = (long)z[zPos + 0] - x; + z[zPos + 0] = (uint)c; + c >>= 32; + c += (long)z[zPos + 1] - 1; + z[zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zPos + 2); + } + + public static int Sub33At(int len, uint x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + long c = (long)z[zOff + zPos] - x; + z[zOff + zPos] = (uint)c; + c >>= 32; + c += (long)z[zOff + zPos + 1] - 1; + z[zOff + zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); + } + + public static int Sub33From(int len, uint x, uint[] z) + { + long c = (long)z[0] - x; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - 1; + z[1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, 2); + } + + public static int Sub33From(int len, uint x, uint[] z, int zOff) + { + long c = (long)z[zOff + 0] - x; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - 1; + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, 2); + } + + public static int SubBothFrom(int len, uint[] x, uint[] y, uint[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)z[i] - x[i] - y[i]; + z[i] = (uint)c; + c >>= 32; + } + return (int)c; + } + + public static int SubBothFrom(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)z[zOff + i] - x[xOff + i] - y[yOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + return (int)c; + } + + public static int SubDWordAt(int len, ulong x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + long c = (long)z[zPos + 0] - (long)(x & M); + z[zPos + 0] = (uint)c; + c >>= 32; + c += (long)z[zPos + 1] - (long)(x >> 32); + z[zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zPos + 2); + } + + public static int SubDWordAt(int len, ulong x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 2)); + long c = (long)z[zOff + zPos] - (long)(x & M); + z[zOff + zPos] = (uint)c; + c >>= 32; + c += (long)z[zOff + zPos + 1] - (long)(x >> 32); + z[zOff + zPos + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2); + } + + public static int SubDWordFrom(int len, ulong x, uint[] z) + { + long c = (long)z[0] - (long)(x & M); + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - (long)(x >> 32); + z[1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, 2); + } + + public static int SubDWordFrom(int len, ulong x, uint[] z, int zOff) + { + long c = (long)z[zOff + 0] - (long)(x & M); + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - (long)(x >> 32); + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, 2); + } + + public static int SubFrom(int len, uint[] x, uint[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)z[i] - x[i]; + z[i] = (uint)c; + c >>= 32; + } + return (int)c; + } + + public static int SubFrom(int len, uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (long)z[zOff + i] - x[xOff + i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + return (int)c; + } + + public static int SubWordAt(int len, uint x, uint[] z, int zPos) + { + Debug.Assert(zPos <= (len - 1)); + long c = (long)z[zPos] - x; + z[zPos] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zPos + 1); + } + + public static int SubWordAt(int len, uint x, uint[] z, int zOff, int zPos) + { + Debug.Assert(zPos <= (len - 1)); + long c = (long)z[zOff + zPos] - x; + z[zOff + zPos] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 1); + } + + public static int SubWordFrom(int len, uint x, uint[] z) + { + long c = (long)z[0] - x; + z[0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, 1); + } + + public static int SubWordFrom(int len, uint x, uint[] z, int zOff) + { + long c = (long)z[zOff + 0] - x; + z[zOff + 0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecAt(len, z, zOff, 1); + } + + public static BigInteger ToBigInteger(int len, uint[] x) + { + byte[] bs = new byte[len << 2]; + for (int i = 0; i < len; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (len - 1 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(int len, uint[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] = 0; + } + } + } +} diff --git a/crypto/src/math/raw/Nat128.cs b/crypto/src/math/raw/Nat128.cs new file mode 100644 index 000000000..819c52062 --- /dev/null +++ b/crypto/src/math/raw/Nat128.cs @@ -0,0 +1,856 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat128 + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) + { + ulong c = cIn; + c += (ulong)x[xOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) + { + ulong c = 0; + c += (ulong)u[uOff + 0] + v[vOff + 0]; + u[uOff + 0] = (uint)c; + v[vOff + 0] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 1] + v[vOff + 1]; + u[uOff + 1] = (uint)c; + v[vOff + 1] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 2] + v[vOff + 2]; + u[uOff + 2] = (uint)c; + v[vOff + 2] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 3] + v[vOff + 3]; + u[uOff + 3] = (uint)c; + v[vOff + 3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static void Copy(uint[] x, uint[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + } + + public static uint[] Create() + { + return new uint[4]; + } + + public static ulong[] Create64() + { + return new ulong[2]; + } + + public static uint[] CreateExt() + { + return new uint[8]; + } + + public static ulong[] CreateExt64() + { + return new ulong[4]; + } + + public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + bool pos = Gte(x, xOff, y, yOff); + if (pos) + { + Sub(x, xOff, y, yOff, z, zOff); + } + else + { + Sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static bool Eq(uint[] x, uint[] y) + { + for (int i = 3; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 1; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static uint[] FromBigInteger(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 128) + throw new ArgumentException(); + + uint[] z = Create(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 128) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + if ((bit & 127) != bit) + { + return 0; + } + int w = bit >> 5; + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(uint[] x, uint[] y) + { + for (int i = 3; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) + { + for (int i = 3; i >= 0; --i) + { + uint x_i = x[xOff + i], y_i = y[yOff + i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool IsOne(uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 4; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 2; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero(uint[] x) + { + for (int i = 0; i < 4; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 2; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + + { + ulong c = 0, x_0 = x[0]; + c += x_0 * y_0; + zz[0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[3] = (uint)c; + c >>= 32; + zz[4] = (uint)c; + } + + for (int i = 1; i < 4; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + zz[i + 4] = (uint)c; + } + } + + public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + + { + ulong c = 0, x_0 = x[xOff + 0]; + c += x_0 * y_0; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (uint)c; + c >>= 32; + zz[zzOff + 4] = (uint)c; + } + + for (int i = 1; i < 4; ++i) + { + ++zzOff; + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + zz[zzOff + 4] = (uint)c; + } + } + + public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + + ulong zc = 0; + for (int i = 0; i < 4; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += zc + zz[i + 4]; + zz[i + 4] = (uint)c; + zc = c >> 32; + } + return (uint)zc; + } + + public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + + ulong zc = 0; + for (int i = 0; i < 4; ++i) + { + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += zc + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + zc = c >> 32; + ++zzOff; + } + return (uint)zc; + } + + public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + Debug.Assert(w >> 31 == 0); + + ulong c = 0, wVal = w; + ulong x0 = x[xOff + 0]; + c += wVal * x0 + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong x1 = x[xOff + 1]; + c += wVal * x1 + x0 + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + ulong x2 = x[xOff + 2]; + c += wVal * x2 + x1 + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + ulong x3 = x[xOff + 3]; + c += wVal * x3 + x2 + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += x3; + return c; + } + + public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff) + { + Debug.Assert(yyOff <= 4); + Debug.Assert(zzOff <= 4); + + ulong c = 0, xVal = x; + c += xVal * yy[yyOff + 0] + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 1] + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 2] + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 3] + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 0); + ulong c = 0, xVal = x; + ulong y00 = y & M; + c += xVal * y00 + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong y01 = y >> 32; + c += xVal * y01 + y00 + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += y01 + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 1); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(4, z, zOff, 3); + } + + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 1); + ulong c = 0, xVal = x; + c += xVal * y + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(4, z, zOff, 3); + } + + public static uint MulWordsAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 2); + + ulong c = 0, xVal = x, yVal = y; + c += yVal * xVal + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(4, z, zOff, 2); + } + + public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + int i = 0; + do + { + c += xVal * y[i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < 4); + return (uint)c; + } + + public static void Square(uint[] x, uint[] zz) + { + ulong x_0 = x[0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 3, j = 8; + do + { + ulong xVal = x[i--]; + ulong p = xVal * xVal; + zz[--j] = (c << 31) | (uint)(p >> 33); + zz[--j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[1]; + ulong zz_2 = zz[2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[2]; + ulong zz_3 = zz[3]; + ulong zz_4 = zz[4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[3]; + ulong zz_5 = zz[5]; + ulong zz_6 = zz[6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_6 += zz_5 >> 32; + } + + w = (uint)zz_4; + zz[4] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_5; + zz[5] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_6; + zz[6] = (w << 1) | c; + c = w >> 31; + w = zz[7] + (uint)(zz_6 >> 32); + zz[7] = (w << 1) | c; + } + + public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) + { + ulong x_0 = x[xOff + 0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 3, j = 8; + do + { + ulong xVal = x[xOff + i--]; + ulong p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[zzOff + 0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[xOff + 1]; + ulong zz_2 = zz[zzOff + 2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[xOff + 2]; + ulong zz_3 = zz[zzOff + 3]; + ulong zz_4 = zz[zzOff + 4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[xOff + 3]; + ulong zz_5 = zz[zzOff + 5]; + ulong zz_6 = zz[zzOff + 6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_6 += zz_5 >> 32; + } + + w = (uint)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >> 31; + w = zz[zzOff + 7] + (uint)(zz_6 >> 32); + zz[zzOff + 7] = (w << 1) | c; + } + + public static int Sub(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + c += (long)x[xOff + 0] - y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)x[xOff + 1] - y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)x[xOff + 2] - y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)x[xOff + 3] - y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubBothFrom(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3]; + z[3] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + c += (long)z[zOff + 0] - x[xOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - x[xOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)z[zOff + 2] - x[xOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)z[zOff + 3] - x[xOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return (int)c; + } + + public static BigInteger ToBigInteger(uint[] x) + { + byte[] bs = new byte[16]; + for (int i = 0; i < 4; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (3 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[16]; + for (int i = 0; i < 2; ++i) + { + ulong x_i = x[i]; + if (x_i != 0UL) + { + Pack.UInt64_To_BE(x_i, bs, (1 - i) << 3); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(uint[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + } + } +} diff --git a/crypto/src/math/raw/Nat160.cs b/crypto/src/math/raw/Nat160.cs new file mode 100644 index 000000000..153ac0a43 --- /dev/null +++ b/crypto/src/math/raw/Nat160.cs @@ -0,0 +1,874 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat160 + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) + { + ulong c = cIn; + c += (ulong)x[xOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + z[zOff + 5]; + return (uint)c; + } + + public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) + { + ulong c = 0; + c += (ulong)u[uOff + 0] + v[vOff + 0]; + u[uOff + 0] = (uint)c; + v[vOff + 0] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 1] + v[vOff + 1]; + u[uOff + 1] = (uint)c; + v[vOff + 1] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 2] + v[vOff + 2]; + u[uOff + 2] = (uint)c; + v[vOff + 2] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 3] + v[vOff + 3]; + u[uOff + 3] = (uint)c; + v[vOff + 3] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 4] + v[vOff + 4]; + u[uOff + 4] = (uint)c; + v[vOff + 4] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static void Copy(uint[] x, uint[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + } + + public static uint[] Create() + { + return new uint[5]; + } + + public static uint[] CreateExt() + { + return new uint[10]; + } + + public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + bool pos = Gte(x, xOff, y, yOff); + if (pos) + { + Sub(x, xOff, y, yOff, z, zOff); + } + else + { + Sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static bool Eq(uint[] x, uint[] y) + { + for (int i = 4; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static uint[] FromBigInteger(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 160) + throw new ArgumentException(); + + uint[] z = Create(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= 5) + { + return 0; + } + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(uint[] x, uint[] y) + { + for (int i = 4; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) + { + for (int i = 4; i >= 0; --i) + { + uint x_i = x[xOff + i], y_i = y[yOff + i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool IsOne(uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 5; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero(uint[] x) + { + for (int i = 0; i < 5; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + + { + ulong c = 0, x_0 = x[0]; + c += x_0 * y_0; + zz[0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[4] = (uint)c; + c >>= 32; + zz[5] = (uint)c; + } + + for (int i = 1; i < 5; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + zz[i + 5] = (uint)c; + } + } + + public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + + { + ulong c = 0, x_0 = x[xOff + 0]; + c += x_0 * y_0; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (uint)c; + c >>= 32; + zz[zzOff + 5] = (uint)c; + } + + for (int i = 1; i < 5; ++i) + { + ++zzOff; + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + zz[zzOff + 5] = (uint)c; + } + } + + public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + + ulong zc = 0; + for (int i = 0; i < 5; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += zc + zz[i + 5]; + zz[i + 5] = (uint)c; + zc = c >> 32; + } + return (uint)zc; + } + + public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + + ulong zc = 0; + for (int i = 0; i < 5; ++i) + { + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += zc + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + zc = c >> 32; + ++zzOff; + } + return (uint)zc; + } + + public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + Debug.Assert(w >> 31 == 0); + + ulong c = 0, wVal = w; + ulong x0 = x[xOff + 0]; + c += wVal * x0 + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong x1 = x[xOff + 1]; + c += wVal * x1 + x0 + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + ulong x2 = x[xOff + 2]; + c += wVal * x2 + x1 + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + ulong x3 = x[xOff + 3]; + c += wVal * x3 + x2 + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + ulong x4 = x[xOff + 4]; + c += wVal * x4 + x3 + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += x4; + return c; + } + + public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff) + { + Debug.Assert(yyOff <= 5); + Debug.Assert(zzOff <= 5); + + ulong c = 0, xVal = x; + c += xVal * yy[yyOff + 0] + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 1] + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 2] + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 3] + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 4] + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 1); + ulong c = 0, xVal = x; + ulong y00 = y & M; + c += xVal * y00 + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong y01 = y >> 32; + c += xVal * y01 + y00 + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += y01 + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 4); + } + + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 2); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 3); + } + + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 2); + ulong c = 0, xVal = x; + c += xVal * y + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 3); + } + + public static uint MulWordsAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 3); + + ulong c = 0, xVal = x, yVal = y; + c += yVal * xVal + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(5, z, zOff, 2); + } + + public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + int i = 0; + do + { + c += xVal * y[i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < 5); + return (uint)c; + } + + public static void Square(uint[] x, uint[] zz) + { + ulong x_0 = x[0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 4, j = 10; + do + { + ulong xVal = x[i--]; + ulong p = xVal * xVal; + zz[--j] = (c << 31) | (uint)(p >> 33); + zz[--j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[1]; + ulong zz_2 = zz[2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[2]; + ulong zz_3 = zz[3]; + ulong zz_4 = zz[4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[3]; + ulong zz_5 = zz[5]; + ulong zz_6 = zz[6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[4]; + ulong zz_7 = zz[7]; + ulong zz_8 = zz[8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_8 += zz_7 >> 32; + } + + w = (uint)zz_5; + zz[5] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_6; + zz[6] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_7; + zz[7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[8] = (w << 1) | c; + c = w >> 31; + w = zz[9] + (uint)(zz_8 >> 32); + zz[9] = (w << 1) | c; + } + + public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) + { + ulong x_0 = x[xOff + 0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 4, j = 10; + do + { + ulong xVal = x[xOff + i--]; + ulong p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[zzOff + 0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[xOff + 1]; + ulong zz_2 = zz[zzOff + 2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[xOff + 2]; + ulong zz_3 = zz[zzOff + 3]; + ulong zz_4 = zz[zzOff + 4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[xOff + 3]; + ulong zz_5 = zz[zzOff + 5]; + ulong zz_6 = zz[zzOff + 6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[xOff + 4]; + ulong zz_7 = zz[zzOff + 7]; + ulong zz_8 = zz[zzOff + 8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_8 += zz_7 >> 32; + } + + w = (uint)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >> 31; + w = zz[zzOff + 9] + (uint)(zz_8 >> 32); + zz[zzOff + 9] = (w << 1) | c; + } + + public static int Sub(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + c += (long)x[xOff + 0] - y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)x[xOff + 1] - y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)x[xOff + 2] - y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)x[xOff + 3] - y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)x[xOff + 4] - y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubBothFrom(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4]; + z[4] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + c += (long)z[zOff + 0] - x[xOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - x[xOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)z[zOff + 2] - x[xOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)z[zOff + 3] - x[xOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)z[zOff + 4] - x[xOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + return (int)c; + } + + public static BigInteger ToBigInteger(uint[] x) + { + byte[] bs = new byte[20]; + for (int i = 0; i < 5; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (4 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(uint[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + } + } +} diff --git a/crypto/src/math/raw/Nat192.cs b/crypto/src/math/raw/Nat192.cs new file mode 100644 index 000000000..4797609ee --- /dev/null +++ b/crypto/src/math/raw/Nat192.cs @@ -0,0 +1,1048 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat192 + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5]; + z[5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) + { + ulong c = cIn; + c += (ulong)x[xOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) + { + ulong c = 0; + c += (ulong)u[uOff + 0] + v[vOff + 0]; + u[uOff + 0] = (uint)c; + v[vOff + 0] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 1] + v[vOff + 1]; + u[uOff + 1] = (uint)c; + v[vOff + 1] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 2] + v[vOff + 2]; + u[uOff + 2] = (uint)c; + v[vOff + 2] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 3] + v[vOff + 3]; + u[uOff + 3] = (uint)c; + v[vOff + 3] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 4] + v[vOff + 4]; + u[uOff + 4] = (uint)c; + v[vOff + 4] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 5] + v[vOff + 5]; + u[uOff + 5] = (uint)c; + v[vOff + 5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static void Copy(uint[] x, uint[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + } + + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + } + + public static uint[] Create() + { + return new uint[6]; + } + + public static ulong[] Create64() + { + return new ulong[3]; + } + + public static uint[] CreateExt() + { + return new uint[12]; + } + + public static ulong[] CreateExt64() + { + return new ulong[6]; + } + + public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + bool pos = Gte(x, xOff, y, yOff); + if (pos) + { + Sub(x, xOff, y, yOff, z, zOff); + } + else + { + Sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static bool Eq(uint[] x, uint[] y) + { + for (int i = 5; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 2; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static uint[] FromBigInteger(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 192) + throw new ArgumentException(); + + uint[] z = Create(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 192) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= 6) + { + return 0; + } + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(uint[] x, uint[] y) + { + for (int i = 5; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) + { + for (int i = 5; i >= 0; --i) + { + uint x_i = x[xOff + i], y_i = y[yOff + i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool IsOne(uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 6; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 3; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero(uint[] x) + { + for (int i = 0; i < 6; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 3; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + + { + ulong c = 0, x_0 = x[0]; + c += x_0 * y_0; + zz[0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[5] = (uint)c; + c >>= 32; + zz[6] = (uint)c; + } + + for (int i = 1; i < 6; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + zz[i + 6] = (uint)c; + } + } + + public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + + { + ulong c = 0, x_0 = x[xOff + 0]; + c += x_0 * y_0; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (uint)c; + c >>= 32; + zz[zzOff + 6] = (uint)c; + } + + for (int i = 1; i < 6; ++i) + { + ++zzOff; + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + zz[zzOff + 6] = (uint)c; + } + } + + public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + + ulong zc = 0; + for (int i = 0; i < 6; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + c += zc + zz[i + 6]; + zz[i + 6] = (uint)c; + zc = c >> 32; + } + return (uint)zc; + } + + public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + + ulong zc = 0; + for (int i = 0; i < 6; ++i) + { + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += zc + zz[zzOff + 6]; + zz[zzOff + 6] = (uint)c; + zc = c >> 32; + ++zzOff; + } + return (uint)zc; + } + + public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + Debug.Assert(w >> 31 == 0); + + ulong c = 0, wVal = w; + ulong x0 = x[xOff + 0]; + c += wVal * x0 + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong x1 = x[xOff + 1]; + c += wVal * x1 + x0 + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + ulong x2 = x[xOff + 2]; + c += wVal * x2 + x1 + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + ulong x3 = x[xOff + 3]; + c += wVal * x3 + x2 + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + ulong x4 = x[xOff + 4]; + c += wVal * x4 + x3 + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + ulong x5 = x[xOff + 5]; + c += wVal * x5 + x4 + y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += x5; + return c; + } + + public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff) + { + Debug.Assert(yyOff <= 6); + Debug.Assert(zzOff <= 6); + ulong c = 0, xVal = x; + c += xVal * yy[yyOff + 0] + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 1] + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 2] + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 3] + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 4] + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += xVal * yy[yyOff + 5] + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 2); + ulong c = 0, xVal = x; + ulong y00 = y & M; + c += xVal * y00 + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong y01 = y >> 32; + c += xVal * y01 + y00 + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += y01 + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 4); + } + + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <=3); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3); + } + + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 3); + ulong c = 0, xVal = x; + c += xVal * y + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3); + } + + public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + int i = 0; + do + { + c += xVal * y[i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < 6); + return (uint)c; + } + + public static void Square(uint[] x, uint[] zz) + { + ulong x_0 = x[0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 5, j = 12; + do + { + ulong xVal = x[i--]; + ulong p = xVal * xVal; + zz[--j] = (c << 31) | (uint)(p >> 33); + zz[--j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[1]; + ulong zz_2 = zz[2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[2]; + ulong zz_3 = zz[3]; + ulong zz_4 = zz[4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[3]; + ulong zz_5 = zz[5]; + ulong zz_6 = zz[6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[4]; + ulong zz_7 = zz[7]; + ulong zz_8 = zz[8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[5]; + ulong zz_9 = zz[9]; + ulong zz_10 = zz[10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_10 += zz_9 >> 32; + } + + w = (uint)zz_6; + zz[6] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_7; + zz[7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[10] = (w << 1) | c; + c = w >> 31; + w = zz[11] + (uint)(zz_10 >> 32); + zz[11] = (w << 1) | c; + } + + public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) + { + ulong x_0 = x[xOff + 0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 5, j = 12; + do + { + ulong xVal = x[xOff + i--]; + ulong p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[zzOff + 0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[xOff + 1]; + ulong zz_2 = zz[zzOff + 2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[xOff + 2]; + ulong zz_3 = zz[zzOff + 3]; + ulong zz_4 = zz[zzOff + 4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[xOff + 3]; + ulong zz_5 = zz[zzOff + 5]; + ulong zz_6 = zz[zzOff + 6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[xOff + 4]; + ulong zz_7 = zz[zzOff + 7]; + ulong zz_8 = zz[zzOff + 8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[xOff + 5]; + ulong zz_9 = zz[zzOff + 9]; + ulong zz_10 = zz[zzOff + 10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_10 += zz_9 >> 32; + } + + w = (uint)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >> 31; + w = zz[zzOff + 11] + (uint)(zz_10 >> 32); + zz[zzOff + 11] = (w << 1) | c; + } + + public static int Sub(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + c += (long)x[xOff + 0] - y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)x[xOff + 1] - y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)x[xOff + 2] - y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)x[xOff + 3] - y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)x[xOff + 4] - y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)x[xOff + 5] - y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubBothFrom(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5]; + z[5] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + c += (long)z[zOff + 0] - x[xOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - x[xOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)z[zOff + 2] - x[xOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)z[zOff + 3] - x[xOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)z[zOff + 4] - x[xOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)z[zOff + 5] - x[xOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + return (int)c; + } + + public static BigInteger ToBigInteger(uint[] x) + { + byte[] bs = new byte[24]; + for (int i = 0; i < 6; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (5 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[24]; + for (int i = 0; i < 3; ++i) + { + ulong x_i = x[i]; + if (x_i != 0L) + { + Pack.UInt64_To_BE(x_i, bs, (2 - i) << 3); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(uint[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + } + } +} diff --git a/crypto/src/math/raw/Nat224.cs b/crypto/src/math/raw/Nat224.cs new file mode 100644 index 000000000..940e930ac --- /dev/null +++ b/crypto/src/math/raw/Nat224.cs @@ -0,0 +1,1176 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat224 + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + y[6]; + z[6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0; + c += (ulong)x[xOff + 0] + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + y[6] + z[6]; + z[6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0; + c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + z[6]; + z[6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) + { + ulong c = cIn; + c += (ulong)x[xOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) + { + ulong c = 0; + c += (ulong)u[uOff + 0] + v[vOff + 0]; + u[uOff + 0] = (uint)c; + v[vOff + 0] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 1] + v[vOff + 1]; + u[uOff + 1] = (uint)c; + v[vOff + 1] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 2] + v[vOff + 2]; + u[uOff + 2] = (uint)c; + v[vOff + 2] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 3] + v[vOff + 3]; + u[uOff + 3] = (uint)c; + v[vOff + 3] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 4] + v[vOff + 4]; + u[uOff + 4] = (uint)c; + v[vOff + 4] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 5] + v[vOff + 5]; + u[uOff + 5] = (uint)c; + v[vOff + 5] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 6] + v[vOff + 6]; + u[uOff + 6] = (uint)c; + v[vOff + 6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static void Copy(uint[] x, uint[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + } + + public static uint[] Create() + { + return new uint[7]; + } + + public static uint[] CreateExt() + { + return new uint[14]; + } + + public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + bool pos = Gte(x, xOff, y, yOff); + if (pos) + { + Sub(x, xOff, y, yOff, z, zOff); + } + else + { + Sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static bool Eq(uint[] x, uint[] y) + { + for (int i = 6; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static uint[] FromBigInteger(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 224) + throw new ArgumentException(); + + uint[] z = Create(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= 7) + { + return 0; + } + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(uint[] x, uint[] y) + { + for (int i = 6; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) + { + for (int i = 6; i >= 0; --i) + { + uint x_i = x[xOff + i], y_i = y[yOff + i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool IsOne(uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 7; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero(uint[] x) + { + for (int i = 0; i < 7; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + ulong y_6 = y[6]; + + { + ulong c = 0, x_0 = x[0]; + c += x_0 * y_0; + zz[0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[5] = (uint)c; + c >>= 32; + c += x_0 * y_6; + zz[6] = (uint)c; + c >>= 32; + zz[7] = (uint)c; + } + + for (int i = 1; i < 7; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[i + 6]; + zz[i + 6] = (uint)c; + c >>= 32; + zz[i + 7] = (uint)c; + } + } + + public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + ulong y_6 = y[yOff + 6]; + + { + ulong c = 0, x_0 = x[xOff + 0]; + c += x_0 * y_0; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_0 * y_6; + zz[zzOff + 6] = (uint)c; + c >>= 32; + zz[zzOff + 7] = (uint)c; + } + + for (int i = 1; i < 7; ++i) + { + ++zzOff; + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[zzOff + 6]; + zz[zzOff + 6] = (uint)c; + c >>= 32; + zz[zzOff + 7] = (uint)c; + } + } + + public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + ulong y_6 = y[6]; + + ulong zc = 0; + for (int i = 0; i < 7; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[i + 6]; + zz[i + 6] = (uint)c; + c >>= 32; + c += zc + zz[i + 7]; + zz[i + 7] = (uint)c; + zc = c >> 32; + } + return (uint)zc; + } + + public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + ulong y_6 = y[yOff + 6]; + + ulong zc = 0; + for (int i = 0; i < 7; ++i) + { + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[zzOff + 6]; + zz[zzOff + 6] = (uint)c; + c >>= 32; + c += zc + zz[zzOff + 7]; + zz[zzOff + 7] = (uint)c; + zc = c >> 32; + ++zzOff; + } + return (uint)zc; + } + + public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + Debug.Assert(w >> 31 == 0); + + ulong c = 0, wVal = w; + ulong x0 = x[xOff + 0]; + c += wVal * x0 + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong x1 = x[xOff + 1]; + c += wVal * x1 + x0 + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + ulong x2 = x[xOff + 2]; + c += wVal * x2 + x1 + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + ulong x3 = x[xOff + 3]; + c += wVal * x3 + x2 + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + ulong x4 = x[xOff + 4]; + c += wVal * x4 + x3 + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + ulong x5 = x[xOff + 5]; + c += wVal * x5 + x4 + y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + ulong x6 = x[xOff + 6]; + c += wVal * x6 + x5 + y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += x6; + return c; + } + + public static uint MulByWord(uint x, uint[] z) + { + ulong c = 0, xVal = x; + c += xVal * (ulong)z[0]; + z[0] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[1]; + z[1] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[2]; + z[2] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[3]; + z[3] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[4]; + z[4] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[5]; + z[5] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[6]; + z[6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint MulByWordAddTo(uint x, uint[] y, uint[] z) + { + ulong c = 0, xVal = x; + c += xVal * (ulong)z[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[5] + y[5]; + z[5] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[6] + y[6]; + z[6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + c += xVal * y[yOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 3); + ulong c = 0, xVal = x; + ulong y00 = y & M; + c += xVal * y00 + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong y01 = y >> 32; + c += xVal * y01 + y00 + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += y01 + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 4); + } + + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 4); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3); + } + + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 4); + ulong c = 0, xVal = x; + c += xVal * y + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3); + } + + public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + int i = 0; + do + { + c += xVal * y[i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < 7); + return (uint)c; + } + + public static void Square(uint[] x, uint[] zz) + { + ulong x_0 = x[0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 6, j = 14; + do + { + ulong xVal = x[i--]; + ulong p = xVal * xVal; + zz[--j] = (c << 31) | (uint)(p >> 33); + zz[--j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[1]; + ulong zz_2 = zz[2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[2]; + ulong zz_3 = zz[3]; + ulong zz_4 = zz[4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[3]; + ulong zz_5 = zz[5]; + ulong zz_6 = zz[6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[4]; + ulong zz_7 = zz[7]; + ulong zz_8 = zz[8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[5]; + ulong zz_9 = zz[9]; + ulong zz_10 = zz[10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >> 32; + zz_9 &= M; + } + + ulong x_6 = x[6]; + ulong zz_11 = zz[11]; + ulong zz_12 = zz[12]; + { + zz_6 += x_6 * x_0; + w = (uint)zz_6; + zz[6] = (w << 1) | c; + c = w >> 31; + zz_7 += (zz_6 >> 32) + x_6 * x_1; + zz_8 += (zz_7 >> 32) + x_6 * x_2; + zz_9 += (zz_8 >> 32) + x_6 * x_3; + zz_10 += (zz_9 >> 32) + x_6 * x_4; + zz_11 += (zz_10 >> 32) + x_6 * x_5; + zz_12 += zz_11 >> 32; + } + + w = (uint)zz_7; + zz[7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[10] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_11; + zz[11] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_12; + zz[12] = (w << 1) | c; + c = w >> 31; + w = zz[13] + (uint)(zz_12 >> 32); + zz[13] = (w << 1) | c; + } + + public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) + { + ulong x_0 = x[xOff + 0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 6, j = 14; + do + { + ulong xVal = x[xOff + i--]; + ulong p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[zzOff + 0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[xOff + 1]; + ulong zz_2 = zz[zzOff + 2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[xOff + 2]; + ulong zz_3 = zz[zzOff + 3]; + ulong zz_4 = zz[zzOff + 4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[xOff + 3]; + ulong zz_5 = zz[zzOff + 5]; + ulong zz_6 = zz[zzOff + 6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[xOff + 4]; + ulong zz_7 = zz[zzOff + 7]; + ulong zz_8 = zz[zzOff + 8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[xOff + 5]; + ulong zz_9 = zz[zzOff + 9]; + ulong zz_10 = zz[zzOff + 10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >> 32; + zz_9 &= M; + } + + ulong x_6 = x[xOff + 6]; + ulong zz_11 = zz[zzOff + 11]; + ulong zz_12 = zz[zzOff + 12]; + { + zz_6 += x_6 * x_0; + w = (uint)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >> 31; + zz_7 += (zz_6 >> 32) + x_6 * x_1; + zz_8 += (zz_7 >> 32) + x_6 * x_2; + zz_9 += (zz_8 >> 32) + x_6 * x_3; + zz_10 += (zz_9 >> 32) + x_6 * x_4; + zz_11 += (zz_10 >> 32) + x_6 * x_5; + zz_12 += zz_11 >> 32; + } + + w = (uint)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_11; + zz[zzOff + 11] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_12; + zz[zzOff + 12] = (w << 1) | c; + c = w >> 31; + w = zz[zzOff + 13] + (uint)(zz_12 >> 32); + zz[zzOff + 13] = (w << 1) | c; + } + + public static int Sub(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)x[6] - y[6]; + z[6] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + c += (long)x[xOff + 0] - y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)x[xOff + 1] - y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)x[xOff + 2] - y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)x[xOff + 3] - y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)x[xOff + 4] - y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)x[xOff + 5] - y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (long)x[xOff + 6] - y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubBothFrom(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6] - x[6] - y[6]; + z[6] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6] - x[6]; + z[6] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + c += (long)z[zOff + 0] - x[xOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - x[xOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)z[zOff + 2] - x[xOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)z[zOff + 3] - x[xOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)z[zOff + 4] - x[xOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)z[zOff + 5] - x[xOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (long)z[zOff + 6] - x[xOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + return (int)c; + } + + public static BigInteger ToBigInteger(uint[] x) + { + byte[] bs = new byte[28]; + for (int i = 0; i < 7; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (6 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(uint[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + z[6] = 0; + } + } +} diff --git a/crypto/src/math/raw/Nat256.cs b/crypto/src/math/raw/Nat256.cs new file mode 100644 index 000000000..19455031a --- /dev/null +++ b/crypto/src/math/raw/Nat256.cs @@ -0,0 +1,1387 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat256 + { + private const ulong M = 0xFFFFFFFFUL; + + public static uint Add(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + y[6]; + z[6] = (uint)c; + c >>= 32; + c += (ulong)x[7] + y[7]; + z[7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0; + c += (ulong)x[xOff + 0] + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 7] + y[yOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, uint[] y, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + y[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + y[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + y[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + y[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + y[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + y[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + y[6] + z[6]; + z[6] = (uint)c; + c >>= 32; + c += (ulong)x[7] + y[7] + z[7]; + z[7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0; + c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 7] + y[yOff + 7] + z[zOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, uint[] z) + { + ulong c = 0; + c += (ulong)x[0] + z[0]; + z[0] = (uint)c; + c >>= 32; + c += (ulong)x[1] + z[1]; + z[1] = (uint)c; + c >>= 32; + c += (ulong)x[2] + z[2]; + z[2] = (uint)c; + c >>= 32; + c += (ulong)x[3] + z[3]; + z[3] = (uint)c; + c >>= 32; + c += (ulong)x[4] + z[4]; + z[4] = (uint)c; + c >>= 32; + c += (ulong)x[5] + z[5]; + z[5] = (uint)c; + c >>= 32; + c += (ulong)x[6] + z[6]; + z[6] = (uint)c; + c >>= 32; + c += (ulong)x[7] + z[7]; + z[7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn) + { + ulong c = cIn; + c += (ulong)x[xOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += (ulong)x[xOff + 7] + z[zOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff) + { + ulong c = 0; + c += (ulong)u[uOff + 0] + v[vOff + 0]; + u[uOff + 0] = (uint)c; + v[vOff + 0] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 1] + v[vOff + 1]; + u[uOff + 1] = (uint)c; + v[vOff + 1] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 2] + v[vOff + 2]; + u[uOff + 2] = (uint)c; + v[vOff + 2] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 3] + v[vOff + 3]; + u[uOff + 3] = (uint)c; + v[vOff + 3] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 4] + v[vOff + 4]; + u[uOff + 4] = (uint)c; + v[vOff + 4] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 5] + v[vOff + 5]; + u[uOff + 5] = (uint)c; + v[vOff + 5] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 6] + v[vOff + 6]; + u[uOff + 6] = (uint)c; + v[vOff + 6] = (uint)c; + c >>= 32; + c += (ulong)u[uOff + 7] + v[vOff + 7]; + u[uOff + 7] = (uint)c; + v[vOff + 7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static void Copy(uint[] x, uint[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + z[7] = x[7]; + } + + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + + public static uint[] Create() + { + return new uint[8]; + } + + public static ulong[] Create64() + { + return new ulong[4]; + } + + public static uint[] CreateExt() + { + return new uint[16]; + } + + public static ulong[] CreateExt64() + { + return new ulong[8]; + } + + public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + bool pos = Gte(x, xOff, y, yOff); + if (pos) + { + Sub(x, xOff, y, yOff, z, zOff); + } + else + { + Sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static bool Eq(uint[] x, uint[] y) + { + for (int i = 7; i >= 0; --i) + { + if (x[i] != y[i]) + return false; + } + return true; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 3; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static uint[] FromBigInteger(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 256) + throw new ArgumentException(); + + uint[] z = Create(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (uint)x.IntValue; + x = x.ShiftRight(32); + } + return z; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 256) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static uint GetBit(uint[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + if ((bit & 255) != bit) + { + return 0; + } + int w = bit >> 5; + int b = bit & 31; + return (x[w] >> b) & 1; + } + + public static bool Gte(uint[] x, uint[] y) + { + for (int i = 7; i >= 0; --i) + { + uint x_i = x[i], y_i = y[i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool Gte(uint[] x, int xOff, uint[] y, int yOff) + { + for (int i = 7; i >= 0; --i) + { + uint x_i = x[xOff + i], y_i = y[yOff + i]; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static bool IsOne(uint[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 8; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 4; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero(uint[] x) + { + for (int i = 0; i < 8; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 4; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + ulong y_6 = y[6]; + ulong y_7 = y[7]; + + { + ulong c = 0, x_0 = x[0]; + c += x_0 * y_0; + zz[0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[5] = (uint)c; + c >>= 32; + c += x_0 * y_6; + zz[6] = (uint)c; + c >>= 32; + c += x_0 * y_7; + zz[7] = (uint)c; + c >>= 32; + zz[8] = (uint)c; + } + + for (int i = 1; i < 8; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[i + 6]; + zz[i + 6] = (uint)c; + c >>= 32; + c += x_i * y_7 + zz[i + 7]; + zz[i + 7] = (uint)c; + c >>= 32; + zz[i + 8] = (uint)c; + } + } + + public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + ulong y_6 = y[yOff + 6]; + ulong y_7 = y[yOff + 7]; + + { + ulong c = 0, x_0 = x[xOff + 0]; + c += x_0 * y_0; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_0 * y_6; + zz[zzOff + 6] = (uint)c; + c >>= 32; + c += x_0 * y_7; + zz[zzOff + 7] = (uint)c; + c >>= 32; + zz[zzOff + 8] = (uint)c; + } + + for (int i = 1; i < 8; ++i) + { + ++zzOff; + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[zzOff + 6]; + zz[zzOff + 6] = (uint)c; + c >>= 32; + c += x_i * y_7 + zz[zzOff + 7]; + zz[zzOff + 7] = (uint)c; + c >>= 32; + zz[zzOff + 8] = (uint)c; + } + } + + public static uint MulAddTo(uint[] x, uint[] y, uint[] zz) + { + ulong y_0 = y[0]; + ulong y_1 = y[1]; + ulong y_2 = y[2]; + ulong y_3 = y[3]; + ulong y_4 = y[4]; + ulong y_5 = y[5]; + ulong y_6 = y[6]; + ulong y_7 = y[7]; + + ulong zc = 0; + for (int i = 0; i < 8; ++i) + { + ulong c = 0, x_i = x[i]; + c += x_i * y_0 + zz[i + 0]; + zz[i + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[i + 1]; + zz[i + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[i + 2]; + zz[i + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[i + 3]; + zz[i + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[i + 4]; + zz[i + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[i + 5]; + zz[i + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[i + 6]; + zz[i + 6] = (uint)c; + c >>= 32; + c += x_i * y_7 + zz[i + 7]; + zz[i + 7] = (uint)c; + c >>= 32; + c += zc + zz[i + 8]; + zz[i + 8] = (uint)c; + zc = c >> 32; + } + return (uint)zc; + } + + public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff) + { + ulong y_0 = y[yOff + 0]; + ulong y_1 = y[yOff + 1]; + ulong y_2 = y[yOff + 2]; + ulong y_3 = y[yOff + 3]; + ulong y_4 = y[yOff + 4]; + ulong y_5 = y[yOff + 5]; + ulong y_6 = y[yOff + 6]; + ulong y_7 = y[yOff + 7]; + + ulong zc = 0; + for (int i = 0; i < 8; ++i) + { + ulong c = 0, x_i = x[xOff + i]; + c += x_i * y_0 + zz[zzOff + 0]; + zz[zzOff + 0] = (uint)c; + c >>= 32; + c += x_i * y_1 + zz[zzOff + 1]; + zz[zzOff + 1] = (uint)c; + c >>= 32; + c += x_i * y_2 + zz[zzOff + 2]; + zz[zzOff + 2] = (uint)c; + c >>= 32; + c += x_i * y_3 + zz[zzOff + 3]; + zz[zzOff + 3] = (uint)c; + c >>= 32; + c += x_i * y_4 + zz[zzOff + 4]; + zz[zzOff + 4] = (uint)c; + c >>= 32; + c += x_i * y_5 + zz[zzOff + 5]; + zz[zzOff + 5] = (uint)c; + c >>= 32; + c += x_i * y_6 + zz[zzOff + 6]; + zz[zzOff + 6] = (uint)c; + c >>= 32; + c += x_i * y_7 + zz[zzOff + 7]; + zz[zzOff + 7] = (uint)c; + c >>= 32; + c += zc + zz[zzOff + 8]; + zz[zzOff + 8] = (uint)c; + zc = c >> 32; + ++zzOff; + } + return (uint)zc; + } + + public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + Debug.Assert(w >> 31 == 0); + + ulong c = 0, wVal = w; + ulong x0 = x[xOff + 0]; + c += wVal * x0 + y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong x1 = x[xOff + 1]; + c += wVal * x1 + x0 + y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + ulong x2 = x[xOff + 2]; + c += wVal * x2 + x1 + y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + ulong x3 = x[xOff + 3]; + c += wVal * x3 + x2 + y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + ulong x4 = x[xOff + 4]; + c += wVal * x4 + x3 + y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + ulong x5 = x[xOff + 5]; + c += wVal * x5 + x4 + y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + ulong x6 = x[xOff + 6]; + c += wVal * x6 + x5 + y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + ulong x7 = x[xOff + 7]; + c += wVal * x7 + x6 + y[yOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + c += x7; + return c; + } + + public static uint MulByWord(uint x, uint[] z) + { + ulong c = 0, xVal = x; + c += xVal * (ulong)z[0]; + z[0] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[1]; + z[1] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[2]; + z[2] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[3]; + z[3] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[4]; + z[4] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[5]; + z[5] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[6]; + z[6] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[7]; + z[7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint MulByWordAddTo(uint x, uint[] y, uint[] z) + { + ulong c = 0, xVal = x; + c += xVal * (ulong)z[0] + y[0]; + z[0] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[1] + y[1]; + z[1] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[2] + y[2]; + z[2] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[3] + y[3]; + z[3] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[4] + y[4]; + z[4] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[5] + y[5]; + z[5] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[6] + y[6]; + z[6] = (uint)c; + c >>= 32; + c += xVal * (ulong)z[7] + y[7]; + z[7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + c += xVal * y[yOff + 0] + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 1] + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 2] + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 3] + z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 4] + z[zOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 5] + z[zOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 6] + z[zOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += xVal * y[yOff + 7] + z[zOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (uint)c; + } + + public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 4); + ulong c = 0, xVal = x; + ulong y00 = y & M; + c += xVal * y00 + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + ulong y01 = y >> 32; + c += xVal * y01 + y00 + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += y01 + z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += z[zOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 4); + } + + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 5); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3); + } + + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) + { + Debug.Assert(zOff <= 5); + ulong c = 0, xVal = x; + c += xVal * y + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += xVal * (y >> 32) + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3); + } + + public static uint MulWord(uint x, uint[] y, uint[] z, int zOff) + { + ulong c = 0, xVal = x; + int i = 0; + do + { + c += xVal * y[i]; + z[zOff + i] = (uint)c; + c >>= 32; + } + while (++i < 8); + return (uint)c; + } + + public static void Square(uint[] x, uint[] zz) + { + ulong x_0 = x[0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 7, j = 16; + do + { + ulong xVal = x[i--]; + ulong p = xVal * xVal; + zz[--j] = (c << 31) | (uint)(p >> 33); + zz[--j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[1]; + ulong zz_2 = zz[2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[2]; + ulong zz_3 = zz[3]; + ulong zz_4 = zz[4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[3]; + ulong zz_5 = zz[5]; + ulong zz_6 = zz[6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[4]; + ulong zz_7 = zz[7]; + ulong zz_8 = zz[8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[5]; + ulong zz_9 = zz[9]; + ulong zz_10 = zz[10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >> 32; + zz_9 &= M; + } + + ulong x_6 = x[6]; + ulong zz_11 = zz[11]; + ulong zz_12 = zz[12]; + { + zz_6 += x_6 * x_0; + w = (uint)zz_6; + zz[6] = (w << 1) | c; + c = w >> 31; + zz_7 += (zz_6 >> 32) + x_6 * x_1; + zz_8 += (zz_7 >> 32) + x_6 * x_2; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_6 * x_3; + zz_8 &= M; + zz_10 += (zz_9 >> 32) + x_6 * x_4; + zz_9 &= M; + zz_11 += (zz_10 >> 32) + x_6 * x_5; + zz_10 &= M; + zz_12 += zz_11 >> 32; + zz_11 &= M; + } + + ulong x_7 = x[7]; + ulong zz_13 = zz[13]; + ulong zz_14 = zz[14]; + { + zz_7 += x_7 * x_0; + w = (uint)zz_7; + zz[7] = (w << 1) | c; + c = w >> 31; + zz_8 += (zz_7 >> 32) + x_7 * x_1; + zz_9 += (zz_8 >> 32) + x_7 * x_2; + zz_10 += (zz_9 >> 32) + x_7 * x_3; + zz_11 += (zz_10 >> 32) + x_7 * x_4; + zz_12 += (zz_11 >> 32) + x_7 * x_5; + zz_13 += (zz_12 >> 32) + x_7 * x_6; + zz_14 += zz_13 >> 32; + } + + w = (uint)zz_8; + zz[8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[10] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_11; + zz[11] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_12; + zz[12] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_13; + zz[13] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_14; + zz[14] = (w << 1) | c; + c = w >> 31; + w = zz[15] + (uint)(zz_14 >> 32); + zz[15] = (w << 1) | c; + } + + public static void Square(uint[] x, int xOff, uint[] zz, int zzOff) + { + ulong x_0 = x[xOff + 0]; + ulong zz_1; + + uint c = 0, w; + { + int i = 7, j = 16; + do + { + ulong xVal = x[xOff + i--]; + ulong p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (uint)(p >> 33); + zz[zzOff + --j] = (uint)(p >> 1); + c = (uint)p; + } + while (i > 0); + + { + ulong p = x_0 * x_0; + zz_1 = (ulong)(c << 31) | (p >> 33); + zz[zzOff + 0] = (uint)p; + c = (uint)(p >> 32) & 1; + } + } + + ulong x_1 = x[xOff + 1]; + ulong zz_2 = zz[zzOff + 2]; + + { + zz_1 += x_1 * x_0; + w = (uint)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >> 31; + zz_2 += zz_1 >> 32; + } + + ulong x_2 = x[xOff + 2]; + ulong zz_3 = zz[zzOff + 3]; + ulong zz_4 = zz[zzOff + 4]; + { + zz_2 += x_2 * x_0; + w = (uint)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >> 31; + zz_3 += (zz_2 >> 32) + x_2 * x_1; + zz_4 += zz_3 >> 32; + zz_3 &= M; + } + + ulong x_3 = x[xOff + 3]; + ulong zz_5 = zz[zzOff + 5]; + ulong zz_6 = zz[zzOff + 6]; + { + zz_3 += x_3 * x_0; + w = (uint)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >> 31; + zz_4 += (zz_3 >> 32) + x_3 * x_1; + zz_5 += (zz_4 >> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >> 32; + zz_5 &= M; + } + + ulong x_4 = x[xOff + 4]; + ulong zz_7 = zz[zzOff + 7]; + ulong zz_8 = zz[zzOff + 8]; + { + zz_4 += x_4 * x_0; + w = (uint)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >> 31; + zz_5 += (zz_4 >> 32) + x_4 * x_1; + zz_6 += (zz_5 >> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >> 32; + zz_7 &= M; + } + + ulong x_5 = x[xOff + 5]; + ulong zz_9 = zz[zzOff + 9]; + ulong zz_10 = zz[zzOff + 10]; + { + zz_5 += x_5 * x_0; + w = (uint)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >> 31; + zz_6 += (zz_5 >> 32) + x_5 * x_1; + zz_7 += (zz_6 >> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >> 32; + zz_9 &= M; + } + + ulong x_6 = x[xOff + 6]; + ulong zz_11 = zz[zzOff + 11]; + ulong zz_12 = zz[zzOff + 12]; + { + zz_6 += x_6 * x_0; + w = (uint)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >> 31; + zz_7 += (zz_6 >> 32) + x_6 * x_1; + zz_8 += (zz_7 >> 32) + x_6 * x_2; + zz_7 &= M; + zz_9 += (zz_8 >> 32) + x_6 * x_3; + zz_8 &= M; + zz_10 += (zz_9 >> 32) + x_6 * x_4; + zz_9 &= M; + zz_11 += (zz_10 >> 32) + x_6 * x_5; + zz_10 &= M; + zz_12 += zz_11 >> 32; + zz_11 &= M; + } + + ulong x_7 = x[xOff + 7]; + ulong zz_13 = zz[zzOff + 13]; + ulong zz_14 = zz[zzOff + 14]; + { + zz_7 += x_7 * x_0; + w = (uint)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >> 31; + zz_8 += (zz_7 >> 32) + x_7 * x_1; + zz_9 += (zz_8 >> 32) + x_7 * x_2; + zz_10 += (zz_9 >> 32) + x_7 * x_3; + zz_11 += (zz_10 >> 32) + x_7 * x_4; + zz_12 += (zz_11 >> 32) + x_7 * x_5; + zz_13 += (zz_12 >> 32) + x_7 * x_6; + zz_14 += zz_13 >> 32; + } + + w = (uint)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_11; + zz[zzOff + 11] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_12; + zz[zzOff + 12] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_13; + zz[zzOff + 13] = (w << 1) | c; + c = w >> 31; + w = (uint)zz_14; + zz[zzOff + 14] = (w << 1) | c; + c = w >> 31; + w = zz[zzOff + 15] + (uint)(zz_14 >> 32); + zz[zzOff + 15] = (w << 1) | c; + } + + public static int Sub(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)x[6] - y[6]; + z[6] = (uint)c; + c >>= 32; + c += (long)x[7] - y[7]; + z[7] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + long c = 0; + c += (long)x[xOff + 0] - y[yOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)x[xOff + 1] - y[yOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)x[xOff + 2] - y[yOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)x[xOff + 3] - y[yOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)x[xOff + 4] - y[yOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)x[xOff + 5] - y[yOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (long)x[xOff + 6] - y[yOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += (long)x[xOff + 7] - y[yOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubBothFrom(uint[] x, uint[] y, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0] - y[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1] - y[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2] - y[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3] - y[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4] - y[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5] - y[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6] - x[6] - y[6]; + z[6] = (uint)c; + c >>= 32; + c += (long)z[7] - x[7] - y[7]; + z[7] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, uint[] z) + { + long c = 0; + c += (long)z[0] - x[0]; + z[0] = (uint)c; + c >>= 32; + c += (long)z[1] - x[1]; + z[1] = (uint)c; + c >>= 32; + c += (long)z[2] - x[2]; + z[2] = (uint)c; + c >>= 32; + c += (long)z[3] - x[3]; + z[3] = (uint)c; + c >>= 32; + c += (long)z[4] - x[4]; + z[4] = (uint)c; + c >>= 32; + c += (long)z[5] - x[5]; + z[5] = (uint)c; + c >>= 32; + c += (long)z[6] - x[6]; + z[6] = (uint)c; + c >>= 32; + c += (long)z[7] - x[7]; + z[7] = (uint)c; + c >>= 32; + return (int)c; + } + + public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff) + { + long c = 0; + c += (long)z[zOff + 0] - x[xOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += (long)z[zOff + 1] - x[xOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += (long)z[zOff + 2] - x[xOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + c += (long)z[zOff + 3] - x[xOff + 3]; + z[zOff + 3] = (uint)c; + c >>= 32; + c += (long)z[zOff + 4] - x[xOff + 4]; + z[zOff + 4] = (uint)c; + c >>= 32; + c += (long)z[zOff + 5] - x[xOff + 5]; + z[zOff + 5] = (uint)c; + c >>= 32; + c += (long)z[zOff + 6] - x[xOff + 6]; + z[zOff + 6] = (uint)c; + c >>= 32; + c += (long)z[zOff + 7] - x[xOff + 7]; + z[zOff + 7] = (uint)c; + c >>= 32; + return (int)c; + } + + public static BigInteger ToBigInteger(uint[] x) + { + byte[] bs = new byte[32]; + for (int i = 0; i < 8; ++i) + { + uint x_i = x[i]; + if (x_i != 0) + { + Pack.UInt32_To_BE(x_i, bs, (7 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[32]; + for (int i = 0; i < 4; ++i) + { + ulong x_i = x[i]; + if (x_i != 0L) + { + Pack.UInt64_To_BE(x_i, bs, (3 - i) << 3); + } + } + return new BigInteger(1, bs); + } + + public static void Zero(uint[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + z[6] = 0; + z[7] = 0; + } + } +} diff --git a/crypto/src/math/raw/Nat320.cs b/crypto/src/math/raw/Nat320.cs new file mode 100644 index 000000000..c7daa71e2 --- /dev/null +++ b/crypto/src/math/raw/Nat320.cs @@ -0,0 +1,98 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat320 + { + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + } + + public static ulong[] Create64() + { + return new ulong[5]; + } + + public static ulong[] CreateExt64() + { + return new ulong[10]; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 4; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 320) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 5; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 5; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[40]; + for (int i = 0; i < 5; ++i) + { + ulong x_i = x[i]; + if (x_i != 0L) + { + Pack.UInt64_To_BE(x_i, bs, (4 - i) << 3); + } + } + return new BigInteger(1, bs); + } + } +} diff --git a/crypto/src/math/raw/Nat384.cs b/crypto/src/math/raw/Nat384.cs new file mode 100644 index 000000000..ed1c47e8c --- /dev/null +++ b/crypto/src/math/raw/Nat384.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat384 + { + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + Nat192.Mul(x, y, zz); + Nat192.Mul(x, 6, y, 6, zz, 12); + + uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12); + uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0); + c18 += Nat192.AddTo(zz, 18, zz, 12, c12); + + uint[] dx = Nat192.Create(), dy = Nat192.Create(); + bool neg = Nat192.Diff(x, 6, x, 0, dx, 0) != Nat192.Diff(y, 6, y, 0, dy, 0); + + uint[] tt = Nat192.CreateExt(); + Nat192.Mul(dx, dy, tt); + + c18 += neg ? Nat.AddTo(12, tt, 0, zz, 6) : (uint)Nat.SubFrom(12, tt, 0, zz, 6); + Nat.AddWordAt(24, c18, zz, 18); + } + + public static void Square(uint[] x, uint[] zz) + { + Nat192.Square(x, zz); + Nat192.Square(x, 6, zz, 12); + + uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12); + uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0); + c18 += Nat192.AddTo(zz, 18, zz, 12, c12); + + uint[] dx = Nat192.Create(); + Nat192.Diff(x, 6, x, 0, dx, 0); + + uint[] m = Nat192.CreateExt(); + Nat192.Square(dx, m); + + c18 += (uint)Nat.SubFrom(12, m, 0, zz, 6); + Nat.AddWordAt(24, c18, zz, 18); + } + } +} diff --git a/crypto/src/math/raw/Nat448.cs b/crypto/src/math/raw/Nat448.cs new file mode 100644 index 000000000..52a253f1b --- /dev/null +++ b/crypto/src/math/raw/Nat448.cs @@ -0,0 +1,100 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat448 + { + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + } + + public static ulong[] Create64() + { + return new ulong[7]; + } + + public static ulong[] CreateExt64() + { + return new ulong[14]; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 6; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 448) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 7; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 7; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[56]; + for (int i = 0; i < 7; ++i) + { + ulong x_i = x[i]; + if (x_i != 0L) + { + Pack.UInt64_To_BE(x_i, bs, (6 - i) << 3); + } + } + return new BigInteger(1, bs); + } + } +} diff --git a/crypto/src/math/raw/Nat512.cs b/crypto/src/math/raw/Nat512.cs new file mode 100644 index 000000000..a9ef2b3b6 --- /dev/null +++ b/crypto/src/math/raw/Nat512.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat512 + { + public static void Mul(uint[] x, uint[] y, uint[] zz) + { + Nat256.Mul(x, y, zz); + Nat256.Mul(x, 8, y, 8, zz, 16); + + uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16); + uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0); + c24 += Nat256.AddTo(zz, 24, zz, 16, c16); + + uint[] dx = Nat256.Create(), dy = Nat256.Create(); + bool neg = Nat256.Diff(x, 8, x, 0, dx, 0) != Nat256.Diff(y, 8, y, 0, dy, 0); + + uint[] tt = Nat256.CreateExt(); + Nat256.Mul(dx, dy, tt); + + c24 += neg ? Nat.AddTo(16, tt, 0, zz, 8) : (uint)Nat.SubFrom(16, tt, 0, zz, 8); + Nat.AddWordAt(32, c24, zz, 24); + } + + public static void Square(uint[] x, uint[] zz) + { + Nat256.Square(x, zz); + Nat256.Square(x, 8, zz, 16); + + uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16); + uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0); + c24 += Nat256.AddTo(zz, 24, zz, 16, c16); + + uint[] dx = Nat256.Create(); + Nat256.Diff(x, 8, x, 0, dx, 0); + + uint[] m = Nat256.CreateExt(); + Nat256.Square(dx, m); + + c24 += (uint)Nat.SubFrom(16, m, 0, zz, 8); + Nat.AddWordAt(32, c24, zz, 24); + } + } +} diff --git a/crypto/src/math/raw/Nat576.cs b/crypto/src/math/raw/Nat576.cs new file mode 100644 index 000000000..813fb86be --- /dev/null +++ b/crypto/src/math/raw/Nat576.cs @@ -0,0 +1,102 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Math.Raw +{ + internal abstract class Nat576 + { + public static void Copy64(ulong[] x, ulong[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + z[7] = x[7]; + z[8] = x[8]; + } + + public static ulong[] Create64() + { + return new ulong[9]; + } + + public static ulong[] CreateExt64() + { + return new ulong[18]; + } + + public static bool Eq64(ulong[] x, ulong[] y) + { + for (int i = 8; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static ulong[] FromBigInteger64(BigInteger x) + { + if (x.SignValue < 0 || x.BitLength > 576) + throw new ArgumentException(); + + ulong[] z = Create64(); + int i = 0; + while (x.SignValue != 0) + { + z[i++] = (ulong)x.LongValue; + x = x.ShiftRight(64); + } + return z; + } + + public static bool IsOne64(ulong[] x) + { + if (x[0] != 1UL) + { + return false; + } + for (int i = 1; i < 9; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static bool IsZero64(ulong[] x) + { + for (int i = 0; i < 9; ++i) + { + if (x[i] != 0UL) + { + return false; + } + } + return true; + } + + public static BigInteger ToBigInteger64(ulong[] x) + { + byte[] bs = new byte[72]; + for (int i = 0; i < 9; ++i) + { + ulong x_i = x[i]; + if (x_i != 0L) + { + Pack.UInt64_To_BE(x_i, bs, (8 - i) << 3); + } + } + return new BigInteger(1, bs); + } + } +} -- cgit 1.4.1 From ddd9150a66af5f9a9f18c51fccfbb4e4b01c43fa Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 19:18:52 +0700 Subject: Fix case-handling for custom curve names --- crypto/src/crypto/ec/CustomNamedCurves.cs | 42 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs index 8ff1d24c7..a7eb6a704 100644 --- a/crypto/src/crypto/ec/CustomNamedCurves.cs +++ b/crypto/src/crypto/ec/CustomNamedCurves.cs @@ -272,43 +272,53 @@ namespace Org.BouncyCastle.Crypto.EC } } + private static readonly IDictionary nameToCurve = Platform.CreateHashtable(); private static readonly IDictionary nameToOid = Platform.CreateHashtable(); private static readonly IDictionary oidToCurve = Platform.CreateHashtable(); private static readonly IDictionary oidToName = Platform.CreateHashtable(); + private static readonly IList names = Platform.CreateArrayList(); private static void DefineCurve(string name, X9ECParametersHolder holder) { + names.Add(name); + name = Platform.ToLowerInvariant(name); nameToCurve.Add(name, holder); } - private static void DefineCurve(string name, DerObjectIdentifier oid, X9ECParametersHolder holder) + private static void DefineCurveWithOid(string name, DerObjectIdentifier oid, X9ECParametersHolder holder) { - nameToCurve.Add(name, holder); - nameToOid.Add(name, oid); + names.Add(name); oidToName.Add(oid, name); oidToCurve.Add(oid, holder); + name = Platform.ToLowerInvariant(name); + nameToOid.Add(name, oid); + nameToCurve.Add(name, holder); } - private static void DefineCurveAlias(string alias, DerObjectIdentifier oid) + private static void DefineCurveAlias(string name, DerObjectIdentifier oid) { - alias = Platform.ToLowerInvariant(alias); - nameToOid.Add(alias, oid); - nameToCurve.Add(alias, oidToCurve[oid]); + object curve = oidToCurve[oid]; + if (curve == null) + throw new InvalidOperationException(); + + name = Platform.ToLowerInvariant(name); + nameToOid.Add(name, oid); + nameToCurve.Add(name, curve); } static CustomNamedCurves() { DefineCurve("curve25519", Curve25519Holder.Instance); - DefineCurve("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance); - DefineCurve("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance); - DefineCurve("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance); - DefineCurve("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance); - DefineCurve("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance); - DefineCurve("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance); - DefineCurve("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance); - DefineCurve("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance); + DefineCurveWithOid("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance); + DefineCurveWithOid("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance); + DefineCurveWithOid("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance); + DefineCurveWithOid("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance); + DefineCurveWithOid("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance); + DefineCurveWithOid("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance); + DefineCurveWithOid("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance); + DefineCurveWithOid("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance); DefineCurveAlias("P-192", SecObjectIdentifiers.SecP192r1); DefineCurveAlias("P-224", SecObjectIdentifiers.SecP224r1); @@ -360,7 +370,7 @@ namespace Org.BouncyCastle.Crypto.EC */ public static IEnumerable Names { - get { return new EnumerableProxy(nameToCurve.Keys); } + get { return new EnumerableProxy(names); } } } } -- cgit 1.4.1 From bca3fd0a7dd9722c1f7ce5b286543f330ca2a3ae Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 23 Mar 2015 20:16:34 +0700 Subject: F2m changes in preparation for custom binary curves --- crypto/src/math/ec/ECCurve.cs | 175 +++++------- crypto/src/math/ec/ECPoint.cs | 307 ++++++++++----------- crypto/src/math/ec/abc/Tnaf.cs | 171 ++++++------ crypto/src/math/ec/multiplier/WTauNafMultiplier.cs | 71 ++--- .../src/math/ec/multiplier/WTauNafPreCompInfo.cs | 6 +- 5 files changed, 354 insertions(+), 376 deletions(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs index 339d37f7c..9fe9e32fd 100644 --- a/crypto/src/math/ec/ECCurve.cs +++ b/crypto/src/math/ec/ECCurve.cs @@ -623,6 +623,18 @@ namespace Org.BouncyCastle.Math.EC public abstract class AbstractF2mCurve : ECCurve { + public static BigInteger Inverse(int m, int[] ks, BigInteger x) + { + return new LongArray(x).ModInverse(m, ks).ToBigInteger(); + } + + /** + * The auxiliary values s0 and + * s1 used for partial modular reduction for + * Koblitz curves. + */ + private BigInteger[] si = null; + private static IFiniteField BuildField(int m, int k1, int k2, int k3) { if (k1 == 0) @@ -657,6 +669,69 @@ namespace Org.BouncyCastle.Math.EC : base(BuildField(m, k1, k2, k3)) { } + + [Obsolete("Per-point compression property will be removed")] + public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression) + { + ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y); + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + if (X.IsZero) + { + if (!Y.Square().Equals(B)) + throw new ArgumentException(); + } + else + { + // Y becomes Lambda (X + Y/X) here + Y = Y.Divide(X).Add(X); + } + break; + } + default: + { + break; + } + } + + return CreateRawPoint(X, Y, withCompression); + } + + /** + * @return the auxiliary values s0 and + * s1 used for partial modular reduction for + * Koblitz curves. + */ + internal virtual BigInteger[] GetSi() + { + if (si == null) + { + lock (this) + { + if (si == null) + { + si = Tnaf.GetSi(this); + } + } + } + return si; + } + + /** + * Returns true if this is a Koblitz curve (ABC curve). + * @return true if this is a Koblitz curve (ABC curve), false otherwise + */ + public virtual bool IsKoblitz + { + get + { + return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne); + } + } } /** @@ -704,19 +779,6 @@ namespace Org.BouncyCastle.Math.EC */ protected readonly F2mPoint m_infinity; - /** - * The parameter μ of the elliptic curve if this is - * a Koblitz curve. - */ - private sbyte mu = 0; - - /** - * The auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - private BigInteger[] si = null; - /** * Constructor for Trinomial Polynomial Basis (TPB). * @param m The exponent m of @@ -917,37 +979,6 @@ namespace Org.BouncyCastle.Math.EC return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x); } - [Obsolete("Per-point compression property will be removed")] - public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression) - { - ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y); - - switch (this.CoordinateSystem) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - if (X.IsZero) - { - if (!Y.Square().Equals(B)) - throw new ArgumentException(); - } - else - { - // Y becomes Lambda (X + Y/X) here - Y = Y.Divide(X).Add(X); - } - break; - } - default: - { - break; - } - } - - return CreateRawPoint(X, Y, withCompression); - } - protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) { return new F2mPoint(this, x, y, withCompression); @@ -963,60 +994,6 @@ namespace Org.BouncyCastle.Math.EC get { return m_infinity; } } - /** - * Returns true if this is a Koblitz curve (ABC curve). - * @return true if this is a Koblitz curve (ABC curve), false otherwise - */ - public virtual bool IsKoblitz - { - get - { - return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne); - } - } - - /** - * Returns the parameter μ of the elliptic curve. - * @return μ of the elliptic curve. - * @throws ArgumentException if the given ECCurve is not a - * Koblitz curve. - */ - internal virtual sbyte GetMu() - { - if (mu == 0) - { - lock (this) - { - if (mu == 0) - { - mu = Tnaf.GetMu(this); - } - } - } - - return mu; - } - - /** - * @return the auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - internal virtual BigInteger[] GetSi() - { - if (si == null) - { - lock (this) - { - if (si == null) - { - si = Tnaf.GetSi(this); - } - } - } - return si; - } - protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) { ECFieldElement xp = FromBigInteger(X1), yp = null; @@ -1086,7 +1063,7 @@ namespace Org.BouncyCastle.Math.EC ECFieldElement t = FromBigInteger(new BigInteger(m, rand)); z = zeroElement; ECFieldElement w = beta; - for (int i = 1; i <= m - 1; i++) + for (int i = 1; i < m; i++) { ECFieldElement w2 = w.Square(); z = z.Square().Add(w2.Multiply(t)); diff --git a/crypto/src/math/ec/ECPoint.cs b/crypto/src/math/ec/ECPoint.cs index 3e206e65f..a5ba515c5 100644 --- a/crypto/src/math/ec/ECPoint.cs +++ b/crypto/src/math/ec/ECPoint.cs @@ -1383,6 +1383,139 @@ namespace Org.BouncyCastle.Math.EC return lhs.Equals(rhs); } + + public override ECPoint ScaleX(ECFieldElement scale) + { + if (this.IsInfinity) + return this; + + switch (CurveCoordinateSystem) + { + case ECCurve.COORD_LAMBDA_AFFINE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = RawXCoord, L = RawYCoord; + + ECFieldElement X2 = X.Multiply(scale); + ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2); + + return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); + } + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0]; + + // We scale the Z coordinate also, to avoid an inversion + ECFieldElement X2 = X.Multiply(scale.Square()); + ECFieldElement L2 = L.Add(X).Add(X2); + ECFieldElement Z2 = Z.Multiply(scale); + + return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed); + } + default: + { + return base.ScaleX(scale); + } + } + } + + public override ECPoint ScaleY(ECFieldElement scale) + { + if (this.IsInfinity) + return this; + + switch (CurveCoordinateSystem) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + // Y is actually Lambda (X + Y/X) here + ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X); + + return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); + } + default: + { + return base.ScaleY(scale); + } + } + } + + public override ECPoint Subtract(ECPoint b) + { + if (b.IsInfinity) + return this; + + // Add -b + return Add(b.Negate()); + } + + public virtual AbstractF2mPoint Tau() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + int coord = curve.CoordinateSystem; + + ECFieldElement X1 = this.RawXCoord; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.RawYCoord; + return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(), IsCompressed); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + return (AbstractF2mPoint)curve.CreateRawPoint(X1.Square(), Y1.Square(), + new ECFieldElement[] { Z1.Square() }, IsCompressed); + } + default: + { + throw new InvalidOperationException("unsupported coordinate system"); + } + } + } + + public virtual AbstractF2mPoint TauPow(int pow) + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + int coord = curve.CoordinateSystem; + + ECFieldElement X1 = this.RawXCoord; + + switch (coord) + { + case ECCurve.COORD_AFFINE: + case ECCurve.COORD_LAMBDA_AFFINE: + { + ECFieldElement Y1 = this.RawYCoord; + return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow), IsCompressed); + } + case ECCurve.COORD_HOMOGENEOUS: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + return (AbstractF2mPoint)curve.CreateRawPoint(X1.SquarePow(pow), Y1.SquarePow(pow), + new ECFieldElement[] { Z1.SquarePow(pow) }, IsCompressed); + } + default: + { + throw new InvalidOperationException("unsupported coordinate system"); + } + } + } } /** @@ -1491,66 +1624,6 @@ namespace Org.BouncyCastle.Math.EC } } - public override ECPoint ScaleX(ECFieldElement scale) - { - if (this.IsInfinity) - return this; - - switch (CurveCoordinateSystem) - { - case ECCurve.COORD_LAMBDA_AFFINE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = RawXCoord, L = RawYCoord; - - ECFieldElement X2 = X.Multiply(scale); - ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2); - - return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); - } - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - // Y is actually Lambda (X + Y/X) here - ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0]; - - // We scale the Z coordinate also, to avoid an inversion - ECFieldElement X2 = X.Multiply(scale.Square()); - ECFieldElement L2 = L.Add(X).Add(X2); - ECFieldElement Z2 = Z.Multiply(scale); - - return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed); - } - default: - { - return base.ScaleX(scale); - } - } - } - - public override ECPoint ScaleY(ECFieldElement scale) - { - if (this.IsInfinity) - return this; - - switch (CurveCoordinateSystem) - { - case ECCurve.COORD_LAMBDA_AFFINE: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement X = RawXCoord, L = RawYCoord; - - // Y is actually Lambda (X + Y/X) here - ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X); - - return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed); - } - default: - { - return base.ScaleY(scale); - } - } - } - protected internal override bool CompressionYTilde { get @@ -1579,43 +1652,7 @@ namespace Org.BouncyCastle.Math.EC } } - /** - * Check, if two ECPoints can be added or subtracted. - * @param a The first ECPoint to check. - * @param b The second ECPoint to check. - * @throws IllegalArgumentException if a and b - * cannot be added. - */ - private static void CheckPoints( - ECPoint a, - ECPoint b) - { - // Check, if points are on the same curve - if (!a.Curve.Equals(b.Curve)) - throw new ArgumentException("Only points on the same curve can be added or subtracted"); - -// F2mFieldElement.CheckFieldElements(a.x, b.x); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) - */ public override ECPoint Add(ECPoint b) - { - CheckPoints(this, b); - return AddSimple((F2mPoint) b); - } - - /** - * Adds another ECPoints.F2m to this without - * checking if both points are on the same curve. Used by multiplication - * algorithms, because there all points are a multiple of the same point - * and hence the checks can be omitted. - * @param b The other ECPoints.F2m to add to - * this. - * @return this + b - */ - internal F2mPoint AddSimple(F2mPoint b) { if (this.IsInfinity) return b; @@ -1640,10 +1677,10 @@ namespace Org.BouncyCastle.Math.EC { if (dy.IsZero) { - return (F2mPoint)Twice(); + return Twice(); } - return (F2mPoint)curve.Infinity; + return curve.Infinity; } ECFieldElement L = dy.Divide(dx); @@ -1681,10 +1718,10 @@ namespace Org.BouncyCastle.Math.EC { if (U.IsZero) { - return (F2mPoint)Twice(); + return Twice(); } - return (F2mPoint)curve.Infinity; + return curve.Infinity; } ECFieldElement VSq = V.Square(); @@ -1705,9 +1742,9 @@ namespace Org.BouncyCastle.Math.EC if (X1.IsZero) { if (X2.IsZero) - return (F2mPoint)curve.Infinity; + return curve.Infinity; - return b.AddSimple(this); + return b.Add(this); } ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; @@ -1736,10 +1773,10 @@ namespace Org.BouncyCastle.Math.EC { if (A.IsZero) { - return (F2mPoint)Twice(); + return Twice(); } - return (F2mPoint)curve.Infinity; + return curve.Infinity; } ECFieldElement X3, L3, Z3; @@ -1800,68 +1837,6 @@ namespace Org.BouncyCastle.Math.EC } } - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) - */ - public override ECPoint Subtract( - ECPoint b) - { - CheckPoints(this, b); - return SubtractSimple((F2mPoint) b); - } - - /** - * Subtracts another ECPoints.F2m from this - * without checking if both points are on the same curve. Used by - * multiplication algorithms, because there all points are a multiple - * of the same point and hence the checks can be omitted. - * @param b The other ECPoints.F2m to subtract from - * this. - * @return this - b - */ - internal F2mPoint SubtractSimple( - F2mPoint b) - { - if (b.IsInfinity) - return this; - - // Add -b - return AddSimple((F2mPoint) b.Negate()); - } - - public virtual F2mPoint Tau() - { - if (this.IsInfinity) - { - return this; - } - - ECCurve curve = this.Curve; - int coord = curve.CoordinateSystem; - - ECFieldElement X1 = this.RawXCoord; - - switch (coord) - { - case ECCurve.COORD_AFFINE: - case ECCurve.COORD_LAMBDA_AFFINE: - { - ECFieldElement Y1 = this.RawYCoord; - return new F2mPoint(curve, X1.Square(), Y1.Square(), IsCompressed); - } - case ECCurve.COORD_HOMOGENEOUS: - case ECCurve.COORD_LAMBDA_PROJECTIVE: - { - ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0]; - return new F2mPoint(curve, X1.Square(), Y1.Square(), new ECFieldElement[] { Z1.Square() }, IsCompressed); - } - default: - { - throw new InvalidOperationException("unsupported coordinate system"); - } - } - } - /* (non-Javadoc) * @see Org.BouncyCastle.Math.EC.ECPoint#twice() */ diff --git a/crypto/src/math/ec/abc/Tnaf.cs b/crypto/src/math/ec/abc/Tnaf.cs index 9f16886f5..b6e792aa4 100644 --- a/crypto/src/math/ec/abc/Tnaf.cs +++ b/crypto/src/math/ec/abc/Tnaf.cs @@ -384,11 +384,11 @@ namespace Org.BouncyCastle.Math.EC.Abc /** * Applies the operation τ() to an - * F2mPoint. - * @param p The F2mPoint to which τ() is applied. + * AbstractF2mPoint. + * @param p The AbstractF2mPoint to which τ() is applied. * @return τ(p) */ - public static F2mPoint Tau(F2mPoint p) + public static AbstractF2mPoint Tau(AbstractF2mPoint p) { return p.Tau(); } @@ -403,7 +403,7 @@ namespace Org.BouncyCastle.Math.EC.Abc * @throws ArgumentException if the given ECCurve is not a Koblitz * curve. */ - public static sbyte GetMu(F2mCurve curve) + public static sbyte GetMu(AbstractF2mCurve curve) { BigInteger a = curve.A.ToBigInteger(); @@ -423,6 +423,16 @@ namespace Org.BouncyCastle.Math.EC.Abc return mu; } + public static sbyte GetMu(ECFieldElement curveA) + { + return (sbyte)(curveA.IsZero ? -1 : 1); + } + + public static sbyte GetMu(int curveA) + { + return (sbyte)(curveA == 0 ? -1 : 1); + } + /** * Calculates the Lucas Sequence elements Uk-1 and * Uk or Vk-1 and @@ -526,53 +536,60 @@ namespace Org.BouncyCastle.Math.EC.Abc * @throws ArgumentException if curve is not a * Koblitz curve (Anomalous Binary Curve, ABC). */ - public static BigInteger[] GetSi(F2mCurve curve) + public static BigInteger[] GetSi(AbstractF2mCurve curve) { if (!curve.IsKoblitz) throw new ArgumentException("si is defined for Koblitz curves only"); - int m = curve.M; + int m = curve.FieldSize; int a = curve.A.ToBigInteger().IntValue; - sbyte mu = curve.GetMu(); - int h = curve.Cofactor.IntValue; + sbyte mu = GetMu(a); + int shifts = GetShiftsForCofactor(curve.Cofactor); int index = m + 3 - a; BigInteger[] ui = GetLucas(mu, index, false); - BigInteger dividend0; - BigInteger dividend1; if (mu == 1) { - dividend0 = BigInteger.One.Subtract(ui[1]); - dividend1 = BigInteger.One.Subtract(ui[0]); - } - else if (mu == -1) - { - dividend0 = BigInteger.One.Add(ui[1]); - dividend1 = BigInteger.One.Add(ui[0]); - } - else - { - throw new ArgumentException("mu must be 1 or -1"); + ui[0] = ui[0].Negate(); + ui[1] = ui[1].Negate(); } - BigInteger[] si = new BigInteger[2]; + BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts); + BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate(); - if (h == 2) - { - si[0] = dividend0.ShiftRight(1); - si[1] = dividend1.ShiftRight(1).Negate(); - } - else if (h == 4) + return new BigInteger[] { dividend0, dividend1 }; + } + + public static BigInteger[] GetSi(int fieldSize, int curveA, BigInteger cofactor) + { + sbyte mu = GetMu(curveA); + int shifts = GetShiftsForCofactor(cofactor); + int index = fieldSize + 3 - curveA; + BigInteger[] ui = GetLucas(mu, index, false); + if (mu == 1) { - si[0] = dividend0.ShiftRight(2); - si[1] = dividend1.ShiftRight(2).Negate(); + ui[0] = ui[0].Negate(); + ui[1] = ui[1].Negate(); } - else + + BigInteger dividend0 = BigInteger.One.Add(ui[1]).ShiftRight(shifts); + BigInteger dividend1 = BigInteger.One.Add(ui[0]).ShiftRight(shifts).Negate(); + + return new BigInteger[] { dividend0, dividend1 }; + } + + protected static int GetShiftsForCofactor(BigInteger h) + { + if (h != null && h.BitLength < 4) { - throw new ArgumentException("h (Cofactor) must be 2 or 4"); + int hi = h.IntValue; + if (hi == 2) + return 1; + if (hi == 4) + return 2; } - return si; + throw new ArgumentException("h (Cofactor) must be 2 or 4"); } /** @@ -624,70 +641,77 @@ namespace Org.BouncyCastle.Math.EC.Abc } /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by a BigInteger using the reduced τ-adic * NAF (RTNAF) method. - * @param p The F2mPoint to Multiply. + * @param p The AbstractF2mPoint to Multiply. * @param k The BigInteger by which to Multiply p. * @return k * p */ - public static F2mPoint MultiplyRTnaf(F2mPoint p, BigInteger k) + public static AbstractF2mPoint MultiplyRTnaf(AbstractF2mPoint p, BigInteger k) { - F2mCurve curve = (F2mCurve) p.Curve; - int m = curve.M; - sbyte a = (sbyte) curve.A.ToBigInteger().IntValue; - sbyte mu = curve.GetMu(); + AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; + int m = curve.FieldSize; + int a = curve.A.ToBigInteger().IntValue; + sbyte mu = GetMu(a); BigInteger[] s = curve.GetSi(); - ZTauElement rho = PartModReduction(k, m, a, s, mu, (sbyte)10); + ZTauElement rho = PartModReduction(k, m, (sbyte)a, s, mu, (sbyte)10); return MultiplyTnaf(p, rho); } /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by an element λ of Z[τ] * using the τ-adic NAF (TNAF) method. - * @param p The F2mPoint to Multiply. + * @param p The AbstractF2mPoint to Multiply. * @param lambda The element λ of * Z[τ]. * @return λ * p */ - public static F2mPoint MultiplyTnaf(F2mPoint p, ZTauElement lambda) + public static AbstractF2mPoint MultiplyTnaf(AbstractF2mPoint p, ZTauElement lambda) { - F2mCurve curve = (F2mCurve)p.Curve; - sbyte mu = curve.GetMu(); + AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; + sbyte mu = GetMu(curve.A); sbyte[] u = TauAdicNaf(mu, lambda); - F2mPoint q = MultiplyFromTnaf(p, u); + AbstractF2mPoint q = MultiplyFromTnaf(p, u); return q; } /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by an element λ of Z[τ] * using the τ-adic NAF (TNAF) method, given the TNAF * of λ. - * @param p The F2mPoint to Multiply. + * @param p The AbstractF2mPoint to Multiply. * @param u The the TNAF of λ.. * @return λ * p */ - public static F2mPoint MultiplyFromTnaf(F2mPoint p, sbyte[] u) + public static AbstractF2mPoint MultiplyFromTnaf(AbstractF2mPoint p, sbyte[] u) { - F2mCurve curve = (F2mCurve)p.Curve; - F2mPoint q = (F2mPoint) curve.Infinity; + ECCurve curve = p.Curve; + AbstractF2mPoint q = (AbstractF2mPoint)curve.Infinity; + AbstractF2mPoint pNeg = (AbstractF2mPoint)p.Negate(); + int tauCount = 0; for (int i = u.Length - 1; i >= 0; i--) { - q = Tau(q); - if (u[i] == 1) - { - q = (F2mPoint)q.AddSimple(p); - } - else if (u[i] == -1) + ++tauCount; + sbyte ui = u[i]; + if (ui != 0) { - q = (F2mPoint)q.SubtractSimple(p); + q = q.TauPow(tauCount); + tauCount = 0; + + ECPoint x = ui > 0 ? p : pNeg; + q = (AbstractF2mPoint)q.Add(x); } } + if (tauCount > 0) + { + q = q.TauPow(tauCount); + } return q; } @@ -800,28 +824,21 @@ namespace Org.BouncyCastle.Math.EC.Abc * @param a The parameter a of the elliptic curve. * @return The precomputation array for p. */ - public static F2mPoint[] GetPreComp(F2mPoint p, sbyte a) + public static AbstractF2mPoint[] GetPreComp(AbstractF2mPoint p, sbyte a) { - F2mPoint[] pu; - pu = new F2mPoint[16]; - pu[1] = p; - sbyte[][] alphaTnaf; - if (a == 0) - { - alphaTnaf = Tnaf.Alpha0Tnaf; - } - else - { - // a == 1 - alphaTnaf = Tnaf.Alpha1Tnaf; - } + sbyte[][] alphaTnaf = (a == 0) ? Tnaf.Alpha0Tnaf : Tnaf.Alpha1Tnaf; + + AbstractF2mPoint[] pu = new AbstractF2mPoint[(uint)(alphaTnaf.Length + 1) >> 1]; + pu[0] = p; - int precompLen = alphaTnaf.Length; - for (int i = 3; i < precompLen; i = i + 2) + uint precompLen = (uint)alphaTnaf.Length; + for (uint i = 3; i < precompLen; i += 2) { - pu[i] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]); + pu[i >> 1] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]); } - + + p.Curve.NormalizeAll(pu); + return pu; } } diff --git a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs index dda778eea..1e7ddae91 100644 --- a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs +++ b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs @@ -15,23 +15,23 @@ namespace Org.BouncyCastle.Math.EC.Multiplier internal static readonly string PRECOMP_NAME = "bc_wtnaf"; /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by k using the reduced τ-adic NAF (RTNAF) * method. - * @param p The F2mPoint to multiply. + * @param p The AbstractF2mPoint to multiply. * @param k The integer by which to multiply k. * @return p multiplied by k. */ protected override ECPoint MultiplyPositive(ECPoint point, BigInteger k) { - if (!(point is F2mPoint)) - throw new ArgumentException("Only F2mPoint can be used in WTauNafMultiplier"); - - F2mPoint p = (F2mPoint)point; - F2mCurve curve = (F2mCurve)p.Curve; - int m = curve.M; - sbyte a = (sbyte) curve.A.ToBigInteger().IntValue; - sbyte mu = curve.GetMu(); + if (!(point is AbstractF2mPoint)) + throw new ArgumentException("Only AbstractF2mPoint can be used in WTauNafMultiplier"); + + AbstractF2mPoint p = (AbstractF2mPoint)point; + AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; + int m = curve.FieldSize; + sbyte a = (sbyte)curve.A.ToBigInteger().IntValue; + sbyte mu = Tnaf.GetMu(a); BigInteger[] s = curve.GetSi(); ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10); @@ -40,16 +40,16 @@ namespace Org.BouncyCastle.Math.EC.Multiplier } /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by an element λ of Z[τ] using * the τ-adic NAF (TNAF) method. - * @param p The F2mPoint to multiply. + * @param p The AbstractF2mPoint to multiply. * @param lambda The element λ of * Z[τ] of which to compute the * [τ]-adic NAF. * @return p multiplied by λ. */ - private F2mPoint MultiplyWTnaf(F2mPoint p, ZTauElement lambda, + private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda, PreCompInfo preCompInfo, sbyte a, sbyte mu) { ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1; @@ -63,20 +63,20 @@ namespace Org.BouncyCastle.Math.EC.Multiplier } /** - * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint} + * Multiplies a {@link org.bouncycastle.math.ec.AbstractF2mPoint AbstractF2mPoint} * by an element λ of Z[τ] * using the window τ-adic NAF (TNAF) method, given the * WTNAF of λ. - * @param p The F2mPoint to multiply. + * @param p The AbstractF2mPoint to multiply. * @param u The the WTNAF of λ.. * @return λ * p */ - private static F2mPoint MultiplyFromWTnaf(F2mPoint p, sbyte[] u, PreCompInfo preCompInfo) + private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u, PreCompInfo preCompInfo) { - F2mCurve curve = (F2mCurve)p.Curve; + AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; sbyte a = (sbyte)curve.A.ToBigInteger().IntValue; - F2mPoint[] pu; + AbstractF2mPoint[] pu; if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo)) { pu = Tnaf.GetPreComp(p, a); @@ -90,26 +90,35 @@ namespace Org.BouncyCastle.Math.EC.Multiplier pu = ((WTauNafPreCompInfo)preCompInfo).PreComp; } + // TODO Include negations in precomp (optionally) and use from here + AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length]; + for (int i = 0; i < pu.Length; ++i) + { + puNeg[i] = (AbstractF2mPoint)pu[i].Negate(); + } + + // q = infinity - F2mPoint q = (F2mPoint)curve.Infinity; + AbstractF2mPoint q = (AbstractF2mPoint) p.Curve.Infinity; + + int tauCount = 0; for (int i = u.Length - 1; i >= 0; i--) { - q = Tnaf.Tau(q); - sbyte ui = u[i]; + ++tauCount; + int ui = u[i]; if (ui != 0) { - if (ui > 0) - { - q = q.AddSimple(pu[ui]); - } - else - { - // u[i] < 0 - q = q.SubtractSimple(pu[-ui]); - } + q = q.TauPow(tauCount); + tauCount = 0; + + ECPoint x = ui > 0 ? pu[ui >> 1] : puNeg[(-ui) >> 1]; + q = (AbstractF2mPoint)q.Add(x); } } - + if (tauCount > 0) + { + q = q.TauPow(tauCount); + } return q; } } diff --git a/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs index 3c18404c0..72659b3ec 100644 --- a/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs +++ b/crypto/src/math/ec/multiplier/WTauNafPreCompInfo.cs @@ -8,14 +8,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier : PreCompInfo { /** - * Array holding the precomputed F2mPoints used for the + * Array holding the precomputed AbstractF2mPoints used for the * WTNAF multiplication in * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() * WTauNafMultiplier.multiply()}. */ - protected F2mPoint[] m_preComp; + protected AbstractF2mPoint[] m_preComp; - public virtual F2mPoint[] PreComp + public virtual AbstractF2mPoint[] PreComp { get { return m_preComp; } set { this.m_preComp = value; } -- cgit 1.4.1 From 4c411105f946de856727eb32a03586293d18a2b3 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 24 Mar 2015 13:17:46 +0700 Subject: Only test each named curve once --- crypto/test/src/math/ec/test/ECPointTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs index 8430f437d..2a62b7740 100644 --- a/crypto/test/src/math/ec/test/ECPointTest.cs +++ b/crypto/test/src/math/ec/test/ECPointTest.cs @@ -483,7 +483,9 @@ namespace Org.BouncyCastle.Math.EC.Tests CollectionUtilities.AddRange(names, ECNamedCurveTable.Names); CollectionUtilities.AddRange(names, CustomNamedCurves.Names); - foreach (string name in names) + ISet uniqNames = new HashSet(names); + + foreach (string name in uniqNames) { X9ECParameters x9ECParameters = ECNamedCurveTable.GetByName(name); if (x9ECParameters != null) -- cgit 1.4.1 From a87f15588587cd166f2951a55947e33a87fee02d Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 24 Mar 2015 13:25:10 +0700 Subject: Custom curves for secp128r1 and secp160r1/r2/k1 --- crypto/crypto.csproj | 70 ++++++ crypto/src/crypto/ec/CustomNamedCurves.cs | 167 +++++++++--- crypto/src/math/ec/custom/sec/SecP128R1Curve.cs | 78 ++++++ crypto/src/math/ec/custom/sec/SecP128R1Field.cs | 218 ++++++++++++++++ .../math/ec/custom/sec/SecP128R1FieldElement.cs | 198 +++++++++++++++ crypto/src/math/ec/custom/sec/SecP128R1Point.cs | 279 +++++++++++++++++++++ crypto/src/math/ec/custom/sec/SecP160K1Curve.cs | 74 ++++++ crypto/src/math/ec/custom/sec/SecP160K1Point.cs | 269 ++++++++++++++++++++ crypto/src/math/ec/custom/sec/SecP160R1Curve.cs | 78 ++++++ crypto/src/math/ec/custom/sec/SecP160R1Field.cs | 186 ++++++++++++++ .../math/ec/custom/sec/SecP160R1FieldElement.cs | 203 +++++++++++++++ crypto/src/math/ec/custom/sec/SecP160R1Point.cs | 279 +++++++++++++++++++++ crypto/src/math/ec/custom/sec/SecP160R2Curve.cs | 78 ++++++ crypto/src/math/ec/custom/sec/SecP160R2Field.cs | 178 +++++++++++++ .../math/ec/custom/sec/SecP160R2FieldElement.cs | 218 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecP160R2Point.cs | 279 +++++++++++++++++++++ 16 files changed, 2820 insertions(+), 32 deletions(-) create mode 100644 crypto/src/math/ec/custom/sec/SecP128R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP128R1Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP128R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R1Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R2Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R2Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecP160R2Point.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 50daeec48..ec03a3071 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5173,6 +5173,76 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + + + + + + + + + > 32); + z[1] = (uint)x1; x2 += (x1 >> 32); + z[2] = (uint)x2; x3 += (x2 >> 32); + z[3] = (uint)x3; + + Reduce32((uint)(x3 >> 32), z); + } + + public static void Reduce32(uint x, uint[] z) + { + while (x != 0) + { + ulong c, x4 = x; + + c = (ulong)z[0] + x4; + z[0] = (uint)c; c >>= 32; + if (c != 0) + { + c += (ulong)z[1]; + z[1] = (uint)c; c >>= 32; + c += (ulong)z[2]; + z[2] = (uint)c; c >>= 32; + } + c += (ulong)z[3] + (x4 << 1); + z[3] = (uint)c; c >>= 32; + + Debug.Assert(c >= 0 && c <= 2); + + x = (uint)c; + } + } + + public static void Square(uint[] x, uint[] z) + { + uint[] tt = Nat128.CreateExt(); + Nat128.Square(x, tt); + Reduce(tt, z); + } + + public static void SquareN(uint[] x, int n, uint[] z) + { + Debug.Assert(n > 0); + + uint[] tt = Nat128.CreateExt(); + Nat128.Square(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + Nat128.Square(z, tt); + Reduce(tt, z); + } + } + + public static void Subtract(uint[] x, uint[] y, uint[] z) + { + int c = Nat128.Sub(x, y, z); + if (c != 0) + { + SubPInvFrom(z); + } + } + + public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz) + { + int c = Nat.Sub(10, xx, yy, zz); + if (c != 0) + { + Nat.SubFrom(PExtInv.Length, PExtInv, zz); + } + } + + public static void Twice(uint[] x, uint[] z) + { + uint c = Nat.ShiftUpBit(4, x, 0, z); + if (c != 0 || (z[3] == P3 && Nat128.Gte(z, P))) + { + AddPInvTo(z); + } + } + + private static void AddPInvTo(uint[] z) + { + long c = (long)z[0] + 1; + z[0] = (uint)c; c >>= 32; + if (c != 0) + { + c += (long)z[1]; + z[1] = (uint)c; c >>= 32; + c += (long)z[2]; + z[2] = (uint)c; c >>= 32; + } + c += (long)z[3] + 2; + z[3] = (uint)c; + } + + private static void SubPInvFrom(uint[] z) + { + long c = (long)z[0] - 1; + z[0] = (uint)c; c >>= 32; + if (c != 0) + { + c += (long)z[1]; + z[1] = (uint)c; c >>= 32; + c += (long)z[2]; + z[2] = (uint)c; c >>= 32; + } + c += (long)z[3] - 2; + z[3] = (uint)c; + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs new file mode 100644 index 000000000..fa7951d5d --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP128R1FieldElement.cs @@ -0,0 +1,198 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP128R1FieldElement + : ECFieldElement + { + public static readonly BigInteger Q = SecP128R1Curve.q; + + protected internal readonly uint[] x; + + public SecP128R1FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0) + throw new ArgumentException("value invalid for SecP128R1FieldElement", "x"); + + this.x = SecP128R1Field.FromBigInteger(x); + } + + public SecP128R1FieldElement() + { + this.x = Nat128.Create(); + } + + protected internal SecP128R1FieldElement(uint[] x) + { + this.x = x; + } + + public override bool IsZero + { + get { return Nat128.IsZero(x); } + } + + public override bool IsOne + { + get { return Nat128.IsOne(x); } + } + + public override bool TestBitZero() + { + return Nat128.GetBit(x, 0) == 1; + } + + public override BigInteger ToBigInteger() + { + return Nat128.ToBigInteger(x); + } + + public override string FieldName + { + get { return "SecP128R1Field"; } + } + + public override int FieldSize + { + get { return Q.BitLength; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + uint[] z = Nat128.Create(); + SecP128R1Field.Add(x, ((SecP128R1FieldElement)b).x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement AddOne() + { + uint[] z = Nat128.Create(); + SecP128R1Field.AddOne(x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + uint[] z = Nat128.Create(); + SecP128R1Field.Subtract(x, ((SecP128R1FieldElement)b).x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + uint[] z = Nat128.Create(); + SecP128R1Field.Multiply(x, ((SecP128R1FieldElement)b).x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + // return multiply(b.invert()); + uint[] z = Nat128.Create(); + Mod.Invert(SecP128R1Field.P, ((SecP128R1FieldElement)b).x, z); + SecP128R1Field.Multiply(z, x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Negate() + { + uint[] z = Nat128.Create(); + SecP128R1Field.Negate(x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Square() + { + uint[] z = Nat128.Create(); + SecP128R1Field.Square(x, z); + return new SecP128R1FieldElement(z); + } + + public override ECFieldElement Invert() + { + // return new SecP128R1FieldElement(toBigInteger().modInverse(Q)); + uint[] z = Nat128.Create(); + Mod.Invert(SecP128R1Field.P, x, z); + return new SecP128R1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public override ECFieldElement Sqrt() + { + /* + * Raise this element to the exponent 2^126 - 2^95 + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 31 1s } { 95 0s } + * + * Therefore we need an addition chain containing 31 (the length of the repunit) We use: + * 1, 2, 4, 8, 10, 20, 30, [31] + */ + + uint[] x1 = this.x; + if (Nat128.IsZero(x1) || Nat128.IsOne(x1)) + return this; + + uint[] x2 = Nat128.Create(); + SecP128R1Field.Square(x1, x2); + SecP128R1Field.Multiply(x2, x1, x2); + uint[] x4 = Nat128.Create(); + SecP128R1Field.SquareN(x2, 2, x4); + SecP128R1Field.Multiply(x4, x2, x4); + uint[] x8 = Nat128.Create(); + SecP128R1Field.SquareN(x4, 4, x8); + SecP128R1Field.Multiply(x8, x4, x8); + uint[] x10 = x4; + SecP128R1Field.SquareN(x8, 2, x10); + SecP128R1Field.Multiply(x10, x2, x10); + uint[] x20 = x2; + SecP128R1Field.SquareN(x10, 10, x20); + SecP128R1Field.Multiply(x20, x10, x20); + uint[] x30 = x8; + SecP128R1Field.SquareN(x20, 10, x30); + SecP128R1Field.Multiply(x30, x10, x30); + uint[] x31 = x10; + SecP128R1Field.Square(x30, x31); + SecP128R1Field.Multiply(x31, x1, x31); + + uint[] t1 = x31; + SecP128R1Field.SquareN(t1, 95, t1); + + uint[] t2 = x30; + SecP128R1Field.Square(t1, t2); + + return Nat128.Eq(x1, t2) ? new SecP128R1FieldElement(t1) : null; + } + + public override bool Equals(object obj) + { + return Equals(obj as SecP128R1FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecP128R1FieldElement); + } + + public virtual bool Equals(SecP128R1FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat128.Eq(x, other.x); + } + + public override int GetHashCode() + { + return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 4); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP128R1Point.cs b/crypto/src/math/ec/custom/sec/SecP128R1Point.cs new file mode 100644 index 000000000..ae76d3cd1 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP128R1Point.cs @@ -0,0 +1,279 @@ +using System; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP128R1Point + : AbstractFpPoint + { + /** + * Create a point which encodes with point compression. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP128R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * @param withCompression + * if true encode with point compression + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP128R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecP128R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecP128R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + if (this == b) + return Twice(); + + ECCurve curve = this.Curve; + + SecP128R1FieldElement X1 = (SecP128R1FieldElement)this.RawXCoord, Y1 = (SecP128R1FieldElement)this.RawYCoord; + SecP128R1FieldElement X2 = (SecP128R1FieldElement)b.RawXCoord, Y2 = (SecP128R1FieldElement)b.RawYCoord; + + SecP128R1FieldElement Z1 = (SecP128R1FieldElement)this.RawZCoords[0]; + SecP128R1FieldElement Z2 = (SecP128R1FieldElement)b.RawZCoords[0]; + + uint c; + uint[] tt1 = Nat128.CreateExt(); + uint[] t2 = Nat128.Create(); + uint[] t3 = Nat128.Create(); + uint[] t4 = Nat128.Create(); + + bool Z1IsOne = Z1.IsOne; + uint[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP128R1Field.Square(Z1.x, S2); + + U2 = t2; + SecP128R1Field.Multiply(S2, X2.x, U2); + + SecP128R1Field.Multiply(S2, Z1.x, S2); + SecP128R1Field.Multiply(S2, Y2.x, S2); + } + + bool Z2IsOne = Z2.IsOne; + uint[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP128R1Field.Square(Z2.x, S1); + + U1 = tt1; + SecP128R1Field.Multiply(S1, X1.x, U1); + + SecP128R1Field.Multiply(S1, Z2.x, S1); + SecP128R1Field.Multiply(S1, Y1.x, S1); + } + + uint[] H = Nat128.Create(); + SecP128R1Field.Subtract(U1, U2, H); + + uint[] R = t2; + SecP128R1Field.Subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat128.IsZero(H)) + { + if (Nat128.IsZero(R)) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + uint[] HSquared = t3; + SecP128R1Field.Square(H, HSquared); + + uint[] G = Nat128.Create(); + SecP128R1Field.Multiply(HSquared, H, G); + + uint[] V = t3; + SecP128R1Field.Multiply(HSquared, U1, V); + + SecP128R1Field.Negate(G, G); + Nat128.Mul(S1, G, tt1); + + c = Nat128.AddBothTo(V, V, G); + SecP128R1Field.Reduce32(c, G); + + SecP128R1FieldElement X3 = new SecP128R1FieldElement(t4); + SecP128R1Field.Square(R, X3.x); + SecP128R1Field.Subtract(X3.x, G, X3.x); + + SecP128R1FieldElement Y3 = new SecP128R1FieldElement(G); + SecP128R1Field.Subtract(V, X3.x, Y3.x); + SecP128R1Field.MultiplyAddToExt(Y3.x, R, tt1); + SecP128R1Field.Reduce(tt1, Y3.x); + + SecP128R1FieldElement Z3 = new SecP128R1FieldElement(H); + if (!Z1IsOne) + { + SecP128R1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP128R1Field.Multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP128R1Point(curve, X3, Y3, zs, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + SecP128R1FieldElement Y1 = (SecP128R1FieldElement)this.RawYCoord; + if (Y1.IsZero) + return curve.Infinity; + + SecP128R1FieldElement X1 = (SecP128R1FieldElement)this.RawXCoord, Z1 = (SecP128R1FieldElement)this.RawZCoords[0]; + + uint c; + uint[] t1 = Nat128.Create(); + uint[] t2 = Nat128.Create(); + + uint[] Y1Squared = Nat128.Create(); + SecP128R1Field.Square(Y1.x, Y1Squared); + + uint[] T = Nat128.Create(); + SecP128R1Field.Square(Y1Squared, T); + + bool Z1IsOne = Z1.IsOne; + + uint[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP128R1Field.Square(Z1.x, Z1Squared); + } + + SecP128R1Field.Subtract(X1.x, Z1Squared, t1); + + uint[] M = t2; + SecP128R1Field.Add(X1.x, Z1Squared, M); + SecP128R1Field.Multiply(M, t1, M); + c = Nat128.AddBothTo(M, M, M); + SecP128R1Field.Reduce32(c, M); + + uint[] S = Y1Squared; + SecP128R1Field.Multiply(Y1Squared, X1.x, S); + c = Nat.ShiftUpBits(4, S, 2, 0); + SecP128R1Field.Reduce32(c, S); + + c = Nat.ShiftUpBits(4, T, 3, 0, t1); + SecP128R1Field.Reduce32(c, t1); + + SecP128R1FieldElement X3 = new SecP128R1FieldElement(T); + SecP128R1Field.Square(M, X3.x); + SecP128R1Field.Subtract(X3.x, S, X3.x); + SecP128R1Field.Subtract(X3.x, S, X3.x); + + SecP128R1FieldElement Y3 = new SecP128R1FieldElement(S); + SecP128R1Field.Subtract(S, X3.x, Y3.x); + SecP128R1Field.Multiply(Y3.x, M, Y3.x); + SecP128R1Field.Subtract(Y3.x, t1, Y3.x); + + SecP128R1FieldElement Z3 = new SecP128R1FieldElement(M); + SecP128R1Field.Twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP128R1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP128R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this == b) + return ThreeTimes(); + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECFieldElement Y1 = this.RawYCoord; + if (Y1.IsZero) + return b; + + return Twice().Add(b); + } + + public override ECPoint ThreeTimes() + { + if (this.IsInfinity || this.RawYCoord.IsZero) + return this; + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return Twice().Add(this); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + return new SecP128R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs new file mode 100644 index 000000000..7d45c6227 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160K1Curve.cs @@ -0,0 +1,74 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160K1Curve + : AbstractFpCurve + { + public static readonly BigInteger q = SecP160R2Curve.q; + + private const int SECP160K1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected readonly SecP160K1Point m_infinity; + + public SecP160K1Curve() + : base(q) + { + this.m_infinity = new SecP160K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.ValueOf(7)); + this.m_order = new BigInteger(1, Hex.Decode("0100000000000000000001B8FA16DFAB9ACA16B6B3")); + this.m_cofactor = BigInteger.One; + this.m_coord = SECP160K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecP160K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public virtual BigInteger Q + { + get { return q; } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return q.BitLength; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecP160R2FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecP160K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecP160K1Point(this, x, y, zs, withCompression); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160K1Point.cs b/crypto/src/math/ec/custom/sec/SecP160K1Point.cs new file mode 100644 index 000000000..1bcbadb33 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160K1Point.cs @@ -0,0 +1,269 @@ +using System; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160K1Point + : AbstractFpPoint + { + /** + * Create a point which encodes with point compression. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * + * @deprecated Use ECCurve.CreatePoint to construct points + */ + public SecP160K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * @param withCompression + * if true encode with point compression + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(bool)} + */ + public SecP160K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecP160K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, + bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecP160K1Point(null, AffineXCoord, AffineYCoord); + } + + // B.3 pg 62 + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + if (this == b) + return Twice(); + + ECCurve curve = this.Curve; + + SecP160R2FieldElement X1 = (SecP160R2FieldElement)this.RawXCoord, Y1 = (SecP160R2FieldElement)this.RawYCoord; + SecP160R2FieldElement X2 = (SecP160R2FieldElement)b.RawXCoord, Y2 = (SecP160R2FieldElement)b.RawYCoord; + + SecP160R2FieldElement Z1 = (SecP160R2FieldElement)this.RawZCoords[0]; + SecP160R2FieldElement Z2 = (SecP160R2FieldElement)b.RawZCoords[0]; + + uint c; + uint[] tt1 = Nat160.CreateExt(); + uint[] t2 = Nat160.Create(); + uint[] t3 = Nat160.Create(); + uint[] t4 = Nat160.Create(); + + bool Z1IsOne = Z1.IsOne; + uint[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP160R2Field.Square(Z1.x, S2); + + U2 = t2; + SecP160R2Field.Multiply(S2, X2.x, U2); + + SecP160R2Field.Multiply(S2, Z1.x, S2); + SecP160R2Field.Multiply(S2, Y2.x, S2); + } + + bool Z2IsOne = Z2.IsOne; + uint[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP160R2Field.Square(Z2.x, S1); + + U1 = tt1; + SecP160R2Field.Multiply(S1, X1.x, U1); + + SecP160R2Field.Multiply(S1, Z2.x, S1); + SecP160R2Field.Multiply(S1, Y1.x, S1); + } + + uint[] H = Nat160.Create(); + SecP160R2Field.Subtract(U1, U2, H); + + uint[] R = t2; + SecP160R2Field.Subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat160.IsZero(H)) + { + if (Nat160.IsZero(R)) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + uint[] HSquared = t3; + SecP160R2Field.Square(H, HSquared); + + uint[] G = Nat160.Create(); + SecP160R2Field.Multiply(HSquared, H, G); + + uint[] V = t3; + SecP160R2Field.Multiply(HSquared, U1, V); + + SecP160R2Field.Negate(G, G); + Nat160.Mul(S1, G, tt1); + + c = Nat160.AddBothTo(V, V, G); + SecP160R2Field.Reduce32(c, G); + + SecP160R2FieldElement X3 = new SecP160R2FieldElement(t4); + SecP160R2Field.Square(R, X3.x); + SecP160R2Field.Subtract(X3.x, G, X3.x); + + SecP160R2FieldElement Y3 = new SecP160R2FieldElement(G); + SecP160R2Field.Subtract(V, X3.x, Y3.x); + SecP160R2Field.MultiplyAddToExt(Y3.x, R, tt1); + SecP160R2Field.Reduce(tt1, Y3.x); + + SecP160R2FieldElement Z3 = new SecP160R2FieldElement(H); + if (!Z1IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[] { Z3 }; + + return new SecP160K1Point(curve, X3, Y3, zs, IsCompressed); + } + + // B.3 pg 62 + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + SecP160R2FieldElement Y1 = (SecP160R2FieldElement)this.RawYCoord; + if (Y1.IsZero) + return curve.Infinity; + + SecP160R2FieldElement X1 = (SecP160R2FieldElement)this.RawXCoord, Z1 = (SecP160R2FieldElement)this.RawZCoords[0]; + + uint c; + + uint[] Y1Squared = Nat160.Create(); + SecP160R2Field.Square(Y1.x, Y1Squared); + + uint[] T = Nat160.Create(); + SecP160R2Field.Square(Y1Squared, T); + + uint[] M = Nat160.Create(); + SecP160R2Field.Square(X1.x, M); + c = Nat160.AddBothTo(M, M, M); + SecP160R2Field.Reduce32(c, M); + + uint[] S = Y1Squared; + SecP160R2Field.Multiply(Y1Squared, X1.x, S); + c = Nat.ShiftUpBits(5, S, 2, 0); + SecP160R2Field.Reduce32(c, S); + + uint[] t1 = Nat160.Create(); + c = Nat.ShiftUpBits(5, T, 3, 0, t1); + SecP160R2Field.Reduce32(c, t1); + + SecP160R2FieldElement X3 = new SecP160R2FieldElement(T); + SecP160R2Field.Square(M, X3.x); + SecP160R2Field.Subtract(X3.x, S, X3.x); + SecP160R2Field.Subtract(X3.x, S, X3.x); + + SecP160R2FieldElement Y3 = new SecP160R2FieldElement(S); + SecP160R2Field.Subtract(S, X3.x, Y3.x); + SecP160R2Field.Multiply(Y3.x, M, Y3.x); + SecP160R2Field.Subtract(Y3.x, t1, Y3.x); + + SecP160R2FieldElement Z3 = new SecP160R2FieldElement(M); + SecP160R2Field.Twice(Y1.x, Z3.x); + if (!Z1.IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP160K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this == b) + return ThreeTimes(); + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECFieldElement Y1 = this.RawYCoord; + if (Y1.IsZero) + return b; + + return Twice().Add(b); + } + + public override ECPoint ThreeTimes() + { + if (this.IsInfinity || this.RawYCoord.IsZero) + return this; + + // NOTE: Be careful about recursions between TwicePlus and threeTimes + return Twice().Add(this); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + return new SecP160K1Point(Curve, this.RawXCoord, this.RawYCoord.Negate(), this.RawZCoords, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs new file mode 100644 index 000000000..87389af36 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R1Curve.cs @@ -0,0 +1,78 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R1Curve + : AbstractFpCurve + { + public static readonly BigInteger q = new BigInteger(1, + Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")); + + private const int SecP160R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected readonly SecP160R1Point m_infinity; + + public SecP160R1Curve() + : base(q) + { + this.m_infinity = new SecP160R1Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, + Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"))); + this.m_b = FromBigInteger(new BigInteger(1, + Hex.Decode("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"))); + this.m_order = new BigInteger(1, Hex.Decode("0100000000000000000001F4C8F927AED3CA752257")); + this.m_cofactor = BigInteger.One; + + this.m_coord = SecP160R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecP160R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public virtual BigInteger Q + { + get { return q; } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return q.BitLength; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecP160R1FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecP160R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecP160R1Point(this, x, y, zs, withCompression); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R1Field.cs b/crypto/src/math/ec/custom/sec/SecP160R1Field.cs new file mode 100644 index 000000000..6a5a2ef64 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R1Field.cs @@ -0,0 +1,186 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R1Field + { + // 2^160 - 2^31 - 1 + internal static readonly uint[] P = new uint[] { 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + internal static readonly uint[] PExt = new uint[] { 0x00000001, 0x40000001, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static readonly uint[] PExtInv = new uint[]{ 0xFFFFFFFF, 0xBFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x00000001, 0x00000001 }; + private const uint P4 = 0xFFFFFFFF; + private const uint PExt9 = 0xFFFFFFFF; + private const uint PInv = 0x80000001; + + public static void Add(uint[] x, uint[] y, uint[] z) + { + uint c = Nat160.Add(x, y, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.AddWordTo(5, PInv, z); + } + } + + public static void AddExt(uint[] xx, uint[] yy, uint[] zz) + { + uint c = Nat.Add(10, xx, yy, zz); + if (c != 0 || (zz[9] == PExt9 && Nat.Gte(10, zz, PExt))) + { + if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.IncAt(10, zz, PExtInv.Length); + } + } + } + + public static void AddOne(uint[] x, uint[] z) + { + uint c = Nat.Inc(5, x, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.AddWordTo(5, PInv, z); + } + } + + public static uint[] FromBigInteger(BigInteger x) + { + uint[] z = Nat160.FromBigInteger(x); + if (z[4] == P4 && Nat160.Gte(z, P)) + { + Nat160.SubFrom(P, z); + } + return z; + } + + public static void Half(uint[] x, uint[] z) + { + if ((x[0] & 1) == 0) + { + Nat.ShiftDownBit(5, x, 0, z); + } + else + { + uint c = Nat160.Add(x, P, z); + Nat.ShiftDownBit(5, z, c); + } + } + + public static void Multiply(uint[] x, uint[] y, uint[] z) + { + uint[] tt = Nat160.CreateExt(); + Nat160.Mul(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz) + { + uint c = Nat160.MulAddTo(x, y, zz); + if (c != 0 || (zz[9] == PExt9 && Nat.Gte(10, zz, PExt))) + { + if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.IncAt(10, zz, PExtInv.Length); + } + } + } + + public static void Negate(uint[] x, uint[] z) + { + if (Nat160.IsZero(x)) + { + Nat160.Zero(z); + } + else + { + Nat160.Sub(P, x, z); + } + } + + public static void Reduce(uint[] xx, uint[] z) + { + ulong x5 = xx[5], x6 = xx[6], x7 = xx[7], x8 = xx[8], x9 = xx[9]; + + ulong c = 0; + c += (ulong)xx[0] + x5 + (x5 << 31); + z[0] = (uint)c; c >>= 32; + c += (ulong)xx[1] + x6 + (x6 << 31); + z[1] = (uint)c; c >>= 32; + c += (ulong)xx[2] + x7 + (x7 << 31); + z[2] = (uint)c; c >>= 32; + c += (ulong)xx[3] + x8 + (x8 << 31); + z[3] = (uint)c; c >>= 32; + c += (ulong)xx[4] + x9 + (x9 << 31); + z[4] = (uint)c; c >>= 32; + + Debug.Assert(c >> 32 == 0); + + Reduce32((uint)c, z); + } + + public static void Reduce32(uint x, uint[] z) + { + if ((x != 0 && Nat160.MulWordsAdd(PInv, x, z, 0) != 0) + || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.AddWordTo(5, PInv, z); + } + } + + public static void Square(uint[] x, uint[] z) + { + uint[] tt = Nat160.CreateExt(); + Nat160.Square(x, tt); + Reduce(tt, z); + } + + public static void SquareN(uint[] x, int n, uint[] z) + { + Debug.Assert(n > 0); + + uint[] tt = Nat160.CreateExt(); + Nat160.Square(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + Nat160.Square(z, tt); + Reduce(tt, z); + } + } + + public static void Subtract(uint[] x, uint[] y, uint[] z) + { + int c = Nat160.Sub(x, y, z); + if (c != 0) + { + Nat.SubWordFrom(5, PInv, z); + } + } + + public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz) + { + int c = Nat.Sub(10, xx, yy, zz); + if (c != 0) + { + if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.DecAt(10, zz, PExtInv.Length); + } + } + } + + public static void Twice(uint[] x, uint[] z) + { + uint c = Nat.ShiftUpBit(5, x, 0, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.AddWordTo(5, PInv, z); + } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs new file mode 100644 index 000000000..d1fc75644 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R1FieldElement.cs @@ -0,0 +1,203 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R1FieldElement + : ECFieldElement + { + public static readonly BigInteger Q = SecP160R1Curve.q; + + protected internal readonly uint[] x; + + public SecP160R1FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0) + throw new ArgumentException("value invalid for SecP160R1FieldElement", "x"); + + this.x = SecP160R1Field.FromBigInteger(x); + } + + public SecP160R1FieldElement() + { + this.x = Nat160.Create(); + } + + protected internal SecP160R1FieldElement(uint[] x) + { + this.x = x; + } + + public override bool IsZero + { + get { return Nat160.IsZero(x); } + } + + public override bool IsOne + { + get { return Nat160.IsOne(x); } + } + + public override bool TestBitZero() + { + return Nat160.GetBit(x, 0) == 1; + } + + public override BigInteger ToBigInteger() + { + return Nat160.ToBigInteger(x); + } + + public override string FieldName + { + get { return "SecP160R1Field"; } + } + + public override int FieldSize + { + get { return Q.BitLength; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R1Field.Add(x, ((SecP160R1FieldElement)b).x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement AddOne() + { + uint[] z = Nat160.Create(); + SecP160R1Field.AddOne(x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R1Field.Subtract(x, ((SecP160R1FieldElement)b).x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R1Field.Multiply(x, ((SecP160R1FieldElement)b).x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + // return multiply(b.invert()); + uint[] z = Nat160.Create(); + Mod.Invert(SecP160R1Field.P, ((SecP160R1FieldElement)b).x, z); + SecP160R1Field.Multiply(z, x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Negate() + { + uint[] z = Nat160.Create(); + SecP160R1Field.Negate(x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Square() + { + uint[] z = Nat160.Create(); + SecP160R1Field.Square(x, z); + return new SecP160R1FieldElement(z); + } + + public override ECFieldElement Invert() + { + // return new SecP160R1FieldElement(ToBigInteger().modInverse(Q)); + uint[] z = Nat160.Create(); + Mod.Invert(SecP160R1Field.P, x, z); + return new SecP160R1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public override ECFieldElement Sqrt() + { + /* + * Raise this element to the exponent 2^158 - 2^29 + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 129 1s } { 29 0s } + * + * Therefore we need an addition chain containing 129 (the length of the repunit) We use: + * 1, 2, 4, 8, 16, 32, 64, 128, [129] + */ + + uint[] x1 = this.x; + if (Nat160.IsZero(x1) || Nat160.IsOne(x1)) + { + return this; + } + + uint[] x2 = Nat160.Create(); + SecP160R1Field.Square(x1, x2); + SecP160R1Field.Multiply(x2, x1, x2); + uint[] x4 = Nat160.Create(); + SecP160R1Field.SquareN(x2, 2, x4); + SecP160R1Field.Multiply(x4, x2, x4); + uint[] x8 = x2; + SecP160R1Field.SquareN(x4, 4, x8); + SecP160R1Field.Multiply(x8, x4, x8); + uint[] x16 = x4; + SecP160R1Field.SquareN(x8, 8, x16); + SecP160R1Field.Multiply(x16, x8, x16); + uint[] x32 = x8; + SecP160R1Field.SquareN(x16, 16, x32); + SecP160R1Field.Multiply(x32, x16, x32); + uint[] x64 = x16; + SecP160R1Field.SquareN(x32, 32, x64); + SecP160R1Field.Multiply(x64, x32, x64); + uint[] x128 = x32; + SecP160R1Field.SquareN(x64, 64, x128); + SecP160R1Field.Multiply(x128, x64, x128); + uint[] x129 = x64; + SecP160R1Field.Square(x128, x129); + SecP160R1Field.Multiply(x129, x1, x129); + + uint[] t1 = x129; + SecP160R1Field.SquareN(t1, 29, t1); + + uint[] t2 = x128; + SecP160R1Field.Square(t1, t2); + + return Nat160.Eq(x1, t2) ? new SecP160R1FieldElement(t1) : null; + } + + public override bool Equals(object obj) + { + return Equals(obj as SecP160R1FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecP160R1FieldElement); + } + + public virtual bool Equals(SecP160R1FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat160.Eq(x, other.x); + } + + public override int GetHashCode() + { + return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 5); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R1Point.cs b/crypto/src/math/ec/custom/sec/SecP160R1Point.cs new file mode 100644 index 000000000..f9f065de6 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R1Point.cs @@ -0,0 +1,279 @@ +using System; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R1Point + : AbstractFpPoint + { + /** + * Create a point which encodes with point compression. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * + * @deprecated Use ECCurve.CreatePoint to construct points + */ + public SecP160R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * @param withCompression + * if true encode with point compression + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(bool)} + */ + public SecP160R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecP160R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecP160R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + if (this == b) + return Twice(); + + ECCurve curve = this.Curve; + + SecP160R1FieldElement X1 = (SecP160R1FieldElement)this.RawXCoord, Y1 = (SecP160R1FieldElement)this.RawYCoord; + SecP160R1FieldElement X2 = (SecP160R1FieldElement)b.RawXCoord, Y2 = (SecP160R1FieldElement)b.RawYCoord; + + SecP160R1FieldElement Z1 = (SecP160R1FieldElement)this.RawZCoords[0]; + SecP160R1FieldElement Z2 = (SecP160R1FieldElement)b.RawZCoords[0]; + + uint c; + uint[] tt1 = Nat160.CreateExt(); + uint[] t2 = Nat160.Create(); + uint[] t3 = Nat160.Create(); + uint[] t4 = Nat160.Create(); + + bool Z1IsOne = Z1.IsOne; + uint[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP160R1Field.Square(Z1.x, S2); + + U2 = t2; + SecP160R1Field.Multiply(S2, X2.x, U2); + + SecP160R1Field.Multiply(S2, Z1.x, S2); + SecP160R1Field.Multiply(S2, Y2.x, S2); + } + + bool Z2IsOne = Z2.IsOne; + uint[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP160R1Field.Square(Z2.x, S1); + + U1 = tt1; + SecP160R1Field.Multiply(S1, X1.x, U1); + + SecP160R1Field.Multiply(S1, Z2.x, S1); + SecP160R1Field.Multiply(S1, Y1.x, S1); + } + + uint[] H = Nat160.Create(); + SecP160R1Field.Subtract(U1, U2, H); + + uint[] R = t2; + SecP160R1Field.Subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat160.IsZero(H)) + { + if (Nat160.IsZero(R)) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + uint[] HSquared = t3; + SecP160R1Field.Square(H, HSquared); + + uint[] G = Nat160.Create(); + SecP160R1Field.Multiply(HSquared, H, G); + + uint[] V = t3; + SecP160R1Field.Multiply(HSquared, U1, V); + + SecP160R1Field.Negate(G, G); + Nat160.Mul(S1, G, tt1); + + c = Nat160.AddBothTo(V, V, G); + SecP160R1Field.Reduce32(c, G); + + SecP160R1FieldElement X3 = new SecP160R1FieldElement(t4); + SecP160R1Field.Square(R, X3.x); + SecP160R1Field.Subtract(X3.x, G, X3.x); + + SecP160R1FieldElement Y3 = new SecP160R1FieldElement(G); + SecP160R1Field.Subtract(V, X3.x, Y3.x); + SecP160R1Field.MultiplyAddToExt(Y3.x, R, tt1); + SecP160R1Field.Reduce(tt1, Y3.x); + + SecP160R1FieldElement Z3 = new SecP160R1FieldElement(H); + if (!Z1IsOne) + { + SecP160R1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP160R1Field.Multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP160R1Point(curve, X3, Y3, zs, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + SecP160R1FieldElement Y1 = (SecP160R1FieldElement)this.RawYCoord; + if (Y1.IsZero) + return curve.Infinity; + + SecP160R1FieldElement X1 = (SecP160R1FieldElement)this.RawXCoord, Z1 = (SecP160R1FieldElement)this.RawZCoords[0]; + + uint c; + uint[] t1 = Nat160.Create(); + uint[] t2 = Nat160.Create(); + + uint[] Y1Squared = Nat160.Create(); + SecP160R1Field.Square(Y1.x, Y1Squared); + + uint[] T = Nat160.Create(); + SecP160R1Field.Square(Y1Squared, T); + + bool Z1IsOne = Z1.IsOne; + + uint[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP160R1Field.Square(Z1.x, Z1Squared); + } + + SecP160R1Field.Subtract(X1.x, Z1Squared, t1); + + uint[] M = t2; + SecP160R1Field.Add(X1.x, Z1Squared, M); + SecP160R1Field.Multiply(M, t1, M); + c = Nat160.AddBothTo(M, M, M); + SecP160R1Field.Reduce32(c, M); + + uint[] S = Y1Squared; + SecP160R1Field.Multiply(Y1Squared, X1.x, S); + c = Nat.ShiftUpBits(5, S, 2, 0); + SecP160R1Field.Reduce32(c, S); + + c = Nat.ShiftUpBits(5, T, 3, 0, t1); + SecP160R1Field.Reduce32(c, t1); + + SecP160R1FieldElement X3 = new SecP160R1FieldElement(T); + SecP160R1Field.Square(M, X3.x); + SecP160R1Field.Subtract(X3.x, S, X3.x); + SecP160R1Field.Subtract(X3.x, S, X3.x); + + SecP160R1FieldElement Y3 = new SecP160R1FieldElement(S); + SecP160R1Field.Subtract(S, X3.x, Y3.x); + SecP160R1Field.Multiply(Y3.x, M, Y3.x); + SecP160R1Field.Subtract(Y3.x, t1, Y3.x); + + SecP160R1FieldElement Z3 = new SecP160R1FieldElement(M); + SecP160R1Field.Twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP160R1Field.Multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP160R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this == b) + return ThreeTimes(); + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECFieldElement Y1 = this.RawYCoord; + if (Y1.IsZero) + return b; + + return Twice().Add(b); + } + + public override ECPoint ThreeTimes() + { + if (this.IsInfinity || this.RawYCoord.IsZero) + return this; + + // NOTE: Be careful about recursions between TwicePlus and ThreeTimes + return Twice().Add(this); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + return new SecP160R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs new file mode 100644 index 000000000..100561453 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R2Curve.cs @@ -0,0 +1,78 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R2Curve + : AbstractFpCurve + { + public static readonly BigInteger q = new BigInteger(1, + Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73")); + + private const int SecP160R2_DEFAULT_COORDS = COORD_JACOBIAN; + + protected readonly SecP160R2Point m_infinity; + + public SecP160R2Curve() + : base(q) + { + this.m_infinity = new SecP160R2Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, + Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70"))); + this.m_b = FromBigInteger(new BigInteger(1, + Hex.Decode("B4E134D3FB59EB8BAB57274904664D5AF50388BA"))); + this.m_order = new BigInteger(1, Hex.Decode("0100000000000000000000351EE786A818F3A1A16B")); + this.m_cofactor = BigInteger.One; + + this.m_coord = SecP160R2_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecP160R2Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public virtual BigInteger Q + { + get { return q; } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return q.BitLength; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecP160R2FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecP160R2Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecP160R2Point(this, x, y, zs, withCompression); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R2Field.cs b/crypto/src/math/ec/custom/sec/SecP160R2Field.cs new file mode 100644 index 000000000..1bef32eea --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R2Field.cs @@ -0,0 +1,178 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R2Field + { + // 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 + internal static readonly uint[] P = new uint[]{ 0xFFFFAC73, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + internal static readonly uint[] PExt = new uint[]{ 0x1B44BBA9, 0x0000A71A, 0x00000001, 0x00000000, 0x00000000, + 0xFFFF58E6, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static readonly uint[] PExtInv = new uint[]{ 0xE4BB4457, 0xFFFF58E5, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, + 0x0000A719, 0x00000002 }; + private const uint P4 = 0xFFFFFFFF; + private const uint PExt9 = 0xFFFFFFFF; + private const uint PInv33 = 0x538D; + + public static void Add(uint[] x, uint[] y, uint[] z) + { + uint c = Nat160.Add(x, y, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.Add33To(5, PInv33, z); + } + } + + public static void AddExt(uint[] xx, uint[] yy, uint[] zz) + { + uint c = Nat.Add(10, xx, yy, zz); + if (c != 0 || (zz[9] == PExt9 && Nat.Gte(10, zz, PExt))) + { + if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.IncAt(10, zz, PExtInv.Length); + } + } + } + + public static void AddOne(uint[] x, uint[] z) + { + uint c = Nat.Inc(5, x, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.Add33To(5, PInv33, z); + } + } + + public static uint[] FromBigInteger(BigInteger x) + { + uint[] z = Nat160.FromBigInteger(x); + if (z[4] == P4 && Nat160.Gte(z, P)) + { + Nat160.SubFrom(P, z); + } + return z; + } + + public static void Half(uint[] x, uint[] z) + { + if ((x[0] & 1) == 0) + { + Nat.ShiftDownBit(5, x, 0, z); + } + else + { + uint c = Nat160.Add(x, P, z); + Nat.ShiftDownBit(5, z, c); + } + } + + public static void Multiply(uint[] x, uint[] y, uint[] z) + { + uint[] tt = Nat160.CreateExt(); + Nat160.Mul(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz) + { + uint c = Nat160.MulAddTo(x, y, zz); + if (c != 0 || (zz[9] == PExt9 && Nat.Gte(10, zz, PExt))) + { + if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.IncAt(10, zz, PExtInv.Length); + } + } + } + + public static void Negate(uint[] x, uint[] z) + { + if (Nat160.IsZero(x)) + { + Nat160.Zero(z); + } + else + { + Nat160.Sub(P, x, z); + } + } + + public static void Reduce(uint[] xx, uint[] z) + { + ulong cc = Nat160.Mul33Add(PInv33, xx, 5, xx, 0, z, 0); + uint c = Nat160.Mul33DWordAdd(PInv33, cc, z, 0); + + Debug.Assert(c == 0 || c == 1); + + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.Add33To(5, PInv33, z); + } + } + + public static void Reduce32(uint x, uint[] z) + { + if ((x != 0 && Nat160.Mul33WordAdd(PInv33, x, z, 0) != 0) + || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.Add33To(5, PInv33, z); + } + } + + public static void Square(uint[] x, uint[] z) + { + uint[] tt = Nat160.CreateExt(); + Nat160.Square(x, tt); + Reduce(tt, z); + } + + public static void SquareN(uint[] x, int n, uint[] z) + { + Debug.Assert(n > 0); + + uint[] tt = Nat160.CreateExt(); + Nat160.Square(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + Nat160.Square(z, tt); + Reduce(tt, z); + } + } + + public static void Subtract(uint[] x, uint[] y, uint[] z) + { + int c = Nat160.Sub(x, y, z); + if (c != 0) + { + Nat.Sub33From(5, PInv33, z); + } + } + + public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz) + { + int c = Nat.Sub(10, xx, yy, zz); + if (c != 0) + { + if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0) + { + Nat.DecAt(10, zz, PExtInv.Length); + } + } + } + + public static void Twice(uint[] x, uint[] z) + { + uint c = Nat.ShiftUpBit(5, x, 0, z); + if (c != 0 || (z[4] == P4 && Nat160.Gte(z, P))) + { + Nat.Add33To(5, PInv33, z); + } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs new file mode 100644 index 000000000..bdb5245b2 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R2FieldElement.cs @@ -0,0 +1,218 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R2FieldElement + : ECFieldElement + { + public static readonly BigInteger Q = SecP160R2Curve.q; + + protected internal readonly uint[] x; + + public SecP160R2FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0) + throw new ArgumentException("value invalid for SecP160R2FieldElement", "x"); + + this.x = SecP160R2Field.FromBigInteger(x); + } + + public SecP160R2FieldElement() + { + this.x = Nat160.Create(); + } + + protected internal SecP160R2FieldElement(uint[] x) + { + this.x = x; + } + + public override bool IsZero + { + get { return Nat160.IsZero(x); } + } + + public override bool IsOne + { + get { return Nat160.IsOne(x); } + } + + public override bool TestBitZero() + { + return Nat160.GetBit(x, 0) == 1; + } + + public override BigInteger ToBigInteger() + { + return Nat160.ToBigInteger(x); + } + + public override string FieldName + { + get { return "SecP160R2Field"; } + } + + public override int FieldSize + { + get { return Q.BitLength; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R2Field.Add(x, ((SecP160R2FieldElement)b).x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement AddOne() + { + uint[] z = Nat160.Create(); + SecP160R2Field.AddOne(x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R2Field.Subtract(x, ((SecP160R2FieldElement)b).x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + uint[] z = Nat160.Create(); + SecP160R2Field.Multiply(x, ((SecP160R2FieldElement)b).x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + // return Multiply(b.invert()); + uint[] z = Nat160.Create(); + Mod.Invert(SecP160R2Field.P, ((SecP160R2FieldElement)b).x, z); + SecP160R2Field.Multiply(z, x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Negate() + { + uint[] z = Nat160.Create(); + SecP160R2Field.Negate(x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Square() + { + uint[] z = Nat160.Create(); + SecP160R2Field.Square(x, z); + return new SecP160R2FieldElement(z); + } + + public override ECFieldElement Invert() + { + // return new SecP160R2FieldElement(ToBigInteger().modInverse(Q)); + uint[] z = Nat160.Create(); + Mod.Invert(SecP160R2Field.P, x, z); + return new SecP160R2FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public override ECFieldElement Sqrt() + { + /* + * Raise this element to the exponent 2^158 - 2^30 - 2^12 - 2^10 - 2^7 - 2^6 - 2^5 - 2^1 - 2^0 + * + * Breaking up the exponent's binary representation into "repunits", we get: { 127 1s } { 1 + * 0s } { 17 1s } { 1 0s } { 1 1s } { 1 0s } { 2 1s } { 3 0s } { 3 1s } { 1 0s } { 1 1s } + * + * Therefore we need an Addition chain containing 1, 2, 3, 17, 127 (the lengths of the repunits) + * We use: [1], [2], [3], 4, 7, 14, [17], 31, 62, 124, [127] + */ + + uint[] x1 = this.x; + if (Nat160.IsZero(x1) || Nat160.IsOne(x1)) + { + return this; + } + + uint[] x2 = Nat160.Create(); + SecP160R2Field.Square(x1, x2); + SecP160R2Field.Multiply(x2, x1, x2); + uint[] x3 = Nat160.Create(); + SecP160R2Field.Square(x2, x3); + SecP160R2Field.Multiply(x3, x1, x3); + uint[] x4 = Nat160.Create(); + SecP160R2Field.Square(x3, x4); + SecP160R2Field.Multiply(x4, x1, x4); + uint[] x7 = Nat160.Create(); + SecP160R2Field.SquareN(x4, 3, x7); + SecP160R2Field.Multiply(x7, x3, x7); + uint[] x14 = x4; + SecP160R2Field.SquareN(x7, 7, x14); + SecP160R2Field.Multiply(x14, x7, x14); + uint[] x17 = x7; + SecP160R2Field.SquareN(x14, 3, x17); + SecP160R2Field.Multiply(x17, x3, x17); + uint[] x31 = Nat160.Create(); + SecP160R2Field.SquareN(x17, 14, x31); + SecP160R2Field.Multiply(x31, x14, x31); + uint[] x62 = x14; + SecP160R2Field.SquareN(x31, 31, x62); + SecP160R2Field.Multiply(x62, x31, x62); + uint[] x124 = x31; + SecP160R2Field.SquareN(x62, 62, x124); + SecP160R2Field.Multiply(x124, x62, x124); + uint[] x127 = x62; + SecP160R2Field.SquareN(x124, 3, x127); + SecP160R2Field.Multiply(x127, x3, x127); + + uint[] t1 = x127; + SecP160R2Field.SquareN(t1, 18, t1); + SecP160R2Field.Multiply(t1, x17, t1); + SecP160R2Field.SquareN(t1, 2, t1); + SecP160R2Field.Multiply(t1, x1, t1); + SecP160R2Field.SquareN(t1, 3, t1); + SecP160R2Field.Multiply(t1, x2, t1); + SecP160R2Field.SquareN(t1, 6, t1); + SecP160R2Field.Multiply(t1, x3, t1); + SecP160R2Field.SquareN(t1, 2, t1); + SecP160R2Field.Multiply(t1, x1, t1); + + uint[] t2 = x2; + SecP160R2Field.Square(t1, t2); + + return Nat160.Eq(x1, t2) ? new SecP160R2FieldElement(t1) : null; + } + + public override bool Equals(object obj) + { + return Equals(obj as SecP160R2FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecP160R2FieldElement); + } + + public virtual bool Equals(SecP160R2FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat160.Eq(x, other.x); + } + + public override int GetHashCode() + { + return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 5); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecP160R2Point.cs b/crypto/src/math/ec/custom/sec/SecP160R2Point.cs new file mode 100644 index 000000000..343cf8c16 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecP160R2Point.cs @@ -0,0 +1,279 @@ +using System; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecP160R2Point + : AbstractFpPoint + { + /** + * Create a point which encodes with point compression. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * + * @deprecated Use ECCurve.CreatePoint to construct points + */ + public SecP160R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * Create a point that encodes with or without point compresion. + * + * @param curve + * the curve to use + * @param x + * affine x co-ordinate + * @param y + * affine y co-ordinate + * @param withCompression + * if true encode with point compression + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(bool)} + */ + public SecP160R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecP160R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecP160R2Point(null, AffineXCoord, AffineYCoord); + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + if (this == b) + return Twice(); + + ECCurve curve = this.Curve; + + SecP160R2FieldElement X1 = (SecP160R2FieldElement)this.RawXCoord, Y1 = (SecP160R2FieldElement)this.RawYCoord; + SecP160R2FieldElement X2 = (SecP160R2FieldElement)b.RawXCoord, Y2 = (SecP160R2FieldElement)b.RawYCoord; + + SecP160R2FieldElement Z1 = (SecP160R2FieldElement)this.RawZCoords[0]; + SecP160R2FieldElement Z2 = (SecP160R2FieldElement)b.RawZCoords[0]; + + uint c; + uint[] tt1 = Nat160.CreateExt(); + uint[] t2 = Nat160.Create(); + uint[] t3 = Nat160.Create(); + uint[] t4 = Nat160.Create(); + + bool Z1IsOne = Z1.IsOne; + uint[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP160R2Field.Square(Z1.x, S2); + + U2 = t2; + SecP160R2Field.Multiply(S2, X2.x, U2); + + SecP160R2Field.Multiply(S2, Z1.x, S2); + SecP160R2Field.Multiply(S2, Y2.x, S2); + } + + bool Z2IsOne = Z2.IsOne; + uint[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP160R2Field.Square(Z2.x, S1); + + U1 = tt1; + SecP160R2Field.Multiply(S1, X1.x, U1); + + SecP160R2Field.Multiply(S1, Z2.x, S1); + SecP160R2Field.Multiply(S1, Y1.x, S1); + } + + uint[] H = Nat160.Create(); + SecP160R2Field.Subtract(U1, U2, H); + + uint[] R = t2; + SecP160R2Field.Subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat160.IsZero(H)) + { + if (Nat160.IsZero(R)) + { + // this == b, i.e. this must be doubled + return this.Twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.Infinity; + } + + uint[] HSquared = t3; + SecP160R2Field.Square(H, HSquared); + + uint[] G = Nat160.Create(); + SecP160R2Field.Multiply(HSquared, H, G); + + uint[] V = t3; + SecP160R2Field.Multiply(HSquared, U1, V); + + SecP160R2Field.Negate(G, G); + Nat160.Mul(S1, G, tt1); + + c = Nat160.AddBothTo(V, V, G); + SecP160R2Field.Reduce32(c, G); + + SecP160R2FieldElement X3 = new SecP160R2FieldElement(t4); + SecP160R2Field.Square(R, X3.x); + SecP160R2Field.Subtract(X3.x, G, X3.x); + + SecP160R2FieldElement Y3 = new SecP160R2FieldElement(G); + SecP160R2Field.Subtract(V, X3.x, Y3.x); + SecP160R2Field.MultiplyAddToExt(Y3.x, R, tt1); + SecP160R2Field.Reduce(tt1, Y3.x); + + SecP160R2FieldElement Z3 = new SecP160R2FieldElement(H); + if (!Z1IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP160R2Point(curve, X3, Y3, zs, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + SecP160R2FieldElement Y1 = (SecP160R2FieldElement)this.RawYCoord; + if (Y1.IsZero) + return curve.Infinity; + + SecP160R2FieldElement X1 = (SecP160R2FieldElement)this.RawXCoord, Z1 = (SecP160R2FieldElement)this.RawZCoords[0]; + + uint c; + uint[] t1 = Nat160.Create(); + uint[] t2 = Nat160.Create(); + + uint[] Y1Squared = Nat160.Create(); + SecP160R2Field.Square(Y1.x, Y1Squared); + + uint[] T = Nat160.Create(); + SecP160R2Field.Square(Y1Squared, T); + + bool Z1IsOne = Z1.IsOne; + + uint[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP160R2Field.Square(Z1.x, Z1Squared); + } + + SecP160R2Field.Subtract(X1.x, Z1Squared, t1); + + uint[] M = t2; + SecP160R2Field.Add(X1.x, Z1Squared, M); + SecP160R2Field.Multiply(M, t1, M); + c = Nat160.AddBothTo(M, M, M); + SecP160R2Field.Reduce32(c, M); + + uint[] S = Y1Squared; + SecP160R2Field.Multiply(Y1Squared, X1.x, S); + c = Nat.ShiftUpBits(5, S, 2, 0); + SecP160R2Field.Reduce32(c, S); + + c = Nat.ShiftUpBits(5, T, 3, 0, t1); + SecP160R2Field.Reduce32(c, t1); + + SecP160R2FieldElement X3 = new SecP160R2FieldElement(T); + SecP160R2Field.Square(M, X3.x); + SecP160R2Field.Subtract(X3.x, S, X3.x); + SecP160R2Field.Subtract(X3.x, S, X3.x); + + SecP160R2FieldElement Y3 = new SecP160R2FieldElement(S); + SecP160R2Field.Subtract(S, X3.x, Y3.x); + SecP160R2Field.Multiply(Y3.x, M, Y3.x); + SecP160R2Field.Subtract(Y3.x, t1, Y3.x); + + SecP160R2FieldElement Z3 = new SecP160R2FieldElement(M); + SecP160R2Field.Twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP160R2Field.Multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP160R2Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this == b) + return ThreeTimes(); + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECFieldElement Y1 = this.RawYCoord; + if (Y1.IsZero) + return b; + + return Twice().Add(b); + } + + public override ECPoint ThreeTimes() + { + if (this.IsInfinity || this.RawYCoord.IsZero) + return this; + + // NOTE: Be careful about recursions between TwicePlus and ThreeTimes + return Twice().Add(this); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + return new SecP160R2Point(Curve, this.RawXCoord, this.RawYCoord.Negate(), this.RawZCoords, IsCompressed); + } + } +} -- cgit 1.4.1 From a6da1221e74d909840ca47be3798f3942f40ebb3 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Costa Beppler Date: Tue, 24 Mar 2015 10:16:11 -0300 Subject: Correct duplicate key exception when more than one signer use the same digest algorithm. --- crypto/src/cms/CMSSignedDataGenerator.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'crypto') diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs index f31105c41..1659a4117 100644 --- a/crypto/src/cms/CMSSignedDataGenerator.cs +++ b/crypto/src/cms/CMSSignedDataGenerator.cs @@ -93,19 +93,24 @@ namespace Org.BouncyCastle.Cms { AlgorithmIdentifier digAlgId = DigestAlgorithmID; string digestName = Helper.GetDigestAlgName(digestOID); - IDigest dig = Helper.GetDigestInstance(digestName); string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID); ISigner sig = Helper.GetSignatureInstance(signatureName); - // TODO Optimise the case where more than one signer with same digest - if (content != null) - { - content.Write(new DigOutputStream(dig)); - } + byte[] hash; - byte[] hash = DigestUtilities.DoFinal(dig); - outer._digests.Add(digestOID, hash.Clone()); + if (outer._digests.Contains(digestOID)) + hash = (byte[])outer._digests[digestOID]; + else + { + IDigest dig = Helper.GetDigestInstance(digestName); + if (content != null) + { + content.Write(new DigOutputStream(dig)); + } + hash = DigestUtilities.DoFinal(dig); + outer._digests.Add(digestOID, hash.Clone()); + } sig.Init(true, new ParametersWithRandom(key, random)); #if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT -- cgit 1.4.1 From 813e5dca6dc23eb82008b1658f44071a8a8a3717 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 24 Mar 2015 22:42:30 +0700 Subject: Add GetHashCode methods for ulong[] --- crypto/src/util/Arrays.cs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'crypto') diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index 8614baead..abea234a7 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -311,6 +311,48 @@ namespace Org.BouncyCastle.Utilities return hc; } + [CLSCompliantAttribute(false)] + public static int GetHashCode(ulong[] data) + { + if (data == null) + return 0; + + int i = data.Length; + int hc = i + 1; + + while (--i >= 0) + { + ulong di = data[i]; + hc *= 257; + hc ^= (int)di; + hc *= 257; + hc ^= (int)(di >> 32); + } + + return hc; + } + + [CLSCompliantAttribute(false)] + public static int GetHashCode(ulong[] data, int off, int len) + { + if (data == null) + return 0; + + int i = len; + int hc = i + 1; + + while (--i >= 0) + { + ulong di = data[off + i]; + hc *= 257; + hc ^= (int)di; + hc *= 257; + hc ^= (int)(di >> 32); + } + + return hc; + } + public static byte[] Clone( byte[] data) { -- cgit 1.4.1 From 63ef85d468f05593c251a6e370d36d717dc08362 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 24 Mar 2015 22:57:22 +0700 Subject: Add custom implementations of SEC binary curves --- crypto/crypto.csproj | 240 ++++++++++++++ crypto/src/crypto/ec/CustomNamedCurves.cs | 367 ++++++++++++++++++++- crypto/src/math/ec/custom/sec/SecT113Field.cs | 180 ++++++++++ .../src/math/ec/custom/sec/SecT113FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT113R1Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT113R1Point.cs | 281 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT113R2Curve.cs | 190 +++++++++++ crypto/src/math/ec/custom/sec/SecT113R2Point.cs | 291 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT131Field.cs | 274 +++++++++++++++ .../src/math/ec/custom/sec/SecT131FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT131R1Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT131R1Point.cs | 287 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT131R2Curve.cs | 190 +++++++++++ crypto/src/math/ec/custom/sec/SecT131R2Point.cs | 283 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT163Field.cs | 272 +++++++++++++++ .../src/math/ec/custom/sec/SecT163FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT163K1Curve.cs | 194 +++++++++++ crypto/src/math/ec/custom/sec/SecT163K1Point.cs | 289 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT163R1Curve.cs | 190 +++++++++++ crypto/src/math/ec/custom/sec/SecT163R1Point.cs | 283 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT163R2Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT163R2Point.cs | 290 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT233Field.cs | 243 ++++++++++++++ .../src/math/ec/custom/sec/SecT233FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT233K1Curve.cs | 196 +++++++++++ crypto/src/math/ec/custom/sec/SecT233K1Point.cs | 302 +++++++++++++++++ crypto/src/math/ec/custom/sec/SecT233R1Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT233R1Point.cs | 282 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT239Field.cs | 249 ++++++++++++++ .../src/math/ec/custom/sec/SecT239FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT239K1Curve.cs | 194 +++++++++++ crypto/src/math/ec/custom/sec/SecT239K1Point.cs | 297 +++++++++++++++++ crypto/src/math/ec/custom/sec/SecT283Field.cs | 335 +++++++++++++++++++ .../src/math/ec/custom/sec/SecT283FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT283K1Curve.cs | 194 +++++++++++ crypto/src/math/ec/custom/sec/SecT283K1Point.cs | 296 +++++++++++++++++ crypto/src/math/ec/custom/sec/SecT283R1Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT283R1Point.cs | 282 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT409Field.cs | 244 ++++++++++++++ .../src/math/ec/custom/sec/SecT409FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT409K1Curve.cs | 194 +++++++++++ crypto/src/math/ec/custom/sec/SecT409K1Point.cs | 296 +++++++++++++++++ crypto/src/math/ec/custom/sec/SecT409R1Curve.cs | 188 +++++++++++ crypto/src/math/ec/custom/sec/SecT409R1Point.cs | 282 ++++++++++++++++ crypto/src/math/ec/custom/sec/SecT571Field.cs | 251 ++++++++++++++ .../src/math/ec/custom/sec/SecT571FieldElement.cs | 213 ++++++++++++ crypto/src/math/ec/custom/sec/SecT571K1Curve.cs | 196 +++++++++++ crypto/src/math/ec/custom/sec/SecT571K1Point.cs | 296 +++++++++++++++++ crypto/src/math/ec/custom/sec/SecT571R1Curve.cs | 193 +++++++++++ crypto/src/math/ec/custom/sec/SecT571R1Point.cs | 286 ++++++++++++++++ 50 files changed, 12040 insertions(+), 1 deletion(-) create mode 100644 crypto/src/math/ec/custom/sec/SecT113Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT113FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT113R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT113R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT113R2Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT113R2Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131R2Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT131R2Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163R2Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT163R2Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT233R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT239Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT239FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT239K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT239K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT283R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT409R1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571Field.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571FieldElement.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571K1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571K1Point.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571R1Curve.cs create mode 100644 crypto/src/math/ec/custom/sec/SecT571R1Point.cs (limited to 'crypto') diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index ec03a3071..cb00f9912 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5403,6 +5403,246 @@ SubType = "Code" BuildAction = "Compile" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + > 15; + private const ulong M57 = ulong.MaxValue >> 7; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat128.FromBigInteger64(x); + Reduce15(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat128.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat128.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3]; + + x1 ^= (x3 << 15) ^ (x3 << 24); + x2 ^= (x3 >> 49) ^ (x3 >> 40); + + x0 ^= (x2 << 15) ^ (x2 << 24); + x1 ^= (x2 >> 49) ^ (x2 >> 40); + + ulong t = x1 >> 49; + z[0] = x0 ^ t ^ (t << 9); + z[1] = x1 & M49; + } + + public static void Reduce15(ulong[] z, int zOff) + { + ulong z1 = z[zOff + 1], t = z1 >> 49; + z[zOff ] ^= t ^ (t << 9); + z[zOff + 1] = z1 & M49; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat128.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat128.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat128.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Three-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong f0 = x[0], f1 = x[1]; + f1 = ((f0 >> 57) ^ (f1 << 7)) & M57; + f0 &= M57; + + ulong g0 = y[0], g1 = y[1]; + g1 = ((g0 >> 57) ^ (g1 << 7)) & M57; + g0 &= M57; + + ulong[] H = new ulong[6]; + + ImplMulw(f0, g0, H, 0); // H(0) 57/56 bits + ImplMulw(f1, g1, H, 2); // H(INF) 57/54 bits + ImplMulw(f0 ^ f1, g0 ^ g1, H, 4); // H(1) 57/56 bits + + ulong r = H[1] ^ H[2]; + ulong z0 = H[0], + z3 = H[3], + z1 = H[4] ^ z0 ^ r, + z2 = H[5] ^ z3 ^ r; + + zz[0] = z0 ^ (z1 << 57); + zz[1] = (z1 >> 7) ^ (z2 << 50); + zz[2] = (z2 >> 14) ^ (z3 << 43); + zz[3] = (z3 >> 21); + } + + protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 57 == 0); + Debug.Assert(y >> 57 == 0); + + ulong[] u = new ulong[8]; + //u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7]; + int k = 48; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 9) > 0); + + h ^= ((x & 0x0100804020100800UL) & (ulong)(((long)y << 7) >> 63)) >> 8; + + Debug.Assert(h >> 49 == 0); + + z[zOff ] = l & M57; + z[zOff + 1] = (l >> 57) ^ (h << 7); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs new file mode 100644 index 000000000..7e9d53e44 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT113FieldElement + : ECFieldElement + { + protected internal readonly ulong[] x; + + public SecT113FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT113FieldElement", "x"); + + this.x = SecT113Field.FromBigInteger(x); + } + + public SecT113FieldElement() + { + this.x = Nat128.Create64(); + } + + protected internal SecT113FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat128.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat128.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1L) != 0L; + } + + public override BigInteger ToBigInteger() + { + return Nat128.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT113Field"; } + } + + public override int FieldSize + { + get { return 113; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat128.Create64(); + SecT113Field.Add(x, ((SecT113FieldElement)b).x, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat128.Create64(); + SecT113Field.AddOne(x, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and Subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat128.Create64(); + SecT113Field.Multiply(x, ((SecT113FieldElement)b).x, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT113FieldElement)b).x; + ulong[] xx = ((SecT113FieldElement)x).x, yx = ((SecT113FieldElement)y).x; + + ulong[] tt = Nat128.CreateExt64(); + SecT113Field.MultiplyAddToExt(ax, bx, tt); + SecT113Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat128.Create64(); + SecT113Field.Reduce(tt, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat128.Create64(); + SecT113Field.Square(x, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT113FieldElement)x).x, yx = ((SecT113FieldElement)y).x; + + ulong[] tt = Nat128.CreateExt64(); + SecT113Field.SquareAddToExt(ax, tt); + SecT113Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat128.Create64(); + SecT113Field.Reduce(tt, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat128.Create64(); + SecT113Field.SquareN(x, pow, z); + return new SecT113FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT113FieldElement( + AbstractF2mCurve.Inverse(113, new int[]{ 9 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Tpb; } + } + + public virtual int M + { + get { return 113; } + } + + public virtual int K1 + { + get { return 9; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT113FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT113FieldElement); + } + + public virtual bool Equals(SecT113FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat128.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 113009 ^ Arrays.GetHashCode(x, 0, 2); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs new file mode 100644 index 000000000..04e69e2a8 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT113R1Curve + : AbstractF2mCurve + { + private const int SecT113R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT113R1Point m_infinity; + + public SecT113R1Curve() + : base(113, 9, 0, 0) + { + this.m_infinity = new SecT113R1Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("003088250CA6E7C7FE649CE85820F7"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00E8BEE4D3E2260744188BE0E9C723"))); + this.m_order = new BigInteger(1, Hex.Decode("0100000000000000D9CCEC8A39E56F")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT113R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT113R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 113; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT113FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT113R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT113R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(113, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 113; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 113; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 9; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Point.cs b/crypto/src/math/ec/custom/sec/SecT113R1Point.cs new file mode 100644 index 000000000..6ecc8b01a --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT113R1Point.cs @@ -0,0 +1,281 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT113R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT113R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT113R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT113R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT113R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT113R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT113R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT113R1Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT113R1Point(Curve, X, L.Add(Z), new ECFieldElement[]{ Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs new file mode 100644 index 000000000..a02db6b25 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs @@ -0,0 +1,190 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT113R2Curve + : AbstractF2mCurve + { + private const int SecT113R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT113R2Point m_infinity; + + public SecT113R2Curve() + : base(113, 9, 0, 0) + { + this.m_infinity = new SecT113R2Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("00689918DBEC7E5A0DD6DFC0AA55C7"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0095E9A9EC9B297BD4BF36E059184F"))); + this.m_order = new BigInteger(1, Hex.Decode("010000000000000108789B2496AF93")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT113R2_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT113R2Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 113; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT113FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT113R2Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT113R2Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(113, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 113; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 113; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 9; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Point.cs b/crypto/src/math/ec/custom/sec/SecT113R2Point.cs new file mode 100644 index 000000000..1453d78c3 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT113R2Point.cs @@ -0,0 +1,291 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT113R2Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT113R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT113R2Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + { + return b; + } + if (b.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT113R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT113R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT113R2Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + { + return b; + } + if (b.IsInfinity) + { + return Twice(); + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT113R2Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT113R2Point(curve, X3, L3, new ECFieldElement[]{ Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT113R2Point(Curve, X, L.Add(Z), new ECFieldElement[]{ Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs new file mode 100644 index 000000000..df75dfcd7 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs @@ -0,0 +1,274 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131Field + { + private const ulong M03 = ulong.MaxValue >> 61; + private const ulong M44 = ulong.MaxValue >> 20; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat192.FromBigInteger64(x); + Reduce61(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat192.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat192.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4]; + + x1 ^= (x4 << 61) ^ (x4 << 63); + x2 ^= (x4 >> 3) ^ (x4 >> 1) ^ x4 ^ (x4 << 5); + x3 ^= (x4 >> 59); + + x0 ^= (x3 << 61) ^ (x3 << 63); + x1 ^= (x3 >> 3) ^ (x3 >> 1) ^ x3 ^ (x3 << 5); + x2 ^= (x3 >> 59); + + ulong t = x2 >> 3; + z[0] = x0 ^ t ^ (t << 2) ^ (t << 3) ^ (t << 8); + z[1] = x1 ^ (t >> 56); + z[2] = x2 & M03; + } + + public static void Reduce61(ulong[] z, int zOff) + { + ulong z2 = z[zOff + 2], t = z2 >> 3; + z[zOff ] ^= t ^ (t << 2) ^ (t << 3) ^ (t << 8); + z[zOff + 1] ^= (t >> 56); + z[zOff + 2] = z2 & M03; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat.Create64(5); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat.Create64(5); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat.Create64(5); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + 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]; + zz[0] = z0 ^ (z1 << 44); + zz[1] = (z1 >> 20) ^ (z2 << 24); + zz[2] = (z2 >> 40) ^ (z3 << 4) + ^ (z4 << 48); + zz[3] = (z3 >> 60) ^ (z5 << 28) + ^ (z4 >> 16); + zz[4] = (z5 >> 36); + zz[5] = 0; + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong f0 = x[0], f1 = x[1], f2 = x[2]; + f2 = ((f1 >> 24) ^ (f2 << 40)) & M44; + f1 = ((f0 >> 44) ^ (f1 << 20)) & M44; + f0 &= M44; + + ulong g0 = y[0], g1 = y[1], g2 = y[2]; + g2 = ((g1 >> 24) ^ (g2 << 40)) & M44; + g1 = ((g0 >> 44) ^ (g1 << 20)) & M44; + g0 &= M44; + + ulong[] H = new ulong[10]; + + ImplMulw(f0, g0, H, 0); // H(0) 44/43 bits + ImplMulw(f2, g2, H, 2); // H(INF) 44/41 bits + + ulong t0 = f0 ^ f1 ^ f2; + ulong t1 = g0 ^ g1 ^ g2; + + ImplMulw(t0, t1, H, 4); // H(1) 44/43 bits + + ulong t2 = (f1 << 1) ^ (f2 << 2); + ulong t3 = (g1 << 1) ^ (g2 << 2); + + ImplMulw(f0 ^ t2, g0 ^ t3, H, 6); // H(t) 44/45 bits + ImplMulw(t0 ^ t2, t1 ^ t3, H, 8); // H(t + 1) 44/45 bits + + ulong t4 = H[6] ^ H[8]; + ulong t5 = H[7] ^ H[9]; + + Debug.Assert(t5 >> 44 == 0); + + // Calculate V + ulong v0 = (t4 << 1) ^ H[6]; + ulong v1 = t4 ^ (t5 << 1) ^ H[7]; + ulong v2 = t5; + + // Calculate U + ulong u0 = H[0]; + ulong u1 = H[1] ^ H[0] ^ H[4]; + ulong u2 = H[1] ^ H[5]; + + // Calculate W + ulong w0 = u0 ^ v0 ^ (H[2] << 4) ^ (H[2] << 1); + ulong w1 = u1 ^ v1 ^ (H[3] << 4) ^ (H[3] << 1); + ulong w2 = u2 ^ v2; + + // Propagate carries + w1 ^= (w0 >> 44); w0 &= M44; + w2 ^= (w1 >> 44); w1 &= M44; + + Debug.Assert((w0 & 1UL) == 0); + + // Divide W by t + + w0 = (w0 >> 1) ^ ((w1 & 1UL) << 43); + w1 = (w1 >> 1) ^ ((w2 & 1UL) << 43); + w2 = (w2 >> 1); + + // Divide W by (t + 1) + + w0 ^= (w0 << 1); + w0 ^= (w0 << 2); + w0 ^= (w0 << 4); + w0 ^= (w0 << 8); + w0 ^= (w0 << 16); + w0 ^= (w0 << 32); + + w0 &= M44; w1 ^= (w0 >> 43); + + w1 ^= (w1 << 1); + w1 ^= (w1 << 2); + w1 ^= (w1 << 4); + w1 ^= (w1 << 8); + w1 ^= (w1 << 16); + w1 ^= (w1 << 32); + + w1 &= M44; w2 ^= (w1 >> 43); + + w2 ^= (w2 << 1); + w2 ^= (w2 << 2); + w2 ^= (w2 << 4); + w2 ^= (w2 << 8); + w2 ^= (w2 << 16); + w2 ^= (w2 << 32); + + Debug.Assert(w2 >> 42 == 0); + + zz[0] = u0; + zz[1] = u1 ^ w0 ^ H[2]; + zz[2] = u2 ^ w1 ^ w0 ^ H[3]; + zz[3] = w2 ^ w1; + zz[4] = w2 ^ H[2]; + zz[5] = H[3]; + + ImplCompactExt(zz); + } + + protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 45 == 0); + Debug.Assert(y >> 45 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6; + int k = 33; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6 + ^ u[(j >> 9) & 7] << 9; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 12) > 0); + + Debug.Assert(h >> 25 == 0); + + z[zOff ] = l & M44; + z[zOff + 1] = (l >> 44) ^ (h << 20); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + + zz[4] = Interleave.Expand8to16((uint)x[2]); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs new file mode 100644 index 000000000..d60c7ed7d --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT131FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT131FieldElement", "x"); + + this.x = SecT131Field.FromBigInteger(x); + } + + public SecT131FieldElement() + { + this.x = Nat192.Create64(); + } + + protected internal SecT131FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat192.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat192.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat192.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT131Field"; } + } + + public override int FieldSize + { + get { return 131; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat192.Create64(); + SecT131Field.Add(x, ((SecT131FieldElement)b).x, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat192.Create64(); + SecT131Field.AddOne(x, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and Subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat192.Create64(); + SecT131Field.Multiply(x, ((SecT131FieldElement)b).x, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT131FieldElement)b).x; + ulong[] xx = ((SecT131FieldElement)x).x, yx = ((SecT131FieldElement)y).x; + + ulong[] tt = Nat.Create64(5); + SecT131Field.MultiplyAddToExt(ax, bx, tt); + SecT131Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat192.Create64(); + SecT131Field.Reduce(tt, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat192.Create64(); + SecT131Field.Square(x, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT131FieldElement)x).x, yx = ((SecT131FieldElement)y).x; + + ulong[] tt = Nat.Create64(5); + SecT131Field.SquareAddToExt(ax, tt); + SecT131Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat192.Create64(); + SecT131Field.Reduce(tt, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat192.Create64(); + SecT131Field.SquareN(x, pow, z); + return new SecT131FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT131FieldElement( + AbstractF2mCurve.Inverse(131, new int[] { 2, 3, 8 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Ppb; } + } + + public virtual int M + { + get { return 131; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 3; } + } + + public virtual int K3 + { + get { return 8; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT131FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT131FieldElement); + } + + public virtual bool Equals(SecT131FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat192.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 131832 ^ Arrays.GetHashCode(x, 0, 3); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs new file mode 100644 index 000000000..789e3c0c3 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131R1Curve + : AbstractF2mCurve + { + private const int SecT131R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT131R1Point m_infinity; + + public SecT131R1Curve() + : base(131, 2, 3, 8) + { + this.m_infinity = new SecT131R1Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("07A11B09A76B562144418FF3FF8C2570B8"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0217C05610884B63B9C6C7291678F9D341"))); + this.m_order = new BigInteger(1, Hex.Decode("0400000000000000023123953A9464B54D")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT131R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT131R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 131; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT131FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT131R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT131R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(131, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 131; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 131; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 3; } + } + + public virtual int K3 + { + get { return 8; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Point.cs b/crypto/src/math/ec/custom/sec/SecT131R1Point.cs new file mode 100644 index 000000000..7afdad89c --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131R1Point.cs @@ -0,0 +1,287 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT131R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT131R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT131R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT131R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT131R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + { + return b; + } + if (b.IsInfinity) + { + return Twice(); + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT131R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT131R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT131R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs new file mode 100644 index 000000000..2004f84ca --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs @@ -0,0 +1,190 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131R2Curve + : AbstractF2mCurve + { + private const int SecT131R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT131R2Point m_infinity; + + public SecT131R2Curve() + : base(131, 2, 3, 8) + { + this.m_infinity = new SecT131R2Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("03E5A88919D7CAFCBF415F07C2176573B2"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("04B8266A46C55657AC734CE38F018F2192"))); + this.m_order = new BigInteger(1, Hex.Decode("0400000000000000016954A233049BA98F")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT131R2_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT131R2Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override int FieldSize + { + get { return 131; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT131FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT131R2Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT131R2Point(this, x, y, zs, withCompression); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(131, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 131; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 131; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 3; } + } + + public virtual int K3 + { + get { return 8; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Point.cs b/crypto/src/math/ec/custom/sec/SecT131R2Point.cs new file mode 100644 index 000000000..be61561da --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT131R2Point.cs @@ -0,0 +1,283 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT131R2Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT131R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT131R2Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT131R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT131R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT131R2Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT131R2Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT131R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT131R2Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs new file mode 100644 index 000000000..2a775e20d --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs @@ -0,0 +1,272 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163Field + { + private const ulong M35 = ulong.MaxValue >> 29; + private const ulong M55 = ulong.MaxValue >> 9; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + zz[5] = xx[5] ^ yy[5]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat192.FromBigInteger64(x); + Reduce29(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat192.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat192.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4], x5 = xx[5]; + + x2 ^= (x5 << 29) ^ (x5 << 32) ^ (x5 << 35) ^ (x5 << 36); + x3 ^= (x5 >> 35) ^ (x5 >> 32) ^ (x5 >> 29) ^ (x5 >> 28); + + x1 ^= (x4 << 29) ^ (x4 << 32) ^ (x4 << 35) ^ (x4 << 36); + x2 ^= (x4 >> 35) ^ (x4 >> 32) ^ (x4 >> 29) ^ (x4 >> 28); + + x0 ^= (x3 << 29) ^ (x3 << 32) ^ (x3 << 35) ^ (x3 << 36); + x1 ^= (x3 >> 35) ^ (x3 >> 32) ^ (x3 >> 29) ^ (x3 >> 28); + + ulong t = x2 >> 35; + z[0] = x0 ^ t ^ (t << 3) ^ (t << 6) ^ (t << 7); + z[1] = x1; + z[2] = x2 & M35; + } + + public static void Reduce29(ulong[] z, int zOff) + { + ulong z2 = z[zOff + 2], t = z2 >> 35; + z[zOff ] ^= t ^ (t << 3) ^ (t << 6) ^ (t << 7); + z[zOff + 2] = z2 & M35; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat192.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat192.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat192.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + 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]; + zz[0] = z0 ^ (z1 << 55); + zz[1] = (z1 >> 9) ^ (z2 << 46); + zz[2] = (z2 >> 18) ^ (z3 << 37); + zz[3] = (z3 >> 27) ^ (z4 << 28); + zz[4] = (z4 >> 36) ^ (z5 << 19); + zz[5] = (z5 >> 45); + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong f0 = x[0], f1 = x[1], f2 = x[2]; + f2 = ((f1 >> 46) ^ (f2 << 18)); + f1 = ((f0 >> 55) ^ (f1 << 9)) & M55; + f0 &= M55; + + ulong g0 = y[0], g1 = y[1], g2 = y[2]; + g2 = ((g1 >> 46) ^ (g2 << 18)); + g1 = ((g0 >> 55) ^ (g1 << 9)) & M55; + g0 &= M55; + + ulong[] H = new ulong[10]; + + ImplMulw(f0, g0, H, 0); // H(0) 55/54 bits + ImplMulw(f2, g2, H, 2); // H(INF) 55/50 bits + + ulong t0 = f0 ^ f1 ^ f2; + ulong t1 = g0 ^ g1 ^ g2; + + ImplMulw(t0, t1, H, 4); // H(1) 55/54 bits + + ulong t2 = (f1 << 1) ^ (f2 << 2); + ulong t3 = (g1 << 1) ^ (g2 << 2); + + ImplMulw(f0 ^ t2, g0 ^ t3, H, 6); // H(t) 55/56 bits + ImplMulw(t0 ^ t2, t1 ^ t3, H, 8); // H(t + 1) 55/56 bits + + ulong t4 = H[6] ^ H[8]; + ulong t5 = H[7] ^ H[9]; + + Debug.Assert(t5 >> 55 == 0); + + // Calculate V + ulong v0 = (t4 << 1) ^ H[6]; + ulong v1 = t4 ^ (t5 << 1) ^ H[7]; + ulong v2 = t5; + + // Calculate U + ulong u0 = H[0]; + ulong u1 = H[1] ^ H[0] ^ H[4]; + ulong u2 = H[1] ^ H[5]; + + // Calculate W + ulong w0 = u0 ^ v0 ^ (H[2] << 4) ^ (H[2] << 1); + ulong w1 = u1 ^ v1 ^ (H[3] << 4) ^ (H[3] << 1); + ulong w2 = u2 ^ v2; + + // Propagate carries + w1 ^= (w0 >> 55); w0 &= M55; + w2 ^= (w1 >> 55); w1 &= M55; + + Debug.Assert((w0 & 1UL) == 0UL); + + // Divide W by t + + w0 = (w0 >> 1) ^ ((w1 & 1UL) << 54); + w1 = (w1 >> 1) ^ ((w2 & 1UL) << 54); + w2 = (w2 >> 1); + + // Divide W by (t + 1) + + w0 ^= (w0 << 1); + w0 ^= (w0 << 2); + w0 ^= (w0 << 4); + w0 ^= (w0 << 8); + w0 ^= (w0 << 16); + w0 ^= (w0 << 32); + + w0 &= M55; w1 ^= (w0 >> 54); + + w1 ^= (w1 << 1); + w1 ^= (w1 << 2); + w1 ^= (w1 << 4); + w1 ^= (w1 << 8); + w1 ^= (w1 << 16); + w1 ^= (w1 << 32); + + w1 &= M55; w2 ^= (w1 >> 54); + + w2 ^= (w2 << 1); + w2 ^= (w2 << 2); + w2 ^= (w2 << 4); + w2 ^= (w2 << 8); + w2 ^= (w2 << 16); + w2 ^= (w2 << 32); + + Debug.Assert(w2 >> 52 == 0); + + zz[0] = u0; + zz[1] = u1 ^ w0 ^ H[2]; + zz[2] = u2 ^ w1 ^ w0 ^ H[3]; + zz[3] = w2 ^ w1; + zz[4] = w2 ^ H[2]; + zz[5] = H[3]; + + ImplCompactExt(zz); + } + + protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 56 == 0); + Debug.Assert(y >> 56 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 3]; + int k = 47; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 9) > 0); + + Debug.Assert(h >> 47 == 0); + + z[zOff ] = l & M55; + z[zOff + 1] = (l >> 55) ^ (h << 9); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + + ulong x2 = x[2]; + zz[4] = Interleave.Expand32to64((uint)x2); + zz[5] = Interleave.Expand8to16((uint)(x2 >> 32)); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs new file mode 100644 index 000000000..0ef421c71 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT163FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT163FieldElement", "x"); + + this.x = SecT163Field.FromBigInteger(x); + } + + public SecT163FieldElement() + { + this.x = Nat192.Create64(); + } + + protected internal SecT163FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat192.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat192.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1L) != 0L; + } + + public override BigInteger ToBigInteger() + { + return Nat192.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT163Field"; } + } + + public override int FieldSize + { + get { return 163; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat192.Create64(); + SecT163Field.Add(x, ((SecT163FieldElement)b).x, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat192.Create64(); + SecT163Field.AddOne(x, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat192.Create64(); + SecT163Field.Multiply(x, ((SecT163FieldElement)b).x, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT163FieldElement)b).x; + ulong[] xx = ((SecT163FieldElement)x).x, yx = ((SecT163FieldElement)y).x; + + ulong[] tt = Nat192.CreateExt64(); + SecT163Field.MultiplyAddToExt(ax, bx, tt); + SecT163Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat192.Create64(); + SecT163Field.Reduce(tt, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat192.Create64(); + SecT163Field.Square(x, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT163FieldElement)x).x, yx = ((SecT163FieldElement)y).x; + + ulong[] tt = Nat192.CreateExt64(); + SecT163Field.SquareAddToExt(ax, tt); + SecT163Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat192.Create64(); + SecT163Field.Reduce(tt, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat192.Create64(); + SecT163Field.SquareN(x, pow, z); + return new SecT163FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT163FieldElement( + AbstractF2mCurve.Inverse(163, new int[] { 3, 6, 7 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Ppb; } + } + + public virtual int M + { + get { return 163; } + } + + public virtual int K1 + { + get { return 3; } + } + + public virtual int K2 + { + get { return 6; } + } + + public virtual int K3 + { + get { return 7; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT163FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT163FieldElement); + } + + public virtual bool Equals(SecT163FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat192.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 163763 ^ Arrays.GetHashCode(x, 0, 3); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs new file mode 100644 index 000000000..1cfd09e1c --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs @@ -0,0 +1,194 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163K1Curve + : AbstractF2mCurve + { + private const int SecT163K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT163K1Point m_infinity; + + public SecT163K1Curve() + : base(163, 3, 6, 7) + { + this.m_infinity = new SecT163K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = this.m_a; + this.m_order = new BigInteger(1, Hex.Decode("04000000000000000000020108A2E0CC0D99F8A5EF")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT163K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT163K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 163; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT163FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT163K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT163K1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(163, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 163; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 163; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 3; } + } + + public virtual int K2 + { + get { return 6; } + } + + public virtual int K3 + { + get { return 7; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Point.cs b/crypto/src/math/ec/custom/sec/SecT163K1Point.cs new file mode 100644 index 000000000..2e3ba57d0 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163K1Point.cs @@ -0,0 +1,289 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT163K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT163K1Point(null, this.AffineXCoord, this.AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.getA()); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + //return new SecT163K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT163K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT163K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT163K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + //return new SecT163K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT163K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(X3); + + return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.getA().Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.getA().Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT163K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT163K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT163K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT163K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs new file mode 100644 index 000000000..fc18e1094 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs @@ -0,0 +1,190 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163R1Curve + : AbstractF2mCurve + { + private const int SecT163R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT163R1Point m_infinity; + + public SecT163R1Curve() + : base(163, 3, 6, 7) + { + this.m_infinity = new SecT163R1Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9"))); + this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT163R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT163R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 163; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT163FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT163R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT163R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(163, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 163; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 163; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 3; } + } + + public virtual int K2 + { + get { return 6; } + } + + public virtual int K3 + { + get { return 7; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Point.cs b/crypto/src/math/ec/custom/sec/SecT163R1Point.cs new file mode 100644 index 000000000..811a09f14 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163R1Point.cs @@ -0,0 +1,283 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT163R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT163R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT163R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT163R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT163R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT163R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT163R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT163R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs new file mode 100644 index 000000000..9efe11c3e --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163R2Curve + : AbstractF2mCurve + { + private const int SecT163R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT163R2Point m_infinity; + + public SecT163R2Curve() + : base(163, 3, 6, 7) + { + this.m_infinity = new SecT163R2Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("020A601907B8C953CA1481EB10512F78744A3205FD"))); + this.m_order = new BigInteger(1, Hex.Decode("040000000000000000000292FE77E70C12A4234C33")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT163R2_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT163R2Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 163; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT163FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT163R2Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT163R2Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(163, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 163; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 163; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 3; } + } + + public virtual int K2 + { + get { return 6; } + } + + public virtual int K3 + { + get { return 7; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Point.cs b/crypto/src/math/ec/custom/sec/SecT163R2Point.cs new file mode 100644 index 000000000..07b3f1fd9 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT163R2Point.cs @@ -0,0 +1,290 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT163R2Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT163R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT163R2Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + { + return Twice(); + } + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + return new SecT163R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT163R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + return new SecT163R2Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + { + return b; + } + if (b.IsInfinity) + { + return Twice(); + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT163R2Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT163R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT163R2Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs new file mode 100644 index 000000000..165fadbf3 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs @@ -0,0 +1,243 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233Field + { + private const ulong M41 = ulong.MaxValue >> 23; + private const ulong M59 = ulong.MaxValue >> 5; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + z[3] = x[3] ^ y[3]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + zz[5] = xx[5] ^ yy[5]; + zz[6] = xx[6] ^ yy[6]; + zz[7] = xx[7] ^ yy[7]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat256.FromBigInteger64(x); + Reduce23(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3]; + ulong x4 = xx[4], x5 = xx[5], x6 = xx[6], x7 = xx[7]; + + x3 ^= (x7 << 23); + x4 ^= (x7 >> 41) ^ (x7 << 33); + x5 ^= (x7 >> 31); + + x2 ^= (x6 << 23); + x3 ^= (x6 >> 41) ^ (x6 << 33); + x4 ^= (x6 >> 31); + + x1 ^= (x5 << 23); + x2 ^= (x5 >> 41) ^ (x5 << 33); + x3 ^= (x5 >> 31); + + x0 ^= (x4 << 23); + x1 ^= (x4 >> 41) ^ (x4 << 33); + x2 ^= (x4 >> 31); + + ulong t = x3 >> 41; + z[0] = x0 ^ t; + z[1] = x1 ^ (t << 10); + z[2] = x2; + z[3] = x3 & M41; + } + + public static void Reduce23(ulong[] z, int zOff) + { + ulong z3 = z[zOff + 3], t = z3 >> 41; + z[zOff ] ^= t; + z[zOff + 1] ^= (t << 10); + z[zOff + 3] = z3 & M41; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + 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]; + zz[0] = z0 ^ (z1 << 59); + zz[1] = (z1 >> 5) ^ (z2 << 54); + zz[2] = (z2 >> 10) ^ (z3 << 49); + zz[3] = (z3 >> 15) ^ (z4 << 44); + zz[4] = (z4 >> 20) ^ (z5 << 39); + zz[5] = (z5 >> 25) ^ (z6 << 34); + zz[6] = (z6 >> 30) ^ (z7 << 29); + zz[7] = (z7 >> 35); + } + + protected static void ImplExpand(ulong[] x, ulong[] z) + { + ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3]; + z[0] = x0 & M59; + z[1] = ((x0 >> 59) ^ (x1 << 5)) & M59; + z[2] = ((x1 >> 54) ^ (x2 << 10)) & M59; + z[3] = ((x2 >> 49) ^ (x3 << 15)); + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong[] f = new ulong[4], g = new ulong[4]; + ImplExpand(x, f); + ImplExpand(y, g); + + ImplMulwAcc(f[0], g[0], zz, 0); + ImplMulwAcc(f[1], g[1], zz, 1); + ImplMulwAcc(f[2], g[2], zz, 2); + ImplMulwAcc(f[3], g[3], zz, 3); + + // U *= (1 - t^n) + for (int i = 5; i > 0; --i) + { + zz[i] ^= zz[i - 1]; + } + + ImplMulwAcc(f[0] ^ f[1], g[0] ^ g[1], zz, 1); + ImplMulwAcc(f[2] ^ f[3], g[2] ^ g[3], zz, 3); + + // V *= (1 - t^2n) + for (int i = 7; i > 1; --i) + { + zz[i] ^= zz[i - 2]; + } + + // Double-length recursion + { + ulong c0 = f[0] ^ f[2], c1 = f[1] ^ f[3]; + ulong d0 = g[0] ^ g[2], d1 = g[1] ^ g[3]; + ImplMulwAcc(c0 ^ c1, d0 ^ d1, zz, 3); + ulong[] t = new ulong[3]; + ImplMulwAcc(c0, d0, t, 0); + ImplMulwAcc(c1, d1, t, 1); + ulong t0 = t[0], t1 = t[1], t2 = t[2]; + zz[2] ^= t0; + zz[3] ^= t0 ^ t1; + zz[4] ^= t2 ^ t1; + zz[5] ^= t2; + } + + ImplCompactExt(zz); + } + + protected static void ImplMulwAcc(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 59 == 0); + Debug.Assert(y >> 59 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7] + ^ (u[(j >> 3) & 7] << 3); + int k = 54; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 6) > 0); + + Debug.Assert(h >> 53 == 0); + + z[zOff ] ^= l & M59; + z[zOff + 1] ^= (l >> 59) ^ (h << 5); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + Interleave.Expand64To128(x[2], zz, 4); + + ulong x3 = x[3]; + zz[6] = Interleave.Expand32to64((uint)x3); + zz[7] = Interleave.Expand16to32((uint)(x3 >> 32)); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs new file mode 100644 index 000000000..439c41d37 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT233FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT233FieldElement", "x"); + + this.x = SecT233Field.FromBigInteger(x); + } + + public SecT233FieldElement() + { + this.x = Nat256.Create64(); + } + + protected internal SecT233FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat256.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat256.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat256.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT233Field"; } + } + + public override int FieldSize + { + get { return 233; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT233Field.Add(x, ((SecT233FieldElement)b).x, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat256.Create64(); + SecT233Field.AddOne(x, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and Subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT233Field.Multiply(x, ((SecT233FieldElement)b).x, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT233FieldElement)b).x; + ulong[] xx = ((SecT233FieldElement)x).x, yx = ((SecT233FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT233Field.MultiplyAddToExt(ax, bx, tt); + SecT233Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT233Field.Reduce(tt, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat256.Create64(); + SecT233Field.Square(x, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT233FieldElement)x).x, yx = ((SecT233FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT233Field.SquareAddToExt(ax, tt); + SecT233Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT233Field.Reduce(tt, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat256.Create64(); + SecT233Field.SquareN(x, pow, z); + return new SecT233FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT233FieldElement( + AbstractF2mCurve.Inverse(233, new int[] { 74 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Tpb; } + } + + public virtual int M + { + get { return 233; } + } + + public virtual int K1 + { + get { return 74; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT233FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT233FieldElement); + } + + public virtual bool Equals(SecT233FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat256.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 2330074 ^ Arrays.GetHashCode(x, 0, 4); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs new file mode 100644 index 000000000..8768eaa81 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs @@ -0,0 +1,196 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233K1Curve + : AbstractF2mCurve + { + private const int SecT233K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT233K1Point m_infinity; + + public SecT233K1Curve() + : base(233, 74, 0, 0) + { + this.m_infinity = new SecT233K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.One); + this.m_order = new BigInteger(1, Hex.Decode("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF")); + this.m_cofactor = BigInteger.ValueOf(4); + + this.m_coord = SecT233K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT233K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override int FieldSize + { + get { return 233; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT233FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT233K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT233K1Point(this, x, y, zs, withCompression); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(233, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 233; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 233; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 74; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Point.cs b/crypto/src/math/ec/custom/sec/SecT233K1Point.cs new file mode 100644 index 000000000..7e7ee8f0b --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233K1Point.cs @@ -0,0 +1,302 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT233K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT233K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + { + return curve.Infinity; + } + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1); + if (X3.IsZero) + { + //return new SecT233K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT233K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT233K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT233K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T; + if (Z1IsOne) + { + T = L1.Square().Add(L1); + } + else + { + T = L1.Add(Z1).Multiply(L1); + } + + if (T.IsZero) + { + //return new SecT233K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT233K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3); + + return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = L1Sq.Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + { + return b.Twice(); + } + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT233K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT233K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT233K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT233K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs new file mode 100644 index 000000000..92795b8a7 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233R1Curve + : AbstractF2mCurve + { + private const int SecT233R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT233R1Point m_infinity; + + public SecT233R1Curve() + : base(233, 74, 0, 0) + { + this.m_infinity = new SecT233R1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD"))); + this.m_order = new BigInteger(1, Hex.Decode("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT233R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT233R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 233; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT233FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT233R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT233R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(233, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 233; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 233; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 74; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Point.cs b/crypto/src/math/ec/custom/sec/SecT233R1Point.cs new file mode 100644 index 000000000..ffac89d15 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT233R1Point.cs @@ -0,0 +1,282 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT233R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT233R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT233R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + return new SecT233R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT233R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + return new SecT233R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT233R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT233R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT233R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs new file mode 100644 index 000000000..1e0824af9 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs @@ -0,0 +1,249 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT239Field + { + private const ulong M47 = ulong.MaxValue >> 17; + private const ulong M60 = ulong.MaxValue >> 4; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + z[3] = x[3] ^ y[3]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + zz[5] = xx[5] ^ yy[5]; + zz[6] = xx[6] ^ yy[6]; + zz[7] = xx[7] ^ yy[7]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat256.FromBigInteger64(x); + Reduce17(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3]; + ulong x4 = xx[4], x5 = xx[5], x6 = xx[6], x7 = xx[7]; + + x3 ^= (x7 << 17); + x4 ^= (x7 >> 47); + x5 ^= (x7 << 47); + x6 ^= (x7 >> 17); + + x2 ^= (x6 << 17); + x3 ^= (x6 >> 47); + x4 ^= (x6 << 47); + x5 ^= (x6 >> 17); + + x1 ^= (x5 << 17); + x2 ^= (x5 >> 47); + x3 ^= (x5 << 47); + x4 ^= (x5 >> 17); + + x0 ^= (x4 << 17); + x1 ^= (x4 >> 47); + x2 ^= (x4 << 47); + x3 ^= (x4 >> 17); + + ulong t = x3 >> 47; + z[0] = x0 ^ t; + z[1] = x1; + z[2] = x2 ^ (t << 30); + z[3] = x3 & M47; + } + + public static void Reduce17(ulong[] z, int zOff) + { + ulong z3 = z[zOff + 3], t = z3 >> 47; + z[zOff ] ^= t; + z[zOff + 2] ^= (t << 30); + z[zOff + 3] = z3 & M47; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + 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]; + zz[0] = z0 ^ (z1 << 60); + zz[1] = (z1 >> 4) ^ (z2 << 56); + zz[2] = (z2 >> 8) ^ (z3 << 52); + zz[3] = (z3 >> 12) ^ (z4 << 48); + zz[4] = (z4 >> 16) ^ (z5 << 44); + zz[5] = (z5 >> 20) ^ (z6 << 40); + zz[6] = (z6 >> 24) ^ (z7 << 36); + zz[7] = (z7 >> 28); + } + + protected static void ImplExpand(ulong[] x, ulong[] z) + { + ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3]; + z[0] = x0 & M60; + z[1] = ((x0 >> 60) ^ (x1 << 4)) & M60; + z[2] = ((x1 >> 56) ^ (x2 << 8)) & M60; + z[3] = ((x2 >> 52) ^ (x3 << 12)); + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong[] f = new ulong[4], g = new ulong[4]; + ImplExpand(x, f); + ImplExpand(y, g); + + ImplMulwAcc(f[0], g[0], zz, 0); + ImplMulwAcc(f[1], g[1], zz, 1); + ImplMulwAcc(f[2], g[2], zz, 2); + ImplMulwAcc(f[3], g[3], zz, 3); + + // U *= (1 - t^n) + for (int i = 5; i > 0; --i) + { + zz[i] ^= zz[i - 1]; + } + + ImplMulwAcc(f[0] ^ f[1], g[0] ^ g[1], zz, 1); + ImplMulwAcc(f[2] ^ f[3], g[2] ^ g[3], zz, 3); + + // V *= (1 - t^2n) + for (int i = 7; i > 1; --i) + { + zz[i] ^= zz[i - 2]; + } + + // Double-length recursion + { + ulong c0 = f[0] ^ f[2], c1 = f[1] ^ f[3]; + ulong d0 = g[0] ^ g[2], d1 = g[1] ^ g[3]; + ImplMulwAcc(c0 ^ c1, d0 ^ d1, zz, 3); + ulong[] t = new ulong[3]; + ImplMulwAcc(c0, d0, t, 0); + ImplMulwAcc(c1, d1, t, 1); + ulong t0 = t[0], t1 = t[1], t2 = t[2]; + zz[2] ^= t0; + zz[3] ^= t0 ^ t1; + zz[4] ^= t2 ^ t1; + zz[5] ^= t2; + } + + ImplCompactExt(zz); + } + + protected static void ImplMulwAcc(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 60 == 0); + Debug.Assert(y >> 60 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7] + ^ (u[(j >> 3) & 7] << 3); + int k = 54; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 6) > 0); + + h ^= ((x & 0x0820820820820820L) & (ulong)(((long)y << 4) >> 63)) >> 5; + + Debug.Assert(h >> 55 == 0); + + z[zOff ] ^= l & M60; + z[zOff + 1] ^= (l >> 60) ^ (h << 4); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + Interleave.Expand64To128(x[2], zz, 4); + + ulong x3 = x[3]; + zz[6] = Interleave.Expand32to64((uint)x3); + zz[7] = Interleave.Expand16to32((uint)(x3 >> 32)); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs new file mode 100644 index 000000000..c89b484b1 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT239FieldElement + : ECFieldElement + { + protected ulong[] x; + + public SecT239FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT239FieldElement", "x"); + + this.x = SecT239Field.FromBigInteger(x); + } + + public SecT239FieldElement() + { + this.x = Nat256.Create64(); + } + + protected internal SecT239FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat256.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat256.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1L) != 0L; + } + + public override BigInteger ToBigInteger() + { + return Nat256.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT239Field"; } + } + + public override int FieldSize + { + get { return 239; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT239Field.Add(x, ((SecT239FieldElement)b).x, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat256.Create64(); + SecT239Field.AddOne(x, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and Subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT239Field.Multiply(x, ((SecT239FieldElement)b).x, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT239FieldElement)b).x; + ulong[] xx = ((SecT239FieldElement)x).x, yx = ((SecT239FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT239Field.MultiplyAddToExt(ax, bx, tt); + SecT239Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT239Field.Reduce(tt, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat256.Create64(); + SecT239Field.Square(x, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT239FieldElement)x).x, yx = ((SecT239FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT239Field.SquareAddToExt(ax, tt); + SecT239Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT239Field.Reduce(tt, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat256.Create64(); + SecT239Field.SquareN(x, pow, z); + return new SecT239FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT239FieldElement( + AbstractF2mCurve.Inverse(239, new int[] { 158 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Tpb; } + } + + public virtual int M + { + get { return 239; } + } + + public virtual int K1 + { + get { return 158; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT239FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT239FieldElement); + } + + public virtual bool Equals(SecT239FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat256.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 23900158 ^ Arrays.GetHashCode(x, 0, 4); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs new file mode 100644 index 000000000..2c73d941f --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs @@ -0,0 +1,194 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT239K1Curve + : AbstractF2mCurve + { + private const int SecT239K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT239K1Point m_infinity; + + public SecT239K1Curve() + : base(239, 158, 0, 0) + { + this.m_infinity = new SecT239K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.One); + this.m_order = new BigInteger(1, Hex.Decode("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5")); + this.m_cofactor = BigInteger.ValueOf(4); + + this.m_coord = SecT239K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT239K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 239; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT239FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT239K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT239K1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(239, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 239; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 239; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 158; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Point.cs b/crypto/src/math/ec/custom/sec/SecT239K1Point.cs new file mode 100644 index 000000000..ac079ad1e --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT239K1Point.cs @@ -0,0 +1,297 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT239K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT239K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT239K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + // X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1); + if (X3.IsZero) + { + //return new SecT239K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT239K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT239K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT239K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T; + if (Z1IsOne) + { + T = L1.Square().Add(L1); + } + else + { + T = L1.Add(Z1).Multiply(L1); + } + + if (T.IsZero) + { + //return new SecT239K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT239K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3); + + return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = L1Sq.Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT239K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT239K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT239K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT239K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs new file mode 100644 index 000000000..9afb27461 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs @@ -0,0 +1,335 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283Field + { + private const ulong M27 = ulong.MaxValue >> 37; + private const ulong M57 = ulong.MaxValue >> 7; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + z[3] = x[3] ^ y[3]; + z[4] = x[4] ^ y[4]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + zz[5] = xx[5] ^ yy[5]; + zz[6] = xx[6] ^ yy[6]; + zz[7] = xx[7] ^ yy[7]; + zz[8] = xx[8] ^ yy[8]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat320.FromBigInteger64(x); + Reduce37(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat320.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat320.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4]; + ulong x5 = xx[5], x6 = xx[6], x7 = xx[7], x8 = xx[8]; + + x3 ^= (x8 << 37) ^ (x8 << 42) ^ (x8 << 44) ^ (x8 << 49); + x4 ^= (x8 >> 27) ^ (x8 >> 22) ^ (x8 >> 20) ^ (x8 >> 15); + + x2 ^= (x7 << 37) ^ (x7 << 42) ^ (x7 << 44) ^ (x7 << 49); + x3 ^= (x7 >> 27) ^ (x7 >> 22) ^ (x7 >> 20) ^ (x7 >> 15); + + x1 ^= (x6 << 37) ^ (x6 << 42) ^ (x6 << 44) ^ (x6 << 49); + x2 ^= (x6 >> 27) ^ (x6 >> 22) ^ (x6 >> 20) ^ (x6 >> 15); + + x0 ^= (x5 << 37) ^ (x5 << 42) ^ (x5 << 44) ^ (x5 << 49); + x1 ^= (x5 >> 27) ^ (x5 >> 22) ^ (x5 >> 20) ^ (x5 >> 15); + + ulong t = x4 >> 27; + z[0] = x0 ^ t ^ (t << 5) ^ (t << 7) ^ (t << 12); + z[1] = x1; + z[2] = x2; + z[3] = x3; + z[4] = x4 & M27; + } + + public static void Reduce37(ulong[] z, int zOff) + { + ulong z4 = z[zOff + 4], t = z4 >> 27; + z[zOff ] ^= t ^ (t << 5) ^ (t << 7) ^ (t << 12); + z[zOff + 4] = z4 & M27; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat.Create64(9); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat.Create64(9); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat.Create64(9); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + protected static void ImplCompactExt(ulong[] zz) + { + ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4]; + ulong z5 = zz[5], z6 = zz[6], z7 = zz[7], z8 = zz[8], z9 = zz[9]; + zz[0] = z0 ^ (z1 << 57); + zz[1] = (z1 >> 7) ^ (z2 << 50); + zz[2] = (z2 >> 14) ^ (z3 << 43); + zz[3] = (z3 >> 21) ^ (z4 << 36); + zz[4] = (z4 >> 28) ^ (z5 << 29); + zz[5] = (z5 >> 35) ^ (z6 << 22); + zz[6] = (z6 >> 42) ^ (z7 << 15); + zz[7] = (z7 >> 49) ^ (z8 << 8); + zz[8] = (z8 >> 56) ^ (z9 << 1); + zz[9] = (z9 >> 63); // Zero! + } + + protected static void ImplExpand(ulong[] x, ulong[] z) + { + ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4]; + z[0] = x0 & M57; + z[1] = ((x0 >> 57) ^ (x1 << 7)) & M57; + z[2] = ((x1 >> 50) ^ (x2 << 14)) & M57; + z[3] = ((x2 >> 43) ^ (x3 << 21)) & M57; + z[4] = ((x3 >> 36) ^ (x4 << 28)); + } + + //protected static void AddMs(ulong[] zz, int zOff, ulong[] p, params int[] ms) + //{ + // ulong t0 = 0, t1 = 0; + // foreach (int m in ms) + // { + // int i = (m - 1) << 1; + // t0 ^= p[i ]; + // t1 ^= p[i + 1]; + // } + // zz[zOff ] ^= t0; + // zz[zOff + 1] ^= t1; + //} + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * Formula (17) from "Some New Results on Binary Polynomial Multiplication", + * Murat Cenk and M. Anwar Hasan. + * + * The formula as given contained an error in the term t25, as noted below + */ + ulong[] a = new ulong[5], b = new ulong[5]; + ImplExpand(x, a); + ImplExpand(y, b); + + ulong[] p = new ulong[26]; + + ImplMulw(a[0], b[0], p, 0); // m1 + ImplMulw(a[1], b[1], p, 2); // m2 + ImplMulw(a[2], b[2], p, 4); // m3 + ImplMulw(a[3], b[3], p, 6); // m4 + ImplMulw(a[4], b[4], p, 8); // m5 + + ulong u0 = a[0] ^ a[1], v0 = b[0] ^ b[1]; + ulong u1 = a[0] ^ a[2], v1 = b[0] ^ b[2]; + ulong u2 = a[2] ^ a[4], v2 = b[2] ^ b[4]; + ulong u3 = a[3] ^ a[4], v3 = b[3] ^ b[4]; + + ImplMulw(u1 ^ a[3], v1 ^ b[3], p, 18); // m10 + ImplMulw(u2 ^ a[1], v2 ^ b[1], p, 20); // m11 + + ulong A4 = u0 ^ u3 , B4 = v0 ^ v3; + ulong A5 = A4 ^ a[2], B5 = B4 ^ b[2]; + + ImplMulw(A4, B4, p, 22); // m12 + ImplMulw(A5, B5, p, 24); // m13 + + ImplMulw(u0, v0, p, 10); // m6 + ImplMulw(u1, v1, p, 12); // m7 + ImplMulw(u2, v2, p, 14); // m8 + ImplMulw(u3, v3, p, 16); // m9 + + + // Original method, corresponding to formula (16) + //AddMs(zz, 0, p, 1); + //AddMs(zz, 1, p, 1, 2, 6); + //AddMs(zz, 2, p, 1, 2, 3, 7); + //AddMs(zz, 3, p, 1, 3, 4, 5, 8, 10, 12, 13); + //AddMs(zz, 4, p, 1, 2, 4, 5, 6, 9, 10, 11, 13); + //AddMs(zz, 5, p, 1, 2, 3, 5, 7, 11, 12, 13); + //AddMs(zz, 6, p, 3, 4, 5, 8); + //AddMs(zz, 7, p, 4, 5, 9); + //AddMs(zz, 8, p, 5); + + // Improved method factors out common single-word terms + // NOTE: p1,...,p26 in the paper maps to p[0],...,p[25] here + + zz[0] = p[ 0]; + zz[9] = p[ 9]; + + ulong t1 = p[ 0] ^ p[ 1]; + ulong t2 = t1 ^ p[ 2]; + ulong t3 = t2 ^ p[10]; + + zz[1] = t3; + + ulong t4 = p[ 3] ^ p[ 4]; + ulong t5 = p[11] ^ p[12]; + ulong t6 = t4 ^ t5; + ulong t7 = t2 ^ t6; + + zz[2] = t7; + + ulong t8 = t1 ^ t4; + ulong t9 = p[ 5] ^ p[ 6]; + ulong t10 = t8 ^ t9; + ulong t11 = t10 ^ p[ 8]; + ulong t12 = p[13] ^ p[14]; + ulong t13 = t11 ^ t12; + ulong t14 = p[18] ^ p[22]; + ulong t15 = t14 ^ p[24]; + ulong t16 = t13 ^ t15; + + zz[3] = t16; + + ulong t17 = p[ 7] ^ p[ 8]; + ulong t18 = t17 ^ p[ 9]; + ulong t19 = t18 ^ p[17]; + + zz[8] = t19; + + ulong t20 = t18 ^ t9; + ulong t21 = p[15] ^ p[16]; + ulong t22 = t20 ^ t21; + + zz[7] = t22; + + ulong t23 = t22 ^ t3; + ulong t24 = p[19] ^ p[20]; + // ulong t25 = p[23] ^ p[24]; + ulong t25 = p[25] ^ p[24]; // Fixes an error in the paper: p[23] -> p{25] + ulong t26 = p[18] ^ p[23]; + ulong t27 = t24 ^ t25; + ulong t28 = t27 ^ t26; + ulong t29 = t28 ^ t23; + + zz[4] = t29; + + ulong t30 = t7 ^ t19; + ulong t31 = t27 ^ t30; + ulong t32 = p[21] ^ p[22]; + ulong t33 = t31 ^ t32; + + zz[5] = t33; + + ulong t34 = t11 ^ p[0]; + ulong t35 = t34 ^ p[9]; + ulong t36 = t35 ^ t12; + ulong t37 = t36 ^ p[21]; + ulong t38 = t37 ^ p[23]; + ulong t39 = t38 ^ p[25]; + + zz[6] = t39; + + ImplCompactExt(zz); + } + + protected static void ImplMulw(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 57 == 0); + Debug.Assert(y >> 57 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7]; + int k = 48; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 9) > 0); + + h ^= ((x & 0x0100804020100800L) & (ulong)(((long)y << 7) >> 63)) >> 8; + + Debug.Assert(h >> 49 == 0); + + z[zOff ] = l & M57; + z[zOff + 1] = (l >> 57) ^ (h << 7); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + for (int i = 0; i < 4; ++i) + { + Interleave.Expand64To128(x[i], zz, i << 1); + } + zz[8] = Interleave.Expand32to64((uint)x[4]); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs new file mode 100644 index 000000000..09243e859 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT283FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT283FieldElement", "x"); + + this.x = SecT283Field.FromBigInteger(x); + } + + public SecT283FieldElement() + { + this.x = Nat320.Create64(); + } + + protected internal SecT283FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat320.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat320.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat320.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT283Field"; } + } + + public override int FieldSize + { + get { return 283; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat320.Create64(); + SecT283Field.Add(x, ((SecT283FieldElement)b).x, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat320.Create64(); + SecT283Field.AddOne(x, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat320.Create64(); + SecT283Field.Multiply(x, ((SecT283FieldElement)b).x, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT283FieldElement)b).x; + ulong[] xx = ((SecT283FieldElement)x).x, yx = ((SecT283FieldElement)y).x; + + ulong[] tt = Nat.Create64(9); + SecT283Field.MultiplyAddToExt(ax, bx, tt); + SecT283Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat320.Create64(); + SecT283Field.Reduce(tt, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat320.Create64(); + SecT283Field.Square(x, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT283FieldElement)x).x, yx = ((SecT283FieldElement)y).x; + + ulong[] tt = Nat.Create64(9); + SecT283Field.SquareAddToExt(ax, tt); + SecT283Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat320.Create64(); + SecT283Field.Reduce(tt, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat320.Create64(); + SecT283Field.SquareN(x, pow, z); + return new SecT283FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT283FieldElement( + AbstractF2mCurve.Inverse(283, new int[] { 5, 7, 12 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Ppb; } + } + + public virtual int M + { + get { return 283; } + } + + public virtual int K1 + { + get { return 5; } + } + + public virtual int K2 + { + get { return 7; } + } + + public virtual int K3 + { + get { return 12; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT283FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT283FieldElement); + } + + public virtual bool Equals(SecT283FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat320.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 2831275 ^ Arrays.GetHashCode(x, 0, 5); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs new file mode 100644 index 000000000..42414401f --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs @@ -0,0 +1,194 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283K1Curve + : AbstractF2mCurve + { + private const int SecT283K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT283K1Point m_infinity; + + public SecT283K1Curve() + : base(283, 5, 7, 12) + { + this.m_infinity = new SecT283K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.One); + this.m_order = new BigInteger(1, Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61")); + this.m_cofactor = BigInteger.ValueOf(4); + + this.m_coord = SecT283K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT283K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 283; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT283FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT283K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT283K1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(283, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 283; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 283; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 5; } + } + + public virtual int K2 + { + get { return 7; } + } + + public virtual int K3 + { + get { return 12; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Point.cs b/crypto/src/math/ec/custom/sec/SecT283K1Point.cs new file mode 100644 index 000000000..f85706c63 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283K1Point.cs @@ -0,0 +1,296 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT283K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT283K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1); + if (X3.IsZero) + { + //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT283K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT283K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT283K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T; + if (Z1IsOne) + { + T = L1.Square().Add(L1); + } + else + { + T = L1.Add(Z1).Multiply(L1); + } + + if (T.IsZero) + { + //return new SecT283K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT283K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3); + + return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = L1Sq.Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT283K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT283K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT283K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT283K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs new file mode 100644 index 000000000..d8c462eeb --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283R1Curve + : AbstractF2mCurve + { + private const int SecT283R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT283R1Point m_infinity; + + public SecT283R1Curve() + : base(283, 5, 7, 12) + { + this.m_infinity = new SecT283R1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5"))); + this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT283R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT283R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 283; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT283FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT283R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT283R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(283, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 283; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 283; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 5; } + } + + public virtual int K2 + { + get { return 7; } + } + + public virtual int K3 + { + get { return 12; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Point.cs b/crypto/src/math/ec/custom/sec/SecT283R1Point.cs new file mode 100644 index 000000000..340bbdae6 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT283R1Point.cs @@ -0,0 +1,282 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT283R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT283R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT283R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + return new SecT283R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT283R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + return new SecT283R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT283R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT283R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT283R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs new file mode 100644 index 000000000..d71f5b5f9 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs @@ -0,0 +1,244 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409Field + { + private const ulong M25 = ulong.MaxValue >> 39; + private const ulong M59 = ulong.MaxValue >> 5; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + z[3] = x[3] ^ y[3]; + z[4] = x[4] ^ y[4]; + z[5] = x[5] ^ y[5]; + z[6] = x[6] ^ y[6]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + for (int i = 0; i < 13; ++i) + { + zz[i] = xx[i] ^ yy[i]; + } + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat448.FromBigInteger64(x); + Reduce39(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat448.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat448.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x00 = xx[0], x01 = xx[1], x02 = xx[2], x03 = xx[3]; + ulong x04 = xx[4], x05 = xx[5], x06 = xx[6], x07 = xx[7]; + + ulong u = xx[12]; + x05 ^= (u << 39); + x06 ^= (u >> 25) ^ (u << 62); + x07 ^= (u >> 2); + + u = xx[11]; + x04 ^= (u << 39); + x05 ^= (u >> 25) ^ (u << 62); + x06 ^= (u >> 2); + + u = xx[10]; + x03 ^= (u << 39); + x04 ^= (u >> 25) ^ (u << 62); + x05 ^= (u >> 2); + + u = xx[9]; + x02 ^= (u << 39); + x03 ^= (u >> 25) ^ (u << 62); + x04 ^= (u >> 2); + + u = xx[8]; + x01 ^= (u << 39); + x02 ^= (u >> 25) ^ (u << 62); + x03 ^= (u >> 2); + + u = x07; + x00 ^= (u << 39); + x01 ^= (u >> 25) ^ (u << 62); + x02 ^= (u >> 2); + + ulong t = x06 >> 25; + z[0] = x00 ^ t; + z[1] = x01 ^ (t << 23); + z[2] = x02; + z[3] = x03; + z[4] = x04; + z[5] = x05; + z[6] = x06 & M25; + } + + public static void Reduce39(ulong[] z, int zOff) + { + ulong z6 = z[zOff + 6], t = z6 >> 25; + z[zOff ] ^= t; + z[zOff + 1] ^= (t << 23); + z[zOff + 6] = z6 & M25; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat.Create64(13); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat.Create64(13); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat.Create64(13); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + 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]; + ulong z07 = zz[ 7], z08 = zz[ 8], z09 = zz[ 9], z10 = zz[10], z11 = zz[11], z12 = zz[12], z13 = zz[13]; + zz[ 0] = z00 ^ (z01 << 59); + zz[ 1] = (z01 >> 5) ^ (z02 << 54); + zz[ 2] = (z02 >> 10) ^ (z03 << 49); + zz[ 3] = (z03 >> 15) ^ (z04 << 44); + zz[ 4] = (z04 >> 20) ^ (z05 << 39); + zz[ 5] = (z05 >> 25) ^ (z06 << 34); + zz[ 6] = (z06 >> 30) ^ (z07 << 29); + zz[ 7] = (z07 >> 35) ^ (z08 << 24); + zz[ 8] = (z08 >> 40) ^ (z09 << 19); + zz[ 9] = (z09 >> 45) ^ (z10 << 14); + zz[10] = (z10 >> 50) ^ (z11 << 9); + zz[11] = (z11 >> 55) ^ (z12 << 4) + ^ (z13 << 63); + zz[12] = (z12 >> 60) + ^ (z13 >> 1); + zz[13] = 0; + } + + protected static void ImplExpand(ulong[] x, ulong[] z) + { + ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6]; + z[0] = x0 & M59; + z[1] = ((x0 >> 59) ^ (x1 << 5)) & M59; + z[2] = ((x1 >> 54) ^ (x2 << 10)) & M59; + z[3] = ((x2 >> 49) ^ (x3 << 15)) & M59; + z[4] = ((x3 >> 44) ^ (x4 << 20)) & M59; + z[5] = ((x4 >> 39) ^ (x5 << 25)) & M59; + z[6] = ((x5 >> 34) ^ (x6 << 30)); + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] a = new ulong[7], b = new ulong[7]; + ImplExpand(x, a); + ImplExpand(y, b); + + for (int i = 0; i < 7; ++i) + { + ImplMulwAcc(a, b[i], zz, i); + } + + ImplCompactExt(zz); + } + + protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff) + { + Debug.Assert(y >> 59 == 0); + + ulong[] u = new ulong[8]; + // u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + for (int i = 0; i < 7; ++i) + { + ulong x = xs[i]; + + Debug.Assert(x >> 59 == 0); + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7] + ^ (u[(j >> 3) & 7] << 3); + int k = 54; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 6) > 0); + + Debug.Assert(h >> 53 == 0); + + z[zOff + i ] ^= l & M59; + z[zOff + i + 1] ^= (l >> 59) ^ (h << 5); + } + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + for (int i = 0; i < 6; ++i) + { + Interleave.Expand64To128(x[i], zz, i << 1); + } + zz[12] = Interleave.Expand32to64((uint)x[6]); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs new file mode 100644 index 000000000..6dabf6a7a --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409FieldElement + : ECFieldElement + { + protected ulong[] x; + + public SecT409FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT409FieldElement", "x"); + + this.x = SecT409Field.FromBigInteger(x); + } + + public SecT409FieldElement() + { + this.x = Nat448.Create64(); + } + + protected internal SecT409FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat448.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat448.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat448.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT409Field"; } + } + + public override int FieldSize + { + get { return 409; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat448.Create64(); + SecT409Field.Add(x, ((SecT409FieldElement)b).x, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat448.Create64(); + SecT409Field.AddOne(x, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat448.Create64(); + SecT409Field.Multiply(x, ((SecT409FieldElement)b).x, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT409FieldElement)b).x; + ulong[] xx = ((SecT409FieldElement)x).x, yx = ((SecT409FieldElement)y).x; + + ulong[] tt = Nat.Create64(13); + SecT409Field.MultiplyAddToExt(ax, bx, tt); + SecT409Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat448.Create64(); + SecT409Field.Reduce(tt, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat448.Create64(); + SecT409Field.Square(x, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT409FieldElement)x).x, yx = ((SecT409FieldElement)y).x; + + ulong[] tt = Nat.Create64(13); + SecT409Field.SquareAddToExt(ax, tt); + SecT409Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat448.Create64(); + SecT409Field.Reduce(tt, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat448.Create64(); + SecT409Field.SquareN(x, pow, z); + return new SecT409FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT409FieldElement( + AbstractF2mCurve.Inverse(409, new int[] { 87 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Tpb; } + } + + public virtual int M + { + get { return 409; } + } + + public virtual int K1 + { + get { return 87; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT409FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT409FieldElement); + } + + public virtual bool Equals(SecT409FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat448.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 4090087 ^ Arrays.GetHashCode(x, 0, 7); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs new file mode 100644 index 000000000..edfe1a293 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs @@ -0,0 +1,194 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409K1Curve + : AbstractF2mCurve + { + private const int SecT409K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT409K1Point m_infinity; + + public SecT409K1Curve() + : base(409, 87, 0, 0) + { + this.m_infinity = new SecT409K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.One); + this.m_order = new BigInteger(1, Hex.Decode("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF")); + this.m_cofactor = BigInteger.ValueOf(4); + + this.m_coord = SecT409K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT409K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 409; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT409FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT409K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT409K1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(409, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 409; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 409; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 87; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Point.cs b/crypto/src/math/ec/custom/sec/SecT409K1Point.cs new file mode 100644 index 000000000..71adc7af2 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409K1Point.cs @@ -0,0 +1,296 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT409K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT409K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1); + if (X3.IsZero) + { + //return new SecT409K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT409K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT409K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT409K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T; + if (Z1IsOne) + { + T = L1.Square().Add(L1); + } + else + { + T = L1.Add(Z1).Multiply(L1); + } + + if (T.IsZero) + { + //return new SecT409K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT409K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3); + + return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = L1Sq.Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT409K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT409K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT409K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT409K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs new file mode 100644 index 000000000..e679094ad --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs @@ -0,0 +1,188 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409R1Curve + : AbstractF2mCurve + { + private const int SecT409R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT409R1Point m_infinity; + + public SecT409R1Curve() + : base(409, 87, 0, 0) + { + this.m_infinity = new SecT409R1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F"))); + this.m_order = new BigInteger(1, Hex.Decode("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT409R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT409R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 409; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT409FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT409R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT409R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(409, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 409; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 409; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 87; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Point.cs b/crypto/src/math/ec/custom/sec/SecT409R1Point.cs new file mode 100644 index 000000000..af69fe656 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT409R1Point.cs @@ -0,0 +1,282 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT409R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT409R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT409R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + return new SecT409R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT409R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + return new SecT409R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT409R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT409R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT409R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs new file mode 100644 index 000000000..0711ee4aa --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs @@ -0,0 +1,251 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571Field + { + private const ulong M59 = ulong.MaxValue >> 5; + + private const ulong RM = 0xEF7BDEF7BDEF7BDEUL; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + for (int i = 0; i < 9; ++i) + { + z[i] = x[i] ^ y[i]; + } + } + + private static void Add(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff) + { + for (int i = 0; i < 9; ++i) + { + z[zOff + i] = x[xOff + i] ^ y[yOff + i]; + } + } + + private static void AddBothTo(ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff) + { + for (int i = 0; i < 9; ++i) + { + z[zOff + i] ^= x[xOff + i] ^ y[yOff + i]; + } + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + for (int i = 0; i < 18; ++i) + { + zz[i] = xx[i] ^ yy[i]; + } + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + for (int i = 1; i < 9; ++i) + { + z[i] = x[i]; + } + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat576.FromBigInteger64(x); + Reduce5(z, 0); + return z; + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat576.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat576.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong xx09 = xx[9]; + ulong u = xx[17], v = xx09; + + xx09 = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49); + v = xx[8] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15); + + for (int i = 16; i >= 10; --i) + { + u = xx[i]; + z[i - 8] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49); + v = xx[i - 9] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15); + } + + u = xx09; + z[1] = v ^ (u >> 59) ^ (u >> 57) ^ (u >> 54) ^ (u >> 49); + v = xx[0] ^ (u << 5) ^ (u << 7) ^ (u << 10) ^ (u << 15); + + ulong x08 = z[8]; + ulong t = x08 >> 59; + z[0] = v ^ t ^ (t << 2) ^ (t << 5) ^ (t << 10); + z[8] = x08 & M59; + } + + public static void Reduce5(ulong[] z, int zOff) + { + ulong z8 = z[zOff + 8], t = z8 >> 59; + z[zOff ] ^= t ^ (t << 2) ^ (t << 5) ^ (t << 10); + z[zOff + 8] = z8 & M59; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat576.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat576.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat576.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + //for (int i = 0; i < 9; ++i) + //{ + // ImplMulwAcc(x, y[i], zz, i); + //} + + /* + * Precompute table of all 4-bit products of y + */ + ulong[] T0 = new ulong[9 << 4]; + Array.Copy(y, 0, T0, 9, 9); + // Reduce5(T0, 9); + int tOff = 0; + for (int i = 7; i > 0; --i) + { + tOff += 18; + Nat.ShiftUpBit64(9, T0, tOff >> 1, 0UL, T0, tOff); + Reduce5(T0, tOff); + Add(T0, 9, T0, tOff, T0, tOff + 9); + } + + /* + * Second table with all 4-bit products of B shifted 4 bits + */ + ulong[] T1 = new ulong[T0.Length]; + Nat.ShiftUpBits64(T0.Length, T0, 0, 4, 0L, T1, 0); + + uint MASK = 0xF; + + /* + * Lopez-Dahab algorithm + */ + + for (int k = 56; k >= 0; k -= 8) + { + for (int j = 1; j < 9; j += 2) + { + uint aVal = (uint)(x[j] >> k); + uint u = aVal & MASK; + uint v = (aVal >> 4) & MASK; + AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j - 1); + } + Nat.ShiftUpBits64(16, zz, 0, 8, 0L); + } + + for (int k = 56; k >= 0; k -= 8) + { + for (int j = 0; j < 9; j += 2) + { + uint aVal = (uint)(x[j] >> k); + uint u = aVal & MASK; + uint v = (aVal >> 4) & MASK; + AddBothTo(T0, (int)(9 * u), T1, (int)(9 * v), zz, j); + } + if (k > 0) + { + Nat.ShiftUpBits64(18, zz, 0, 8, 0L); + } + } + } + + protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff) + { + ulong[] u = new ulong[32]; + // u[0] = 0; + u[1] = y; + for (int i = 2; i < 32; i += 2) + { + u[i ] = u[i >> 1] << 1; + u[i + 1] = u[i ] ^ y; + } + + ulong l = 0; + for (int i = 0; i < 9; ++i) + { + ulong x = xs[i]; + + uint j = (uint)x; + + l ^= u[j & 31]; + + ulong g, h = 0; + int k = 60; + do + { + j = (uint)(x >> k); + g = u[j & 31]; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 5) > 0); + + for (int p = 0; p < 4; ++p) + { + x = (x & RM) >> 1; + h ^= x & (ulong)(((long)y << p) >> 63); + } + + z[zOff + i] ^= l; + + l = h; + } + z[zOff + 9] ^= l; + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + for (int i = 0; i < 9; ++i) + { + Interleave.Expand64To128(x[i], zz, i << 1); + } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs new file mode 100644 index 000000000..8474c912e --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs @@ -0,0 +1,213 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT571FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0) + throw new ArgumentException("value invalid for SecT571FieldElement", "x"); + + this.x = SecT571Field.FromBigInteger(x); + } + + public SecT571FieldElement() + { + this.x = Nat576.Create64(); + } + + protected internal SecT571FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat576.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat576.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat576.ToBigInteger64(x); + } + + public override String FieldName + { + get { return "SecT571Field"; } + } + + public override int FieldSize + { + get { return 571; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat576.Create64(); + SecT571Field.Add(x, ((SecT571FieldElement)b).x, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat576.Create64(); + SecT571Field.AddOne(x, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat576.Create64(); + SecT571Field.Multiply(x, ((SecT571FieldElement)b).x, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT571FieldElement)b).x; + ulong[] xx = ((SecT571FieldElement)x).x, yx = ((SecT571FieldElement)y).x; + + ulong[] tt = Nat576.CreateExt64(); + SecT571Field.MultiplyAddToExt(ax, bx, tt); + SecT571Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat576.Create64(); + SecT571Field.Reduce(tt, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat576.Create64(); + SecT571Field.Square(x, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT571FieldElement)x).x, yx = ((SecT571FieldElement)y).x; + + ulong[] tt = Nat576.CreateExt64(); + SecT571Field.SquareAddToExt(ax, tt); + SecT571Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat576.Create64(); + SecT571Field.Reduce(tt, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat576.Create64(); + SecT571Field.SquareN(x, pow, z); + return new SecT571FieldElement(z); + } + + public override ECFieldElement Invert() + { + return new SecT571FieldElement( + AbstractF2mCurve.Inverse(571, new int[] { 2, 5, 10 }, ToBigInteger())); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Ppb; } + } + + public virtual int M + { + get { return 571; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 5; } + } + + public virtual int K3 + { + get { return 10; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT571FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT571FieldElement); + } + + public virtual bool Equals(SecT571FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat576.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 5711052 ^ Arrays.GetHashCode(x, 0, 9); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs new file mode 100644 index 000000000..fb136c967 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs @@ -0,0 +1,196 @@ +using System; + +using Org.BouncyCastle.Math.EC.Multiplier; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571K1Curve + : AbstractF2mCurve + { + private const int SecT571K1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT571K1Point m_infinity; + + public SecT571K1Curve() + : base(571, 2, 5, 10) + { + this.m_infinity = new SecT571K1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.Zero); + this.m_b = FromBigInteger(BigInteger.One); + this.m_order = new BigInteger(1, Hex.Decode("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001")); + this.m_cofactor = BigInteger.ValueOf(4); + + this.m_coord = SecT571K1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT571K1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + protected override ECMultiplier CreateDefaultMultiplier() + { + return new WTauNafMultiplier(); + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 571; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT571FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT571K1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT571K1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return true; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(571, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 571; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 571; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 5; } + } + + public virtual int K3 + { + get { return 10; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Point.cs b/crypto/src/math/ec/custom/sec/SecT571K1Point.cs new file mode 100644 index 000000000..62ed7bda0 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571K1Point.cs @@ -0,0 +1,296 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571K1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT571K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT571K1Point(null, this.AffineXCoord, this.AffineYCoord); // earlier JDK + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + //return new SecT571K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT571K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT571K1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT571K1Point(curve, X3, curve.B, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T; + if (Z1IsOne) + { + T = L1.Square().Add(L1); + } + else + { + T = L1.Add(Z1).Multiply(L1); + } + + if (T.IsZero) + { + //return new SecT571K1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT571K1Point(curve, T, curve.B, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement t1 = L1.Add(X1).Square(); + ECFieldElement t2 = Z1IsOne ? Z1 : Z1Sq.Square(); + ECFieldElement L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3); + + return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + // NOTE: TwicePlus() only optimized for lambda-affine argument + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = L1Sq.Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT571K1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT571K1Point(curve, A, curve.B, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT571K1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT571K1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs new file mode 100644 index 000000000..05d58863e --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs @@ -0,0 +1,193 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571R1Curve + : AbstractF2mCurve + { + private const int SecT571R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT571R1Point m_infinity; + + internal static readonly SecT571FieldElement SecT571R1_B = new SecT571FieldElement( + new BigInteger(1, Hex.Decode("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A"))); + internal static readonly SecT571FieldElement SecT571R1_B_SQRT = (SecT571FieldElement)SecT571R1_B.Sqrt(); + + public SecT571R1Curve() + : base(571, 2, 5, 10) + { + this.m_infinity = new SecT571R1Point(this, null, null); + + this.m_a = FromBigInteger(BigInteger.One); + this.m_b = SecT571R1_B; + this.m_order = new BigInteger(1, Hex.Decode("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT571R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT571R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 571; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT571FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT571R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT571R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + // y = B.Sqrt(); + y = SecT571R1_B_SQRT; + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation z2 + z = beta(X9.62 + * D.1.6) The other solution is z + 1. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for z2 + z = beta or + * null if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + return beta; + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(571, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 571; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 571; } + } + + public virtual bool IsTrinomial + { + get { return false; } + } + + public virtual int K1 + { + get { return 2; } + } + + public virtual int K2 + { + get { return 5; } + } + + public virtual int K3 + { + get { return 10; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Point.cs b/crypto/src/math/ec/custom/sec/SecT571R1Point.cs new file mode 100644 index 000000000..0cbc98cf3 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT571R1Point.cs @@ -0,0 +1,286 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT571R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT571R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT571R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + //X3 = L.Square().Add(L).Add(X1).Add(curve.A); + X3 = L.Square().Add(L).Add(X1).AddOne(); + if (X3.IsZero) + { + //return new SecT571R1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT571R1Point(curve, X3, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + //return new SecT571R1Point(curve, X3, curve.B.sqrt(), IsCompressed); + return new SecT571R1Point(curve, X3, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement T = L1.Square().Add(L1Z1).Add(Z1Sq); + if (T.IsZero) + { + //return new SecT571R1Point(curve, T, curve.B.sqrt(), withCompression); + return new SecT571R1Point(curve, T, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + //ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement T = Z1Sq.Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + //ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement A = L2.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + //return new SecT571R1Point(curve, A, curve.B.sqrt(), withCompression); + return new SecT571R1Point(curve, A, SecT571R1Curve.SecT571R1_B_SQRT, IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT571R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT571R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} -- cgit 1.4.1 From 4ae9f1d15ece3597624e9335f300f2829e25db27 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 24 Mar 2015 22:58:19 +0700 Subject: Delete spurious file --- crypto/TestResult.xml | 1985 ------------------------------------------------- 1 file changed, 1985 deletions(-) delete mode 100644 crypto/TestResult.xml (limited to 'crypto') diff --git a/crypto/TestResult.xml b/crypto/TestResult.xml deleted file mode 100644 index 047a66cb3..000000000 --- a/crypto/TestResult.xml +++ /dev/null @@ -1,1985 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- cgit 1.4.1 From 3d88159d06742c44948972112e854cbc29e8a8ba Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 25 Mar 2015 21:46:51 +0700 Subject: Include ANSSI curves in getByOID lookup --- crypto/src/asn1/x9/ECNamedCurveTable.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/asn1/x9/ECNamedCurveTable.cs b/crypto/src/asn1/x9/ECNamedCurveTable.cs index 70b04a583..d8315c16f 100644 --- a/crypto/src/asn1/x9/ECNamedCurveTable.cs +++ b/crypto/src/asn1/x9/ECNamedCurveTable.cs @@ -98,12 +98,17 @@ namespace Org.BouncyCastle.Asn1.X9 ecP = SecNamedCurves.GetByOid(oid); } + // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup + if (ecP == null) { ecP = TeleTrusTNamedCurves.GetByOid(oid); } - // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup + if (ecP == null) + { + ecP = AnssiNamedCurves.GetByOid(oid); + } return ecP; } -- cgit 1.4.1 From cbd8f700e65fc66dced3a4a0ae75213a2ade0eb7 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 25 Mar 2015 22:36:55 +0700 Subject: Formatting --- crypto/src/cms/CMSSignedDataGenerator.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs index 1659a4117..114b9631d 100644 --- a/crypto/src/cms/CMSSignedDataGenerator.cs +++ b/crypto/src/cms/CMSSignedDataGenerator.cs @@ -98,9 +98,10 @@ namespace Org.BouncyCastle.Cms ISigner sig = Helper.GetSignatureInstance(signatureName); byte[] hash; - if (outer._digests.Contains(digestOID)) + { hash = (byte[])outer._digests[digestOID]; + } else { IDigest dig = Helper.GetDigestInstance(digestName); -- cgit 1.4.1 From 37ebe56013377b5d5aaa2bf8b15ca9d8ea68d3ed Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 26 Mar 2015 14:01:31 +0700 Subject: F2mCurve cleanup --- crypto/src/math/ec/ECAlgorithms.cs | 18 +++++++++++++----- crypto/src/util/Arrays.cs | 16 ++++++++++++++++ crypto/test/src/math/ec/test/TnafTest.cs | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs index a1349a9e0..5d60de40f 100644 --- a/crypto/src/math/ec/ECAlgorithms.cs +++ b/crypto/src/math/ec/ECAlgorithms.cs @@ -10,14 +10,23 @@ namespace Org.BouncyCastle.Math.EC { public static bool IsF2mCurve(ECCurve c) { - IFiniteField field = c.Field; + return IsF2mField(c.Field); + } + + public static bool IsF2mField(IFiniteField field) + { return field.Dimension > 1 && field.Characteristic.Equals(BigInteger.Two) && field is IPolynomialExtensionField; } public static bool IsFpCurve(ECCurve c) { - return c.Field.Dimension == 1; + return IsFpField(c.Field); + } + + public static bool IsFpField(IFiniteField field) + { + return field.Dimension == 1; } public static ECPoint SumOfMultiplies(ECPoint[] ps, BigInteger[] ks) @@ -61,10 +70,9 @@ namespace Org.BouncyCastle.Math.EC Q = ImportPoint(cp, Q); // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick - if (cp is F2mCurve) { - F2mCurve f2mCurve = (F2mCurve) cp; - if (f2mCurve.IsKoblitz) + AbstractF2mCurve f2mCurve = cp as AbstractF2mCurve; + if (f2mCurve != null && f2mCurve.IsKoblitz) { return ValidatePoint(P.Multiply(a).Add(Q.Multiply(b))); } diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index abea234a7..1f9711555 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -655,5 +655,21 @@ namespace Org.BouncyCastle.Utilities return result; } + + public static int[] Reverse(int[] a) + { + if (a == null) + return null; + + int p1 = 0, p2 = a.Length; + int[] result = new int[p2]; + + while (--p2 >= 0) + { + result[p2] = a[p1++]; + } + + return result; + } } } diff --git a/crypto/test/src/math/ec/test/TnafTest.cs b/crypto/test/src/math/ec/test/TnafTest.cs index c04ae00d2..f5a58e858 100644 --- a/crypto/test/src/math/ec/test/TnafTest.cs +++ b/crypto/test/src/math/ec/test/TnafTest.cs @@ -40,7 +40,7 @@ // { // X9ECParameters x9ECParameters = SecNamedCurves.GetByName(curveName); // -// F2mCurve curve = (F2mCurve)x9ECParameters.Curve; +// AbstractF2mCurve curve = (AbstractF2mCurve)x9ECParameters.Curve; // BigInteger n = curve.N; // // // The generator is multiplied by random b to get random q -- cgit 1.4.1 From da8b8b5d20ede0797f98fe6ea8c6e6277e38cf8c Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 14 Oct 2014 14:49:51 -0400 Subject: Added AES, IDEA, and CAST5 CBC S/MIME Capability identifiers --- crypto/src/asn1/smime/SMIMECapabilities.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'crypto') diff --git a/crypto/src/asn1/smime/SMIMECapabilities.cs b/crypto/src/asn1/smime/SMIMECapabilities.cs index ca3c3af7d..5fb67dde1 100644 --- a/crypto/src/asn1/smime/SMIMECapabilities.cs +++ b/crypto/src/asn1/smime/SMIMECapabilities.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.X509; @@ -25,6 +26,11 @@ namespace Org.BouncyCastle.Asn1.Smime /** * encryption algorithms preferences */ + public static readonly DerObjectIdentifier Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc; + public static readonly DerObjectIdentifier Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc; + public static readonly DerObjectIdentifier Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc; + public static readonly DerObjectIdentifier IdeaCbc = new DerObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2"); + public static readonly DerObjectIdentifier Cast5Cbc = new DerObjectIdentifier("1.2.840.113533.7.66.10"); public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7"); public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc; public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc; -- cgit 1.4.1 From 525129e163323f739636eed10af888f633390417 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 26 Mar 2015 16:39:04 +0700 Subject: Retain the OID actually used when initialized by keysize - Thanks to Kyle Hamilton for the patch (see bcgit/bc-csharp#16) --- crypto/src/crypto/generators/ECKeyPairGenerator.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'crypto') diff --git a/crypto/src/crypto/generators/ECKeyPairGenerator.cs b/crypto/src/crypto/generators/ECKeyPairGenerator.cs index 6e777c74c..d4afff750 100644 --- a/crypto/src/crypto/generators/ECKeyPairGenerator.cs +++ b/crypto/src/crypto/generators/ECKeyPairGenerator.cs @@ -78,6 +78,7 @@ namespace Org.BouncyCastle.Crypto.Generators X9ECParameters ecps = FindECCurveByOid(oid); + this.publicKeyParamSet = oid; this.parameters = new ECDomainParameters( ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed()); } -- cgit 1.4.1 From 47c7ecf546892d8cacadbd3ef3a946e326d6d6c2 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 26 Mar 2015 17:15:53 +0700 Subject: Provide a KeyContainerName when creating an RSACryptoServiceProvider - Thanks to Frederik Carlier for reporting and providing a fix (see JIRA BMA-130) --- crypto/src/security/DotNetUtilities.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/src/security/DotNetUtilities.cs b/crypto/src/security/DotNetUtilities.cs index d50e17d39..732b5e075 100644 --- a/crypto/src/security/DotNetUtilities.cs +++ b/crypto/src/security/DotNetUtilities.cs @@ -233,7 +233,9 @@ namespace Org.BouncyCastle.Security private static RSA CreateRSAProvider(RSAParameters rp) { - RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(); + CspParameters csp = new CspParameters(); + csp.KeyContainerName = string.Format("BouncyCastle-{0}", Guid.NewGuid()); + RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(csp); rsaCsp.ImportParameters(rp); return rsaCsp; } -- cgit 1.4.1 From dc0edd9ca359e7874d165f99dfd92791928bb985 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 26 Mar 2015 21:50:54 +0700 Subject: Improved docs and code cleanup --- .../crypto/generators/DsaParametersGenerator.cs | 57 +++++----------------- 1 file changed, 11 insertions(+), 46 deletions(-) (limited to 'crypto') diff --git a/crypto/src/crypto/generators/DsaParametersGenerator.cs b/crypto/src/crypto/generators/DsaParametersGenerator.cs index cf6343a16..d7ae3ec54 100644 --- a/crypto/src/crypto/generators/DsaParametersGenerator.cs +++ b/crypto/src/crypto/generators/DsaParametersGenerator.cs @@ -31,13 +31,11 @@ namespace Org.BouncyCastle.Crypto.Generators this.digest = digest; } - /** - * initialise the key generator. - * - * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments) - * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80). - * @param random random byte source. - */ + /// Initialise the generator + /// This form can only be used for older DSA (pre-DSA2) parameters + /// the size of keys in bits (from 512 up to 1024, and a multiple of 64) + /// measure of robustness of primes (at least 80 for FIPS 186-2 compliance) + /// the source of randomness to use public virtual void Init( int size, int certainty, @@ -53,14 +51,9 @@ namespace Org.BouncyCastle.Crypto.Generators this.random = random; } - /** - * Initialise the key generator for DSA 2. - *

- * Use this init method if you need to generate parameters for DSA 2 keys. - *

- * - * @param params DSA 2 key generation parameters. - */ + /// Initialise the generator for DSA 2 + /// You must use this Init method if you need to generate parameters for DSA 2 keys + /// An instance of DsaParameterGenerationParameters used to configure this generator public virtual void Init(DsaParameterGenerationParameters parameters) { // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1? @@ -84,35 +77,8 @@ namespace Org.BouncyCastle.Crypto.Generators throw new InvalidOperationException("Digest output size too small for value of N"); } -// /** -// * add value to b, returning the result in a. The a value is treated -// * as a BigInteger of length (a.Length * 8) bits. The result is -// * modulo 2^a.Length in case of overflow. -// */ -// private static void Add( -// byte[] a, -// byte[] b, -// int value) -// { -// int x = (b[b.Length - 1] & 0xff) + value; -// -// a[b.Length - 1] = (byte)x; -// x = (int) ((uint) x >>8); -// -// for (int i = b.Length - 2; i >= 0; i--) -// { -// x += (b[i] & 0xff); -// a[i] = (byte)x; -// x = (int) ((uint) x >>8); -// } -// } - - /** - * which Generates the p and g values from the given parameters, - * returning the DsaParameters object. - *

- * Note: can take a while...

- */ + /// Generates a set of DsaParameters + /// Can take a while... public virtual DsaParameters GenerateParameters() { return use186_3 @@ -242,8 +208,7 @@ namespace Org.BouncyCastle.Crypto.Generators BigInteger U = new BigInteger(1, output).Mod(BigInteger.One.ShiftLeft(N - 1)); // 7. q = 2^(N–1) + U + 1 – ( U mod 2). - BigInteger q = BigInteger.One.ShiftLeft(N - 1).Add(U).Add(BigInteger.One).Subtract( - U.Mod(BigInteger.Two)); + BigInteger q = U.SetBit(0).SetBit(N - 1); // 8. Test whether or not q is prime as specified in Appendix C.3. // TODO Review C.3 for primality checking -- cgit 1.4.1 From 703ef7118a82ba378ed2ebdf7ca7a061339af8f2 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 27 Mar 2015 11:54:06 +0700 Subject: ValidDays only returns 0 if there is no expiry, and is Obsolete - Thanks to Severin Friede for reporting (see JIRA BMA-127) --- crypto/src/openpgp/PgpPublicKey.cs | 47 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'crypto') diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs index c6b2e9e0e..249b94ea6 100644 --- a/crypto/src/openpgp/PgpPublicKey.cs +++ b/crypto/src/openpgp/PgpPublicKey.cs @@ -266,16 +266,23 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } /// The number of valid days from creation time - zero means no expiry. + /// WARNING: This method will return 1 for keys with version > 3 that expire in less than 1 day + [Obsolete("Use 'GetValidSeconds' instead")] public int ValidDays { get { - if (publicPk.Version > 3) + if (publicPk.Version <= 3) { - return (int)(GetValidSeconds() / (24 * 60 * 60)); + return publicPk.ValidDays; } - return publicPk.ValidDays; + long expSecs = GetValidSeconds(); + if (expSecs <= 0) + return 0; + + int days = (int)(expSecs / (24 * 60 * 60)); + return System.Math.Max(1, days); } } @@ -294,34 +301,32 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// The number of valid seconds from creation time - zero means no expiry. public long GetValidSeconds() { - if (publicPk.Version > 3) + if (publicPk.Version <= 3) { - if (IsMasterKey) - { - for (int i = 0; i != MasterKeyCertificationTypes.Length; i++) - { - long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]); + return (long)publicPk.ValidDays * (24 * 60 * 60); + } - if (seconds >= 0) - { - return seconds; - } - } - } - else + if (IsMasterKey) + { + for (int i = 0; i != MasterKeyCertificationTypes.Length; i++) { - long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding); - + long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]); if (seconds >= 0) { return seconds; } } - - return 0; + } + else + { + long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding); + if (seconds >= 0) + { + return seconds; + } } - return (long) publicPk.ValidDays * 24 * 60 * 60; + return 0; } private long GetExpirationTimeFromSig( -- cgit 1.4.1 From da7d43dcc83fb8e5d4d97cc89dd00c75a7625cd2 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 30 Mar 2015 15:15:47 +0700 Subject: Update version to 1.8.0-RC.1 prior to release --- crypto/NBuild.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/NBuild.build b/crypto/NBuild.build index eada08eee..64ea07545 100644 --- a/crypto/NBuild.build +++ b/crypto/NBuild.build @@ -16,7 +16,7 @@ - + -- cgit 1.4.1