summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2016-01-05 08:38:03 -0500
committerOren Novotny <oren@novotny.org>2016-01-05 08:38:03 -0500
commitd74e0ee364cfde298eb077d9cd58d452c0aa0329 (patch)
tree53f1061193bd3c2e58e2ee91de33ea3b2c4221ec /crypto/src
parentUpdate description (diff)
parentUpdate versions and release notes for release 1.8.1 (diff)
downloadBouncyCastle.NET-ed25519-d74e0ee364cfde298eb077d9cd58d452c0aa0329.tar.xz
Merge branch 'master' into pcl
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/AssemblyInfo.cs9
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs4
-rw-r--r--crypto/src/asn1/Asn1TaggedObject.cs10
-rw-r--r--crypto/src/asn1/DERExternal.cs15
-rw-r--r--crypto/src/asn1/DerApplicationSpecific.cs2
-rw-r--r--crypto/src/asn1/DerGraphicString.cs103
-rw-r--r--crypto/src/asn1/DerVideotexString.cs103
-rw-r--r--crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs35
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs8
-rw-r--r--crypto/src/crypto/engines/SerpentEngineBase.cs9
-rw-r--r--crypto/src/crypto/macs/VMPCMac.cs2
-rw-r--r--crypto/src/crypto/signers/Iso9796d2PssSigner.cs9
-rw-r--r--crypto/src/crypto/signers/PssSigner.cs57
-rw-r--r--crypto/src/crypto/tls/AbstractTlsClient.cs11
-rw-r--r--crypto/src/crypto/tls/AbstractTlsKeyExchange.cs11
-rw-r--r--crypto/src/crypto/tls/DeferredHash.cs2
-rw-r--r--crypto/src/crypto/tls/DtlsClientProtocol.cs11
-rw-r--r--crypto/src/crypto/tls/DtlsRecordLayer.cs30
-rw-r--r--crypto/src/crypto/tls/DtlsServerProtocol.cs38
-rw-r--r--crypto/src/crypto/tls/HashAlgorithm.cs28
-rw-r--r--crypto/src/crypto/tls/TlsClient.cs12
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsECDheKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsServerProtocol.cs20
-rw-r--r--crypto/src/crypto/tls/TlsSrpKeyExchange.cs2
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs42
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113Field.cs16
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163Field.cs27
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193Field.cs23
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233Field.cs41
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239Field.cs42
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283Field.cs32
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409Field.cs36
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409FieldElement.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571Field.cs31
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571FieldElement.cs4
-rw-r--r--crypto/src/math/raw/Interleave.cs12
45 files changed, 800 insertions, 100 deletions
diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs

index 239347365..bb9811d83 100644 --- a/crypto/src/AssemblyInfo.cs +++ b/crypto/src/AssemblyInfo.cs
@@ -33,9 +33,9 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.8.0.0")] -[assembly: AssemblyFileVersion("1.8.0.0")] -[assembly: AssemblyInformationalVersion("1.8.0.0")] +[assembly: AssemblyVersion("1.8.1.0")] +[assembly: AssemblyFileVersion("1.8.15362.1")] +[assembly: AssemblyInformationalVersion("1.8.1")] // // In order to sign your assembly you must specify a key to use. Refer to the @@ -65,10 +65,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyDelaySign(false)] #if STRONG_NAME [assembly: AssemblyKeyFile(@"../BouncyCastle.snk")] -#else -[assembly: AssemblyKeyFile("")] #endif -[assembly: AssemblyKeyName("")] [assembly: CLSCompliant(true)] #if !PORTABLE diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 501e788a0..a94ae5235 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -337,6 +337,8 @@ namespace Org.BouncyCastle.Asn1 return new DerGeneralizedTime(bytes); case Asn1Tags.GeneralString: return new DerGeneralString(bytes); + case Asn1Tags.GraphicString: + return new DerGraphicString(bytes); case Asn1Tags.IA5String: return new DerIA5String(bytes); case Asn1Tags.Integer: @@ -357,6 +359,8 @@ namespace Org.BouncyCastle.Asn1 return new DerUtcTime(bytes); case Asn1Tags.Utf8String: return new DerUtf8String(bytes); + case Asn1Tags.VideotexString: + return new DerVideotexString(bytes); case Asn1Tags.VisibleString: return new DerVisibleString(bytes); default: diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs
index fdf5b651a..a6d4b2c28 100644 --- a/crypto/src/asn1/Asn1TaggedObject.cs +++ b/crypto/src/asn1/Asn1TaggedObject.cs
@@ -12,6 +12,16 @@ namespace Org.BouncyCastle.Asn1 public abstract class Asn1TaggedObject : Asn1Object, Asn1TaggedObjectParser { + internal static bool IsConstructed(bool isExplicit, Asn1Object obj) + { + if (isExplicit || obj is Asn1Sequence || obj is Asn1Set) + return true; + Asn1TaggedObject tagged = obj as Asn1TaggedObject; + if (tagged == null) + return false; + return IsConstructed(tagged.IsExplicit(), tagged.GetObject()); + } + internal int tagNo; // internal bool empty; internal bool explicitly = true; diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs
index a342d6520..c29975193 100644 --- a/crypto/src/asn1/DERExternal.cs +++ b/crypto/src/asn1/DERExternal.cs
@@ -34,25 +34,20 @@ namespace Org.BouncyCastle.Asn1 offset++; enc = GetObjFromVector(vector, offset); } - if (!(enc is DerTaggedObject)) + if (!(enc is Asn1TaggedObject)) { - dataValueDescriptor = (Asn1Object) enc; + dataValueDescriptor = enc; offset++; enc = GetObjFromVector(vector, offset); } - if (!(enc is DerTaggedObject)) - { - throw new InvalidOperationException( - "No tagged object found in vector. Structure doesn't seem to be of type External"); - } - if (vector.Count != offset + 1) + if (vector.Count != offset + 1) throw new ArgumentException("input vector too large", "vector"); - if (!(enc is DerTaggedObject)) + if (!(enc is Asn1TaggedObject)) throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector"); - DerTaggedObject obj = (DerTaggedObject)enc; + Asn1TaggedObject obj = (Asn1TaggedObject)enc; // Use property accessor to include check on value Encoding = obj.TagNo; diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index 9149930e0..52467fabe 100644 --- a/crypto/src/asn1/DerApplicationSpecific.cs +++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1 byte[] data = asn1Obj.GetDerEncoded(); - this.isConstructed = isExplicit || asn1Obj is Asn1Set || asn1Obj is Asn1Sequence; + this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj); this.tag = tag; if (isExplicit) diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs new file mode 100644
index 000000000..f213f461d --- /dev/null +++ b/crypto/src/asn1/DerGraphicString.cs
@@ -0,0 +1,103 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerGraphicString + : DerStringBase + { + private readonly byte[] mString; + + /** + * return a Graphic String from the passed in object + * + * @param obj a DerGraphicString or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return a DerGraphicString instance, or null. + */ + public static DerGraphicString GetInstance(object obj) + { + if (obj == null || obj is DerGraphicString) + { + return (DerGraphicString)obj; + } + + if (obj is byte[]) + { + try + { + return (DerGraphicString)FromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj"); + } + } + + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); + } + + /** + * return a Graphic String from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the tagged object cannot + * be converted. + * @return a DerGraphicString instance, or null. + */ + public static DerGraphicString GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerGraphicString) + { + return GetInstance(o); + } + + return new DerGraphicString(((Asn1OctetString)o).GetOctets()); + } + + /** + * basic constructor - with bytes. + * @param string the byte encoding of the characters making up the string. + */ + public DerGraphicString(byte[] encoding) + { + this.mString = Arrays.Clone(encoding); + } + + public override string GetString() + { + return Strings.FromByteArray(mString); + } + + public byte[] GetOctets() + { + return Arrays.Clone(mString); + } + + internal override void Encode(DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.GraphicString, mString); + } + + protected override int Asn1GetHashCode() + { + return Arrays.GetHashCode(mString); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerGraphicString other = asn1Object as DerGraphicString; + + if (other == null) + return false; + + return Arrays.AreEqual(mString, other.mString); + } + } +} diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs new file mode 100644
index 000000000..b25401044 --- /dev/null +++ b/crypto/src/asn1/DerVideotexString.cs
@@ -0,0 +1,103 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1 +{ + public class DerVideotexString + : DerStringBase + { + private readonly byte[] mString; + + /** + * return a Videotex String from the passed in object + * + * @param obj a DERVideotexString or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERVideotexString instance, or null. + */ + public static DerVideotexString GetInstance(object obj) + { + if (obj == null || obj is DerVideotexString) + { + return (DerVideotexString)obj; + } + + if (obj is byte[]) + { + try + { + return (DerVideotexString)FromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new ArgumentException("encoding error in GetInstance: " + e.ToString(), "obj"); + } + } + + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); + } + + /** + * return a Videotex String from a tagged object. + * + * @param obj the tagged object holding the object we want + * @param explicit true if the object is meant to be explicitly + * tagged false otherwise. + * @exception IllegalArgumentException if the tagged object cannot + * be converted. + * @return a DERVideotexString instance, or null. + */ + public static DerVideotexString GetInstance(Asn1TaggedObject obj, bool isExplicit) + { + Asn1Object o = obj.GetObject(); + + if (isExplicit || o is DerVideotexString) + { + return GetInstance(o); + } + + return new DerVideotexString(((Asn1OctetString)o).GetOctets()); + } + + /** + * basic constructor - with bytes. + * @param string the byte encoding of the characters making up the string. + */ + public DerVideotexString(byte[] encoding) + { + this.mString = Arrays.Clone(encoding); + } + + public override string GetString() + { + return Strings.FromByteArray(mString); + } + + public byte[] GetOctets() + { + return Arrays.Clone(mString); + } + + internal override void Encode(DerOutputStream derOut) + { + derOut.WriteEncoded(Asn1Tags.VideotexString, mString); + } + + protected override int Asn1GetHashCode() + { + return Arrays.GetHashCode(mString); + } + + protected override bool Asn1Equals( + Asn1Object asn1Object) + { + DerVideotexString other = asn1Object as DerVideotexString; + + if (other == null) + return false; + + return Arrays.AreEqual(mString, other.mString); + } + } +} diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
index 0b2ffa0d1..042911a06 100644 --- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs +++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -118,6 +118,8 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier Pkcs9AtSigningDescription = new DerObjectIdentifier(Pkcs9 + ".13"); public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest = new DerObjectIdentifier(Pkcs9 + ".14"); public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities = new DerObjectIdentifier(Pkcs9 + ".15"); + public static readonly DerObjectIdentifier IdSmime = new DerObjectIdentifier(Pkcs9 + ".16"); + public static readonly DerObjectIdentifier Pkcs9AtFriendlyName = new DerObjectIdentifier(Pkcs9 + ".20"); public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID = new DerObjectIdentifier(Pkcs9 + ".21"); @@ -131,19 +133,37 @@ namespace Org.BouncyCastle.Asn1.Pkcs public const string CrlTypes = Pkcs9 + ".23"; public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1"); - public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9"); + public static readonly DerObjectIdentifier IdAlg = IdSmime.Branch("3"); + + public static readonly DerObjectIdentifier IdAlgEsdh = IdAlg.Branch("5"); + public static readonly DerObjectIdentifier IdAlgCms3DesWrap = IdAlg.Branch("6"); + public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = IdAlg.Branch("7"); + public static readonly DerObjectIdentifier IdAlgPwriKek = IdAlg.Branch("9"); + public static readonly DerObjectIdentifier IdAlgSsdh = IdAlg.Branch("10"); + + /* + * <pre> + * -- RSA-KEM Key Transport Algorithm + * + * id-rsa-kem OID ::= { + * iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) + * pkcs-9(9) smime(16) alg(3) 14 + * } + * </pre> + */ + public static readonly DerObjectIdentifier IdRsaKem = IdAlg.Branch("14"); // // SMIME capability sub oids. // - public static readonly DerObjectIdentifier PreferSignedData = new DerObjectIdentifier(Pkcs9 + ".15.1"); - public static readonly DerObjectIdentifier CannotDecryptAny = new DerObjectIdentifier(Pkcs9 + ".15.2"); - public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = new DerObjectIdentifier(Pkcs9 + ".15.3"); + public static readonly DerObjectIdentifier PreferSignedData = Pkcs9AtSmimeCapabilities.Branch("1"); + public static readonly DerObjectIdentifier CannotDecryptAny = Pkcs9AtSmimeCapabilities.Branch("2"); + public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = Pkcs9AtSmimeCapabilities.Branch("3"); // // other SMIME attributes // - public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1"); + public static readonly DerObjectIdentifier IdAAReceiptRequest = IdSmime.Branch("2.1"); // // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840) @@ -249,8 +269,5 @@ namespace Org.BouncyCastle.Asn1.Pkcs public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc = new DerObjectIdentifier(Pkcs12PbeIds + ".4"); public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".5"); public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".6"); - - public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6"); - public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7"); - } + } } diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 36b17c8fd..6a21ee2af 100644 --- a/crypto/src/asn1/util/Asn1Dump.cs +++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -198,6 +198,14 @@ namespace Org.BouncyCastle.Asn1.Utilities { buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine); } + else if (obj is DerGraphicString) + { + buf.Append(indent + "GraphicString(" + ((DerGraphicString)obj).GetString() + ") " + NewLine); + } + else if (obj is DerVideotexString) + { + buf.Append(indent + "VideotexString(" + ((DerVideotexString)obj).GetString() + ") " + NewLine); + } else if (obj is DerUtcTime) { buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine); diff --git a/crypto/src/crypto/engines/SerpentEngineBase.cs b/crypto/src/crypto/engines/SerpentEngineBase.cs
index a5d91b3be..9de552233 100644 --- a/crypto/src/crypto/engines/SerpentEngineBase.cs +++ b/crypto/src/crypto/engines/SerpentEngineBase.cs
@@ -101,12 +101,13 @@ namespace Org.BouncyCastle.Crypto.Engines return ( (int)((uint)x >> bits) | (x << (32 - bits))); } - /** + /* * The sboxes below are based on the work of Brian Gladman and * Sam Simpson, whose original notice appears below. * <p> * For further details see: * http://fp.gladman.plus.com/cryptography_technology/serpent/ + * </p> */ /* Partially optimised Serpent S Box boolean functions derived */ @@ -124,9 +125,9 @@ namespace Org.BouncyCastle.Crypto.Engines /* We hereby give permission for information in this file to be */ /* used freely subject only to acknowledgement of its origin. */ - /** - * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. - */ + /* + * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. + */ protected void Sb0(int a, int b, int c, int d) { int t1 = a ^ d; diff --git a/crypto/src/crypto/macs/VMPCMac.cs b/crypto/src/crypto/macs/VMPCMac.cs
index 89916355c..6f2da075c 100644 --- a/crypto/src/crypto/macs/VMPCMac.cs +++ b/crypto/src/crypto/macs/VMPCMac.cs
@@ -166,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Macs for (int i = 0; i < len; i++) { - Update(input[i]); + Update(input[inOff + i]); } } } diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
index fb117c19d..3aa2e3719 100644 --- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs +++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
@@ -486,7 +486,14 @@ namespace Org.BouncyCastle.Crypto.Signers digest.BlockUpdate(m2Hash, 0, m2Hash.Length); // Update for the salt - digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength); + if (standardSalt != null) + { + digest.BlockUpdate(standardSalt, 0, standardSalt.Length); + } + else + { + digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength); + } byte[] hash = new byte[digest.GetDigestSize()]; digest.DoFinal(hash, 0); diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs
index 03890902b..23b7c0f49 100644 --- a/crypto/src/crypto/signers/PssSigner.cs +++ b/crypto/src/crypto/signers/PssSigner.cs
@@ -25,6 +25,7 @@ namespace Org.BouncyCastle.Crypto.Signers private int hLen; private int mgfhLen; private int sLen; + private bool sSet; private int emBits; private byte[] salt; private byte[] mDash; @@ -35,7 +36,7 @@ namespace Org.BouncyCastle.Crypto.Signers IAsymmetricBlockCipher cipher, IDigest digest) { - return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), TrailerImplicit); + return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), null, TrailerImplicit); } public static PssSigner CreateRawSigner( @@ -45,7 +46,7 @@ namespace Org.BouncyCastle.Crypto.Signers int saltLen, byte trailer) { - return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, trailer); + return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, null, trailer); } public PssSigner( @@ -67,7 +68,19 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public PssSigner( + /// <summary>Basic constructor</summary> + /// <param name="cipher">the asymmetric cipher to use.</param> + /// <param name="digest">the digest to use.</param> + /// <param name="salt">the fixed salt to be used.</param> + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest digest, + byte[] salt) + : this(cipher, digest, digest, digest, salt.Length, salt, TrailerImplicit) + { + } + + public PssSigner( IAsymmetricBlockCipher cipher, IDigest contentDigest, IDigest mgfDigest, @@ -76,7 +89,16 @@ namespace Org.BouncyCastle.Crypto.Signers { } - public PssSigner( + public PssSigner( + IAsymmetricBlockCipher cipher, + IDigest contentDigest, + IDigest mgfDigest, + byte[] salt) + : this(cipher, contentDigest, contentDigest, mgfDigest, salt.Length, salt, TrailerImplicit) + { + } + + public PssSigner( IAsymmetricBlockCipher cipher, IDigest digest, int saltLen, @@ -91,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Signers IDigest mgfDigest, int saltLen, byte trailer) - : this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, trailer) + : this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, null, trailer) { } @@ -101,6 +123,7 @@ namespace Org.BouncyCastle.Crypto.Signers IDigest contentDigest2, IDigest mgfDigest, int saltLen, + byte[] salt, byte trailer) { this.cipher = cipher; @@ -110,7 +133,15 @@ namespace Org.BouncyCastle.Crypto.Signers this.hLen = contentDigest2.GetDigestSize(); this.mgfhLen = mgfDigest.GetDigestSize(); this.sLen = saltLen; - this.salt = new byte[saltLen]; + this.sSet = salt != null; + if (sSet) + { + this.salt = salt; + } + else + { + this.salt = new byte[saltLen]; + } this.mDash = new byte[8 + saltLen + hLen]; this.trailer = trailer; } @@ -197,7 +228,10 @@ namespace Org.BouncyCastle.Crypto.Signers if (sLen != 0) { - random.NextBytes(salt); + if (!sSet) + { + random.NextBytes(salt); + } salt.CopyTo(mDash, mDash.Length - sLen); } @@ -270,7 +304,14 @@ namespace Org.BouncyCastle.Crypto.Signers return false; } - Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen); + if (sSet) + { + Array.Copy(salt, 0, mDash, mDash.Length - sLen, sLen); + } + else + { + Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen); + } contentDigest2.BlockUpdate(mDash, 0, mDash.Length); contentDigest2.DoFinal(mDash, mDash.Length - hLen); diff --git a/crypto/src/crypto/tls/AbstractTlsClient.cs b/crypto/src/crypto/tls/AbstractTlsClient.cs
index 046feb78c..fedca0934 100644 --- a/crypto/src/crypto/tls/AbstractTlsClient.cs +++ b/crypto/src/crypto/tls/AbstractTlsClient.cs
@@ -66,22 +66,15 @@ namespace Org.BouncyCastle.Crypto.Tls return null; } - /** - * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value - * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest - * version number supported by the client, and the value of ClientHello.client_version. No - * single value will guarantee interoperability with all old servers, but this is a complex - * topic beyond the scope of this document." - */ public virtual ProtocolVersion ClientHelloRecordLayerVersion { get { // "{03,00}" - // return ProtocolVersion.SSLv3; + //return ProtocolVersion.SSLv3; // "the lowest version number supported by the client" - // return getMinimumVersion(); + //return MinimumVersion; // "the value of ClientHello.client_version" return ClientVersion; diff --git a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs
index c9ec06107..09fb8782d 100644 --- a/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs +++ b/crypto/src/crypto/tls/AbstractTlsKeyExchange.cs
@@ -18,6 +18,17 @@ namespace Org.BouncyCastle.Crypto.Tls this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms; } + protected virtual DigitallySigned ParseSignature(Stream input) + { + DigitallySigned signature = DigitallySigned.Parse(mContext, input); + SignatureAndHashAlgorithm signatureAlgorithm = signature.Algorithm; + if (signatureAlgorithm != null) + { + TlsUtilities.VerifySupportedSignatureAlgorithm(mSupportedSignatureAlgorithms, signatureAlgorithm); + } + return signature; + } + public virtual void Init(TlsContext context) { this.mContext = context; diff --git a/crypto/src/crypto/tls/DeferredHash.cs b/crypto/src/crypto/tls/DeferredHash.cs
index 1112d4a3c..f402f26d2 100644 --- a/crypto/src/crypto/tls/DeferredHash.cs +++ b/crypto/src/crypto/tls/DeferredHash.cs
@@ -103,7 +103,7 @@ namespace Org.BouncyCastle.Crypto.Tls { IDigest d = (IDigest)mHashes[hashAlgorithm]; if (d == null) - throw new InvalidOperationException("HashAlgorithm " + hashAlgorithm + " is not being tracked"); + throw new InvalidOperationException("HashAlgorithm." + HashAlgorithm.GetText(hashAlgorithm) + " is not being tracked"); d = TlsUtilities.CloneHash(hashAlgorithm, d); if (mBuf != null) diff --git a/crypto/src/crypto/tls/DtlsClientProtocol.cs b/crypto/src/crypto/tls/DtlsClientProtocol.cs
index 411e7cca2..7cb554ae8 100644 --- a/crypto/src/crypto/tls/DtlsClientProtocol.cs +++ b/crypto/src/crypto/tls/DtlsClientProtocol.cs
@@ -74,13 +74,16 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.clientContext, recordLayer); byte[] clientHelloBody = GenerateClientHello(state, state.client); + + recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10); + handshake.SendMessage(HandshakeType.client_hello, clientHelloBody); DtlsReliableHandshake.Message serverMessage = handshake.ReceiveMessage(); while (serverMessage.Type == HandshakeType.hello_verify_request) { - ProtocolVersion recordLayerVersion = recordLayer.ResetDiscoveredPeerVersion(); + ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; ProtocolVersion client_version = state.clientContext.ClientVersion; /* @@ -92,6 +95,8 @@ namespace Org.BouncyCastle.Crypto.Tls if (!recordLayerVersion.IsEqualOrEarlierVersionOf(client_version)) throw new TlsFatalAlert(AlertDescription.illegal_parameter); + recordLayer.ReadVersion = null; + byte[] cookie = ProcessHelloVerifyRequest(state, serverMessage.Body); byte[] patched = PatchClientHelloWithCookie(clientHelloBody, cookie); @@ -103,7 +108,9 @@ namespace Org.BouncyCastle.Crypto.Tls if (serverMessage.Type == HandshakeType.server_hello) { - ReportServerVersion(state, recordLayer.DiscoveredPeerVersion); + ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; + ReportServerVersion(state, recordLayerVersion); + recordLayer.SetWriteVersion(recordLayerVersion); ProcessServerHello(state, serverMessage.Body); } diff --git a/crypto/src/crypto/tls/DtlsRecordLayer.cs b/crypto/src/crypto/tls/DtlsRecordLayer.cs
index 70befd9e4..6796f4cbb 100644 --- a/crypto/src/crypto/tls/DtlsRecordLayer.cs +++ b/crypto/src/crypto/tls/DtlsRecordLayer.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Tls private volatile bool mClosed = false; private volatile bool mFailed = false; - private volatile ProtocolVersion mDiscoveredPeerVersion = null; + private volatile ProtocolVersion mReadVersion = null, mWriteVersion = null; private volatile bool mInHandshake; private volatile int mPlaintextLimit; private DtlsEpoch mCurrentEpoch, mPendingEpoch; @@ -52,16 +52,15 @@ namespace Org.BouncyCastle.Crypto.Tls this.mPlaintextLimit = plaintextLimit; } - internal virtual ProtocolVersion DiscoveredPeerVersion + internal virtual ProtocolVersion ReadVersion { - get { return mDiscoveredPeerVersion; } + get { return mReadVersion; } + set { this.mReadVersion = value; } } - internal virtual ProtocolVersion ResetDiscoveredPeerVersion() + internal virtual void SetWriteVersion(ProtocolVersion writeVersion) { - ProtocolVersion result = mDiscoveredPeerVersion; - mDiscoveredPeerVersion = null; - return result; + this.mWriteVersion = writeVersion; } internal virtual void InitPendingEpoch(TlsCipher pendingCipher) @@ -199,7 +198,12 @@ namespace Org.BouncyCastle.Crypto.Tls } ProtocolVersion version = TlsUtilities.ReadVersion(record, 1); - if (mDiscoveredPeerVersion != null && !mDiscoveredPeerVersion.Equals(version)) + if (!version.IsDtls) + { + continue; + } + + if (mReadVersion != null && !mReadVersion.Equals(version)) { continue; } @@ -215,9 +219,9 @@ namespace Org.BouncyCastle.Crypto.Tls continue; } - if (mDiscoveredPeerVersion == null) + if (mReadVersion == null) { - mDiscoveredPeerVersion = version; + mReadVersion = version; } switch (type) @@ -469,6 +473,10 @@ namespace Org.BouncyCastle.Crypto.Tls private void SendRecord(byte contentType, byte[] buf, int off, int len) { + // Never send anything until a valid ClientHello has been received + if (mWriteVersion == null) + return; + if (len > this.mPlaintextLimit) throw new TlsFatalAlert(AlertDescription.internal_error); @@ -489,7 +497,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] record = new byte[ciphertext.Length + RECORD_HEADER_LENGTH]; TlsUtilities.WriteUint8(contentType, record, 0); - ProtocolVersion version = mDiscoveredPeerVersion != null ? mDiscoveredPeerVersion : mContext.ClientVersion; + ProtocolVersion version = mWriteVersion; TlsUtilities.WriteVersion(version, record, 1); TlsUtilities.WriteUint16(recordEpoch, record, 3); TlsUtilities.WriteUint48(recordSequenceNumber, record, 5); diff --git a/crypto/src/crypto/tls/DtlsServerProtocol.cs b/crypto/src/crypto/tls/DtlsServerProtocol.cs
index 9c7caf290..171984b6f 100644 --- a/crypto/src/crypto/tls/DtlsServerProtocol.cs +++ b/crypto/src/crypto/tls/DtlsServerProtocol.cs
@@ -76,12 +76,8 @@ namespace Org.BouncyCastle.Crypto.Tls DtlsReliableHandshake.Message clientMessage = handshake.ReceiveMessage(); - { - // NOTE: After receiving a record from the client, we discover the record layer version - ProtocolVersion client_version = recordLayer.DiscoveredPeerVersion; - // TODO Read RFCs for guidance on the expected record layer version number - state.serverContext.SetClientVersion(client_version); - } + // NOTE: DTLSRecordLayer requires any DTLS version, we don't otherwise constrain this + //ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; if (clientMessage.Type == HandshakeType.client_hello) { @@ -97,6 +93,10 @@ namespace Org.BouncyCastle.Crypto.Tls ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); + ProtocolVersion recordLayerVersion = state.serverContext.ServerVersion; + recordLayer.ReadVersion = recordLayerVersion; + recordLayer.SetWriteVersion(recordLayerVersion); + handshake.SendMessage(HandshakeType.server_hello, serverHelloBody); } @@ -156,6 +156,9 @@ namespace Org.BouncyCastle.Crypto.Tls state.certificateRequest = state.server.GetCertificateRequest(); if (state.certificateRequest != null) { + if (TlsUtilities.IsTlsV12(state.serverContext) != (state.certificateRequest.SupportedSignatureAlgorithms != null)) + throw new TlsFatalAlert(AlertDescription.internal_error); + state.keyExchange.ValidateCertificateRequest(state.certificateRequest); byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest); @@ -458,6 +461,9 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ProcessCertificateVerify(ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash) { + if (state.certificateRequest == null) + throw new InvalidOperationException(); + MemoryStream buf = new MemoryStream(body, false); TlsServerContextImpl context = state.serverContext; @@ -466,13 +472,15 @@ namespace Org.BouncyCastle.Crypto.Tls TlsProtocol.AssertEmpty(buf); // Verify the CertificateVerify message contains a correct signature. - bool verified = false; try { + SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm; + byte[] hash; if (TlsUtilities.IsTlsV12(context)) { - hash = prepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash); + TlsUtilities.VerifySupportedSignatureAlgorithm(state.certificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm); + hash = prepareFinishHash.GetFinalHash(signatureAlgorithm.Hash); } else { @@ -485,15 +493,17 @@ namespace Org.BouncyCastle.Crypto.Tls TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)state.clientCertificateType); tlsSigner.Init(context); - verified = tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm, - clientCertificateVerify.Signature, publicKey, hash); + if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash)) + throw new TlsFatalAlert(AlertDescription.decrypt_error); } - catch (Exception) + catch (TlsFatalAlert e) { + throw e; + } + catch (Exception e) + { + throw new TlsFatalAlert(AlertDescription.decrypt_error, e); } - - if (!verified) - throw new TlsFatalAlert(AlertDescription.decrypt_error); } protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body) diff --git a/crypto/src/crypto/tls/HashAlgorithm.cs b/crypto/src/crypto/tls/HashAlgorithm.cs
index ac6def26f..ff540d2e0 100644 --- a/crypto/src/crypto/tls/HashAlgorithm.cs +++ b/crypto/src/crypto/tls/HashAlgorithm.cs
@@ -12,5 +12,33 @@ namespace Org.BouncyCastle.Crypto.Tls public const byte sha256 = 4; public const byte sha384 = 5; public const byte sha512 = 6; + + public static string GetName(byte hashAlgorithm) + { + switch (hashAlgorithm) + { + case none: + return "none"; + case md5: + return "md5"; + case sha1: + return "sha1"; + case sha224: + return "sha224"; + case sha256: + return "sha256"; + case sha384: + return "sha384"; + case sha512: + return "sha512"; + default: + return "UNKNOWN"; + } + } + + public static string GetText(byte hashAlgorithm) + { + return GetName(hashAlgorithm) + "(" + hashAlgorithm + ")"; + } } } diff --git a/crypto/src/crypto/tls/TlsClient.cs b/crypto/src/crypto/tls/TlsClient.cs
index 116f6a779..73f169054 100644 --- a/crypto/src/crypto/tls/TlsClient.cs +++ b/crypto/src/crypto/tls/TlsClient.cs
@@ -23,6 +23,18 @@ namespace Org.BouncyCastle.Crypto.Tls /// </returns> TlsSession GetSessionToResume(); + /// <summary> + /// Return the <see cref="ProtocolVersion"/> to use for the <c>TLSPlaintext.version</c> field prior to + /// receiving the server version. NOTE: This method is <b>not</b> called for DTLS. + /// </summary> + /// <remarks> + /// See RFC 5246 E.1.: "TLS clients that wish to negotiate with older servers MAY send any value + /// {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest + /// version number supported by the client, and the value of ClientHello.client_version. No + /// single value will guarantee interoperability with all old servers, but this is a complex + /// topic beyond the scope of this document." + /// </remarks> + /// <returns>The <see cref="ProtocolVersion"/> to use.</returns> ProtocolVersion ClientHelloRecordLayerVersion { get; } ProtocolVersion ClientVersion { get; } diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index 9831e8cd7..cdd629247 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Tls ServerDHParams dhParams = ServerDHParams.Parse(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
index b681aada3..e0553b3f0 100644 --- a/crypto/src/crypto/tls/TlsECDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -73,7 +73,7 @@ namespace Org.BouncyCastle.Crypto.Tls byte[] point = TlsUtilities.ReadOpaque8(teeIn); - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index 4ab628b13..1b790c9e0 100644 --- a/crypto/src/crypto/tls/TlsServerProtocol.cs +++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -200,6 +200,9 @@ namespace Org.BouncyCastle.Crypto.Tls this.mCertificateRequest = mTlsServer.GetCertificateRequest(); if (this.mCertificateRequest != null) { + if (TlsUtilities.IsTlsV12(Context) != (mCertificateRequest.SupportedSignatureAlgorithms != null)) + throw new TlsFatalAlert(AlertDescription.internal_error); + this.mKeyExchange.ValidateCertificateRequest(mCertificateRequest); SendCertificateRequestMessage(mCertificateRequest); @@ -460,6 +463,9 @@ namespace Org.BouncyCastle.Crypto.Tls protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf) { + if (mCertificateRequest == null) + throw new InvalidOperationException(); + DigitallySigned clientCertificateVerify = DigitallySigned.Parse(Context, buf); AssertEmpty(buf); @@ -467,10 +473,13 @@ namespace Org.BouncyCastle.Crypto.Tls // Verify the CertificateVerify message contains a correct signature. try { + SignatureAndHashAlgorithm signatureAlgorithm = clientCertificateVerify.Algorithm; + byte[] hash; if (TlsUtilities.IsTlsV12(Context)) { - hash = mPrepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash); + TlsUtilities.VerifySupportedSignatureAlgorithm(mCertificateRequest.SupportedSignatureAlgorithms, signatureAlgorithm); + hash = mPrepareFinishHash.GetFinalHash(signatureAlgorithm.Hash); } else { @@ -483,11 +492,12 @@ namespace Org.BouncyCastle.Crypto.Tls TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)mClientCertificateType); tlsSigner.Init(Context); - if (!tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm, - clientCertificateVerify.Signature, publicKey, hash)) - { + if (!tlsSigner.VerifyRawSignature(signatureAlgorithm, clientCertificateVerify.Signature, publicKey, hash)) throw new TlsFatalAlert(AlertDescription.decrypt_error); - } + } + catch (TlsFatalAlert e) + { + throw e; } catch (Exception e) { diff --git a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
index ce8e4834a..09fa72348 100644 --- a/crypto/src/crypto/tls/TlsSrpKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsSrpKeyExchange.cs
@@ -189,7 +189,7 @@ namespace Org.BouncyCastle.Crypto.Tls if (buf != null) { - DigitallySigned signed_params = DigitallySigned.Parse(mContext, input); + DigitallySigned signed_params = ParseSignature(input); ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters); buf.UpdateSigner(signer); diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 26fb0d5e8..7d1d488d7 100644 --- a/crypto/src/crypto/tls/TlsUtilities.cs +++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -129,14 +129,24 @@ namespace Org.BouncyCastle.Crypto.Tls return context.ServerVersion.IsSsl; } + public static bool IsTlsV11(ProtocolVersion version) + { + return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion()); + } + public static bool IsTlsV11(TlsContext context) { - return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion()); + return IsTlsV11(context.ServerVersion); + } + + public static bool IsTlsV12(ProtocolVersion version) + { + return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion()); } public static bool IsTlsV12(TlsContext context) { - return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion()); + return IsTlsV12(context.ServerVersion); } public static void WriteUint8(byte i, Stream output) @@ -712,11 +722,10 @@ namespace Org.BouncyCastle.Crypto.Tls public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, bool allowAnonymous, Stream output) { - if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1 - || supportedSignatureAlgorithms.Count >= (1 << 15)) - { + if (supportedSignatureAlgorithms == null) + throw new ArgumentNullException("supportedSignatureAlgorithms"); + if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15)) throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms"); - } // supported_signature_algorithms int length = 2 * supportedSignatureAlgorithms.Count; @@ -762,6 +771,27 @@ namespace Org.BouncyCastle.Crypto.Tls return supportedSignatureAlgorithms; } + public static void VerifySupportedSignatureAlgorithm(IList supportedSignatureAlgorithms, SignatureAndHashAlgorithm signatureAlgorithm) + { + if (supportedSignatureAlgorithms == null) + throw new ArgumentNullException("supportedSignatureAlgorithms"); + if (supportedSignatureAlgorithms.Count < 1 || supportedSignatureAlgorithms.Count >= (1 << 15)) + throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms"); + if (signatureAlgorithm == null) + throw new ArgumentNullException("signatureAlgorithm"); + + if (signatureAlgorithm.Signature != SignatureAlgorithm.anonymous) + { + foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms) + { + if (entry.Hash == signatureAlgorithm.Hash && entry.Signature == signatureAlgorithm.Signature) + return; + } + } + + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size) { ProtocolVersion version = context.ServerVersion; diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs
index 640c6e787..49773b66d 100644 --- a/crypto/src/math/ec/custom/sec/SecT113Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs
@@ -102,6 +102,16 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 1] = z1 & M49; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0 = Interleave.Unshuffle(x[0]), u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + z[0] = e0 ^ (c0 << 57) ^ (c0 << 5); + z[1] = (c0 >> 7) ^ (c0 >> 59); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat128.CreateExt64(); @@ -131,6 +141,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { /* diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
index f217e28cb..9ba25d987 100644 --- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat128.Create64(); + SecT113Field.Sqrt(x, z); + return new SecT113FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs
index 47f97078c..1b6697afe 100644 --- a/crypto/src/math/ec/custom/sec/SecT131Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M03 = ulong.MaxValue >> 61; private const ulong M44 = ulong.MaxValue >> 20; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x26BC4D789AF13523UL, 0x26BC4D789AF135E2UL, 0x6UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -109,6 +111,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 2] = z2 & M03; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat192.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL); + odd[1] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(5); @@ -138,6 +159,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 123, 129 + return (uint)(x[0] ^ (x[1] >> 59) ^ (x[2] >> 1)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5]; diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
index 0ea00ea07..e0ecc100f 100644 --- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat192.Create64(); + SecT131Field.Sqrt(x, z); + return new SecT131FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs
index f921a5bc7..b1e9aa725 100644 --- a/crypto/src/math/ec/custom/sec/SecT163Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M35 = ulong.MaxValue >> 29; private const ulong M55 = ulong.MaxValue >> 9; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0xB6DB6DB6DB6DB6B0UL, 0x492492492492DB6DUL, 0x492492492UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -122,6 +124,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 2] = z2 & M35; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat192.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL); + odd[1] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat192.CreateExt64(); @@ -151,6 +172,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 157 + return (uint)(x[0] ^ (x[2] >> 29)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5]; diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
index c7a0b5639..8953fb529 100644 --- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat192.Create64(); + SecT163Field.Sqrt(x, z); + return new SecT163FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs
index 5154f1e0a..41acb4f94 100644 --- a/crypto/src/math/ec/custom/sec/SecT193Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs
@@ -132,6 +132,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M01; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) ^ (x[3] << 32); + ulong c1 = (u0 >> 32); + + z[0] = e0 ^ (c0 << 8); + z[1] = e1 ^ (c1 << 8) ^ (c0 >> 56) ^ (c0 << 33); + z[2] = (c1 >> 56) ^ (c1 << 33) ^ (c0 >> 31); + z[3] = (c1 >> 31); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -161,6 +178,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
index eba4d10e6..a1150b3f9 100644 --- a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT193Field.Sqrt(x, z); + return new SecT193FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs
index a2f73fd5d..870dade50 100644 --- a/crypto/src/math/ec/custom/sec/SecT233Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs
@@ -128,6 +128,41 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M41; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + ulong c2; + c2 = (c1 >> 27); + c1 ^= (c0 >> 27) | (c1 << 37); + c0 ^= (c0 << 37); + + ulong[] tt = Nat256.CreateExt64(); + + int[] shifts = { 32, 117, 191 }; + for (int i = 0; i < shifts.Length; ++i) + { + int w = shifts[i] >> 6, s = shifts[i] & 63; + Debug.Assert(s != 0); + tt[w ] ^= (c0 << s); + tt[w + 1] ^= (c1 << s) | (c0 >> -s); + tt[w + 2] ^= (c2 << s) | (c1 >> -s); + tt[w + 3] ^= (c2 >> -s); + } + + Reduce(tt, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -157,6 +192,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 159 + return (uint)(x[0] ^ (x[2] >> 31)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
index a9041efde..91b8e2f1c 100644 --- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT233Field.Sqrt(x, z); + return new SecT233FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs
index 6b8ad696f..2e6ed2ad6 100644 --- a/crypto/src/math/ec/custom/sec/SecT239Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs
@@ -136,6 +136,42 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 3] = z3 & M47; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + ulong c2, c3; + c3 = (c1 >> 49); + c2 = (c0 >> 49) | (c1 << 15); + c1 ^= (c0 << 15); + + ulong[] tt = Nat256.CreateExt64(); + + int[] shifts = { 39, 120 }; + for (int i = 0; i < shifts.Length; ++i) + { + int w = shifts[i] >> 6, s = shifts[i] & 63; + Debug.Assert(s != 0); + tt[w ] ^= (c0 << s); + tt[w + 1] ^= (c1 << s) | (c0 >> -s); + tt[w + 2] ^= (c2 << s) | (c1 >> -s); + tt[w + 3] ^= (c3 << s) | (c2 >> -s); + tt[w + 4] ^= (c3 >> -s); + } + + Reduce(tt, z); + + z[0] ^= e0; + z[1] ^= e1; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -165,6 +201,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 81, 162 + return (uint)(x[0] ^ (x[1] >> 17) ^ (x[2] >> 34)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
index de074c55f..a32ffc5d2 100644 --- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat256.Create64(); + SecT239Field.Sqrt(x, z); + return new SecT239FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs
index 903ea02ff..22b7eaaab 100644 --- a/crypto/src/math/ec/custom/sec/SecT283Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs
@@ -10,6 +10,8 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong M27 = ulong.MaxValue >> 37; private const ulong M57 = ulong.MaxValue >> 7; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x0C30C30C30C30808UL, 0x30C30C30C30C30C3UL, 0x820820820820830CUL, 0x0820820820820820UL, 0x2082082UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { z[0] = x[0] ^ y[0]; @@ -129,6 +131,30 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 4] = z4 & M27; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] odd = Nat320.Create64(); + + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[0] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[1] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[4]); + ulong e2 = (u0 & 0x00000000FFFFFFFFUL); + odd[2] = (u0 >> 32); + + Multiply(odd, ROOT_Z, z); + + z[0] ^= e0; + z[1] ^= e1; + z[2] ^= e2; + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(9); @@ -158,6 +184,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 271 + return (uint)(x[0] ^ (x[4] >> 15)) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4]; diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
index e02108f73..adfd4e0ed 100644 --- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat320.Create64(); + SecT283Field.Sqrt(x, z); + return new SecT283FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs
index 84eada96e..861b77aa1 100644 --- a/crypto/src/math/ec/custom/sec/SecT409Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs
@@ -165,6 +165,36 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 6] = z6 & M25; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong u0, u1; + u0 = Interleave.Unshuffle(x[0]); u1 = Interleave.Unshuffle(x[1]); + ulong e0 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c0 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[2]); u1 = Interleave.Unshuffle(x[3]); + ulong e1 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c1 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[4]); u1 = Interleave.Unshuffle(x[5]); + ulong e2 = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + ulong c2 = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + + u0 = Interleave.Unshuffle(x[6]); + ulong e3 = (u0 & 0x00000000FFFFFFFFUL); + ulong c3 = (u0 >> 32); + + z[0] = e0 ^ (c0 << 44); + z[1] = e1 ^ (c1 << 44) ^ (c0 >> 20); + z[2] = e2 ^ (c2 << 44) ^ (c1 >> 20); + z[3] = e3 ^ (c3 << 44) ^ (c2 >> 20) ^ (c0 << 13); + z[4] = (c3 >> 20) ^ (c1 << 13) ^ (c0 >> 51); + z[5] = (c2 << 13) ^ (c1 >> 51); + z[6] = (c3 << 13) ^ (c2 >> 51); + + Debug.Assert((c3 >> 51) == 0); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat.Create64(13); @@ -194,6 +224,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0 + return (uint)(x[0]) & 1U; + } + protected static void ImplCompactExt(ulong[] zz) { ulong z00 = zz[ 0], z01 = zz[ 1], z02 = zz[ 2], z03 = zz[ 3], z04 = zz[ 4], z05 = zz[ 5], z06 = zz[ 6]; diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
index 581ea73df..f954f46e7 100644 --- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat448.Create64(); + SecT409Field.Sqrt(x, z); + return new SecT409FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index fc84e336b..98f4f7fc2 100644 --- a/crypto/src/math/ec/custom/sec/SecT571Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -11,6 +11,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec private const ulong RM = 0xEF7BDEF7BDEF7BDEUL; + private static readonly ulong[] ROOT_Z = new ulong[]{ 0x2BE1195F08CAFB99UL, 0x95F08CAF84657C23UL, 0xCAF84657C232BE11UL, 0x657C232BE1195F08UL, + 0xF84657C2308CAF84UL, 0x7C232BE1195F08CAUL, 0xBE1195F08CAF8465UL, 0x5F08CAF84657C232UL, 0x784657C232BE119UL }; + public static void Add(ulong[] x, ulong[] y, ulong[] z) { for (int i = 0; i < 9; ++i) @@ -156,6 +159,28 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec z[zOff + 8] = z8 & M59; } + public static void Sqrt(ulong[] x, ulong[] z) + { + ulong[] evn = Nat576.Create64(), odd = Nat576.Create64(); + + int pos = 0; + for (int i = 0; i < 4; ++i) + { + ulong u0 = Interleave.Unshuffle(x[pos++]); + ulong u1 = Interleave.Unshuffle(x[pos++]); + evn[i] = (u0 & 0x00000000FFFFFFFFUL) | (u1 << 32); + odd[i] = (u0 >> 32) | (u1 & 0xFFFFFFFF00000000UL); + } + { + ulong u0 = Interleave.Unshuffle(x[pos]); + evn[4] = (u0 & 0x00000000FFFFFFFFUL); + odd[4] = (u0 >> 32); + } + + Multiply(odd, ROOT_Z, z); + Add(z, evn, z); + } + public static void Square(ulong[] x, ulong[] z) { ulong[] tt = Nat576.CreateExt64(); @@ -185,6 +210,12 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static uint Trace(ulong[] x) + { + // Non-zero-trace bits: 0, 561, 569 + return (uint)(x[0] ^ (x[8] >> 49) ^ (x[8] >> 57)) & 1U; + } + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { //for (int i = 0; i < 9; ++i) diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
index 5d5458412..c43b8dc3a 100644 --- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -159,7 +159,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Sqrt() { - return SquarePow(M - 1); + ulong[] z = Nat576.Create64(); + SecT571Field.Sqrt(x, z); + return new SecT571FieldElement(z); } public virtual int Representation diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs
index a45ee1e08..d21840644 100644 --- a/crypto/src/math/raw/Interleave.cs +++ b/crypto/src/math/raw/Interleave.cs
@@ -91,5 +91,17 @@ namespace Org.BouncyCastle.Math.Raw z[zOff ] = (x ) & M64; z[zOff + 1] = (x >> 1) & M64; } + + internal static ulong Unshuffle(ulong x) + { + // "unshuffle" even bits to low half and odd bits to high half + ulong t; + t = (x ^ (x >> 1)) & 0x2222222222222222UL; x ^= (t ^ (t << 1)); + t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t << 2)); + t = (x ^ (x >> 4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t << 4)); + t = (x ^ (x >> 8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t << 8)); + t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16)); + return x; + } } }