summary refs log tree commit diff
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2015-07-30 14:05:56 -0400
committerOren Novotny <oren@novotny.org>2015-07-30 14:05:56 -0400
commit48e58953790b3ead2c0136d4401f7b4403457045 (patch)
tree5b4f10358509957c3c0ffde8d4377b9a5c326b13
parentAdd Sys.Runtime PCL (diff)
parentMerge branch 'master' into master-vs12 (diff)
downloadBouncyCastle.NET-ed25519-48e58953790b3ead2c0136d4401f7b4403457045.tar.xz
Merge branch 'master-vs12' into pcl
-rw-r--r--crypto/crypto.csproj55
-rw-r--r--crypto/src/asn1/pkcs/PBKDF2Params.cs196
-rw-r--r--crypto/src/asn1/x9/X9ECParametersHolder.cs35
-rw-r--r--crypto/src/bcpg/ECDHPublicBCPGKey.cs102
-rw-r--r--crypto/src/bcpg/ECDsaPublicBCPGKey.cs34
-rw-r--r--crypto/src/bcpg/ECPublicBCPGKey.cs97
-rw-r--r--crypto/src/bcpg/ECSecretBCPGKey.cs56
-rw-r--r--crypto/src/bcpg/PublicKeyPacket.cs6
-rw-r--r--crypto/src/bcpg/SignaturePacket.cs5
-rw-r--r--crypto/src/crypto/ec/CustomNamedCurves.cs44
-rw-r--r--crypto/src/crypto/modes/CcmBlockCipher.cs11
-rw-r--r--crypto/src/crypto/tls/AbstractTlsServer.cs8
-rw-r--r--crypto/src/crypto/tls/DefaultTlsServer.cs2
-rw-r--r--crypto/src/crypto/tls/PskTlsServer.cs2
-rw-r--r--crypto/src/crypto/tls/TlsDHKeyExchange.cs22
-rw-r--r--crypto/src/crypto/tls/TlsDHUtilities.cs24
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs2
-rw-r--r--crypto/src/math/Primes.cs310
-rw-r--r--crypto/src/math/ec/ECFieldElement.cs3
-rw-r--r--crypto/src/math/ec/custom/sec/SecT113FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131Field.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT131FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163Field.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT163FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193Field.cs239
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193FieldElement.cs213
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R1Curve.cs190
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R1Point.cs283
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R2Curve.cs190
-rw-r--r--crypto/src/math/ec/custom/sec/SecT193R2Point.cs283
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233Field.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT233FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239Field.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT239FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283Field.cs4
-rw-r--r--crypto/src/math/ec/custom/sec/SecT283FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409Field.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT409FieldElement.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571Field.cs2
-rw-r--r--crypto/src/math/ec/custom/sec/SecT571FieldElement.cs2
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs5
-rw-r--r--crypto/src/pkix/PkixCertPathChecker.cs4
-rw-r--r--crypto/src/util/io/Streams.cs6
-rw-r--r--crypto/test/src/test/CertPathValidatorTest.cs2
44 files changed, 2333 insertions, 136 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index cb00f9912..93ca2cf23 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -2324,6 +2324,26 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\bcpg\ECDHPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECDsaPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECPublicBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\bcpg\ECSecretBCPGKey.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\bcpg\ElGamalPublicBCPGKey.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5099,6 +5119,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\Primes.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\ECAlgorithms.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5504,6 +5529,36 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\math\ec\custom\sec\SecT193Field.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\custom\sec\SecT193FieldElement.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\custom\sec\SecT193R1Curve.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\custom\sec\SecT193R1Point.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\custom\sec\SecT193R2Curve.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\math\ec\custom\sec\SecT193R2Point.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\math\ec\custom\sec\SecT233Field.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/pkcs/PBKDF2Params.cs b/crypto/src/asn1/pkcs/PBKDF2Params.cs
index 1351b94cf..5d1e9854f 100644
--- a/crypto/src/asn1/pkcs/PBKDF2Params.cs
+++ b/crypto/src/asn1/pkcs/PBKDF2Params.cs
@@ -1,50 +1,73 @@
 using System;
-
+using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
 {
-	public class Pbkdf2Params
-		: Asn1Encodable
-	{
-		private readonly Asn1OctetString	octStr;
-		private readonly DerInteger			iterationCount;
-		private readonly DerInteger			keyLength;
-
-		public static Pbkdf2Params GetInstance(
-			object obj)
-		{
-			if (obj == null || obj is Pbkdf2Params)
-				return (Pbkdf2Params)obj;
-
-			if (obj is Asn1Sequence)
-				return new Pbkdf2Params((Asn1Sequence)obj);
-
-			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
-		}
-
-		public Pbkdf2Params(
-			Asn1Sequence seq)
-		{
-			if (seq.Count < 2 || seq.Count > 3)
-				throw new ArgumentException("Wrong number of elements in sequence", "seq");
-
-			octStr = (Asn1OctetString)seq[0];
-			iterationCount = (DerInteger)seq[1];
-
-			if (seq.Count > 2)
-			{
-				keyLength = (DerInteger)seq[2];
-			}
-		}
-
-		public Pbkdf2Params(
-			byte[] salt,
-			int iterationCount)
-		{
-			this.octStr = new DerOctetString(salt);
-			this.iterationCount = new DerInteger(iterationCount);
-		}
+    public class Pbkdf2Params
+        : Asn1Encodable
+    {
+        private static AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdHmacWithSha1, DerNull.Instance);
+
+        private readonly Asn1OctetString     octStr;
+        private readonly DerInteger          iterationCount, keyLength;
+        private readonly AlgorithmIdentifier prf;
+
+        public static Pbkdf2Params GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Pbkdf2Params)
+                return (Pbkdf2Params)obj;
+
+            if (obj is Asn1Sequence)
+                return new Pbkdf2Params((Asn1Sequence)obj);
+
+            throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+        }
+
+        public Pbkdf2Params(
+            Asn1Sequence seq)
+        {
+            if (seq.Count < 2 || seq.Count > 4)
+                throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+            this.octStr = (Asn1OctetString)seq[0];
+            this.iterationCount = (DerInteger)seq[1];
+
+            Asn1Encodable kl = null, d = null;
+            if (seq.Count > 3)
+            {
+                kl = seq[2];
+                d = seq[3];
+            }
+            else if (seq.Count > 2)
+            {
+                if (seq[2] is DerInteger)
+                {
+                    kl = seq[2];
+                }
+                else
+                {
+                    d = seq[2];
+                }
+            }
+            if (kl != null)
+            {
+                keyLength = (DerInteger)kl;
+            }
+            if (d != null)
+            {
+                prf = AlgorithmIdentifier.GetInstance(d);
+            }
+        }
+
+        public Pbkdf2Params(
+            byte[] salt,
+            int iterationCount)
+        {
+            this.octStr = new DerOctetString(salt);
+            this.iterationCount = new DerInteger(iterationCount);
+        }
 
         public Pbkdf2Params(
             byte[]  salt,
@@ -55,32 +78,65 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             this.keyLength = new DerInteger(keyLength);
         }
 
-		public byte[] GetSalt()
-		{
-			return octStr.GetOctets();
-		}
-
-		public BigInteger IterationCount
-		{
-			get { return iterationCount.Value; }
-		}
-
-		public BigInteger KeyLength
-		{
-			get { return keyLength == null ? null : keyLength.Value; }
-		}
-
-		public override Asn1Object ToAsn1Object()
-		{
-			Asn1EncodableVector v = new Asn1EncodableVector(
-				octStr, iterationCount);
-
-			if (keyLength != null)
-			{
-				v.Add(keyLength);
-			}
-
-			return new DerSequence(v);
-		}
-	}
+        public Pbkdf2Params(
+            byte[] salt,
+            int iterationCount,
+            int keyLength,
+            AlgorithmIdentifier prf)
+            : this(salt, iterationCount, keyLength)
+        {
+            this.prf = prf;
+        }
+
+        public Pbkdf2Params(
+            byte[] salt,
+            int iterationCount,
+            AlgorithmIdentifier prf)
+            : this(salt, iterationCount)
+        {
+            this.prf = prf;
+        }
+
+        public byte[] GetSalt()
+        {
+            return octStr.GetOctets();
+        }
+
+        public BigInteger IterationCount
+        {
+            get { return iterationCount.Value; }
+        }
+
+        public BigInteger KeyLength
+        {
+            get { return keyLength == null ? null : keyLength.Value; }
+        }
+
+        public bool IsDefaultPrf
+        {
+            get { return prf == null || prf.Equals(algid_hmacWithSHA1); }
+        }
+
+        public AlgorithmIdentifier Prf
+        {
+            get { return prf != null ? prf : algid_hmacWithSHA1; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                octStr, iterationCount);
+
+            if (keyLength != null)
+            {
+                v.Add(keyLength);
+            }
+            if (!IsDefaultPrf)
+            {
+                v.Add(prf);
+            }
+
+            return new DerSequence(v);
+        }
+    }
 }
diff --git a/crypto/src/asn1/x9/X9ECParametersHolder.cs b/crypto/src/asn1/x9/X9ECParametersHolder.cs
index b3455709c..dd59e9f56 100644
--- a/crypto/src/asn1/x9/X9ECParametersHolder.cs
+++ b/crypto/src/asn1/x9/X9ECParametersHolder.cs
@@ -1,22 +1,25 @@
 namespace Org.BouncyCastle.Asn1.X9
 {
-	public abstract class X9ECParametersHolder
-	{
-		private X9ECParameters parameters;
+    public abstract class X9ECParametersHolder
+    {
+        private X9ECParameters parameters;
 
-		public X9ECParameters Parameters
-		{
-			get
-			{
-				if (parameters == null)
-				{
-					parameters = CreateParameters();
-				}
+        public X9ECParameters Parameters
+        {
+            get
+            {
+                lock (this)
+                {
+                    if (parameters == null)
+                    {
+                        parameters = CreateParameters();
+                    }
 
-				return parameters;
-			}
-		}
+                    return parameters;
+                }
+            }
+        }
 
-		protected abstract X9ECParameters CreateParameters();
-	}
+        protected abstract X9ECParameters CreateParameters();
+    }
 }
diff --git a/crypto/src/bcpg/ECDHPublicBCPGKey.cs b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
new file mode 100644
index 000000000..b85379586
--- /dev/null
+++ b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an ECDH Public Key.</remarks>
+    public class ECDHPublicBcpgKey
+        : ECPublicBcpgKey
+    {
+        private byte reserved;
+        private byte hashFunctionId;
+        private byte symAlgorithmId;
+
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        public ECDHPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+            int length = bcpgIn.ReadByte();
+            byte[] kdfParameters =  new byte[length];
+            if (kdfParameters.Length != 3)
+                throw new InvalidOperationException("kdf parameters size of 3 expected.");
+
+            bcpgIn.ReadFully(kdfParameters);
+
+            reserved = kdfParameters[0];
+            hashFunctionId = kdfParameters[1];
+            symAlgorithmId = kdfParameters[2];
+
+            VerifyHashAlgorithm();
+            VerifySymmetricKeyAlgorithm();
+        }
+
+        public ECDHPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point,
+            int hashAlgorithm,
+            int symmetricKeyAlgorithm)
+            : base(oid, point)
+        {
+            reserved = 1;
+            hashFunctionId = (byte)hashAlgorithm;
+            symAlgorithmId = (byte)symmetricKeyAlgorithm;
+
+            VerifyHashAlgorithm();
+            VerifySymmetricKeyAlgorithm();
+        }
+
+        public virtual byte Reserved
+        {
+            get { return reserved; }
+        }
+
+        public virtual byte HashAlgorithm
+        {
+            get { return hashFunctionId; }
+        }
+
+        public virtual byte SymmetricKeyAlgorithm
+        {
+            get { return symAlgorithmId; }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            base.Encode(bcpgOut);
+            bcpgOut.WriteByte(0x3);
+            bcpgOut.WriteByte(reserved);
+            bcpgOut.WriteByte(hashFunctionId);
+            bcpgOut.WriteByte(symAlgorithmId);
+        }
+
+        private void VerifyHashAlgorithm()
+        {
+            switch ((HashAlgorithmTag)hashFunctionId)
+            {
+            case HashAlgorithmTag.Sha256:
+            case HashAlgorithmTag.Sha384:
+            case HashAlgorithmTag.Sha512:
+                break;
+            default:
+                throw new InvalidOperationException("Hash algorithm must be SHA-256 or stronger.");
+            }
+        }
+
+        private void VerifySymmetricKeyAlgorithm()
+        {
+            switch ((SymmetricKeyAlgorithmTag)symAlgorithmId)
+            {
+            case SymmetricKeyAlgorithmTag.Aes128:
+            case SymmetricKeyAlgorithmTag.Aes192:
+            case SymmetricKeyAlgorithmTag.Aes256:
+                break;
+            default:
+                throw new InvalidOperationException("Symmetric key algorithm must be AES-128 or stronger.");
+            }
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECDsaPublicBCPGKey.cs b/crypto/src/bcpg/ECDsaPublicBCPGKey.cs
new file mode 100644
index 000000000..5f0c8ac55
--- /dev/null
+++ b/crypto/src/bcpg/ECDsaPublicBCPGKey.cs
@@ -0,0 +1,34 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an ECDSA Public Key.</remarks>
+    public class ECDsaPublicBcpgKey
+        : ECPublicBcpgKey
+    {
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        protected internal ECDsaPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+        }
+
+        public ECDsaPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point)
+            : base(oid, point)
+        {
+        }
+
+        public ECDsaPublicBcpgKey(
+            DerObjectIdentifier oid,
+            BigInteger encodedPoint)
+            : base(oid, encodedPoint)
+        {
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECPublicBCPGKey.cs b/crypto/src/bcpg/ECPublicBCPGKey.cs
new file mode 100644
index 000000000..f328f9dc3
--- /dev/null
+++ b/crypto/src/bcpg/ECPublicBCPGKey.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for an EC Public Key.</remarks>
+    public abstract class ECPublicBcpgKey
+        : BcpgObject, IBcpgKey
+    {
+        internal DerObjectIdentifier oid;
+        internal BigInteger point;
+
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        protected ECPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+        {
+            this.oid = DerObjectIdentifier.GetInstance(Asn1Object.FromByteArray(ReadBytesOfEncodedLength(bcpgIn)));
+            this.point = new MPInteger(bcpgIn).Value;
+        }
+
+        protected ECPublicBcpgKey(
+            DerObjectIdentifier oid,
+            ECPoint point)
+        {
+            this.point = new BigInteger(1, point.GetEncoded());
+            this.oid = oid;
+        }
+
+        protected ECPublicBcpgKey(
+            DerObjectIdentifier oid,
+            BigInteger encodedPoint)
+        {
+            this.point = encodedPoint;
+            this.oid = oid;
+        }
+
+        /// <summary>The format, as a string, always "PGP".</summary>
+        public string Format
+        {
+            get { return "PGP"; }
+        }
+
+        /// <summary>Return the standard PGP encoding of the key.</summary>
+        public override byte[] GetEncoded()
+        {
+            try
+            {
+                return base.GetEncoded();
+            }
+            catch (IOException)
+            {
+                return null;
+            }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            byte[] oid = this.oid.GetEncoded();
+            bcpgOut.Write(oid, 1, oid.Length - 1);
+
+            MPInteger point = new MPInteger(this.point);
+            bcpgOut.WriteObject(point);
+        }
+
+        public virtual BigInteger EncodedPoint
+        {
+            get { return point; }
+        }
+
+        public virtual DerObjectIdentifier CurveOid
+        {
+            get { return oid; }
+        }
+
+        protected static byte[] ReadBytesOfEncodedLength(
+            BcpgInputStream bcpgIn)
+        {
+            int length = bcpgIn.ReadByte();
+            if (length == 0 || length == 0xFF)
+            {
+                throw new IOException("future extensions not yet implemented.");
+            }
+
+            byte[] buffer = new byte[length + 2];
+            bcpgIn.ReadFully(buffer, 2, buffer.Length - 2);
+            buffer[0] = (byte)0x06;
+            buffer[1] = (byte)length;
+
+            return buffer;
+        }
+    }
+}
diff --git a/crypto/src/bcpg/ECSecretBCPGKey.cs b/crypto/src/bcpg/ECSecretBCPGKey.cs
new file mode 100644
index 000000000..22e0a3473
--- /dev/null
+++ b/crypto/src/bcpg/ECSecretBCPGKey.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an EC Secret Key.</remarks>
+    public class ECSecretBcpgKey
+        : BcpgObject, IBcpgKey
+    {
+        internal MPInteger x;
+
+        public ECSecretBcpgKey(
+            BcpgInputStream bcpgIn)
+        {
+            this.x = new MPInteger(bcpgIn);
+        }
+
+        public ECSecretBcpgKey(
+            BigInteger x)
+        {
+            this.x = new MPInteger(x);
+        }
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WriteObject(x);
+        }
+
+        public virtual BigInteger X
+        {
+            get { return x.Value; }
+        }
+    }
+}
diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs
index a45aeb469..cea5c8ed2 100644
--- a/crypto/src/bcpg/PublicKeyPacket.cs
+++ b/crypto/src/bcpg/PublicKeyPacket.cs
@@ -44,6 +44,12 @@ namespace Org.BouncyCastle.Bcpg
                 case PublicKeyAlgorithmTag.ElGamalGeneral:
                     key = new ElGamalPublicBcpgKey(bcpgIn);
                     break;
+                case PublicKeyAlgorithmTag.EC:
+                    key = new ECDHPublicBcpgKey(bcpgIn);
+                    break;
+                case PublicKeyAlgorithmTag.ECDsa:
+                    key = new ECDsaPublicBcpgKey(bcpgIn);
+                    break;
                 default:
                     throw new IOException("unknown PGP public key algorithm encountered");
             }
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index 605ce84c4..5b91c15a3 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -146,6 +146,11 @@ namespace Org.BouncyCastle.Bcpg
                     MPInteger y = new MPInteger(bcpgIn);
 					signature = new MPInteger[]{ p, g, y };
                     break;
+                case PublicKeyAlgorithmTag.ECDsa:
+                    MPInteger ecR = new MPInteger(bcpgIn);
+                    MPInteger ecS = new MPInteger(bcpgIn);
+                    signature = new MPInteger[]{ ecR, ecS };
+                    break;
                 default:
 					if (keyAlgorithm >= PublicKeyAlgorithmTag.Experimental_1 && keyAlgorithm <= PublicKeyAlgorithmTag.Experimental_11)
 					{
diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
index 9b7935523..0f13b4571 100644
--- a/crypto/src/crypto/ec/CustomNamedCurves.cs
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -516,6 +516,48 @@ namespace Org.BouncyCastle.Crypto.EC
         };
 
         /*
+         * sect193r1
+         */
+        internal class SecT193R1Holder
+            : X9ECParametersHolder
+        {
+            private SecT193R1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new SecT193R1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30");
+                ECCurve curve = ConfigureCurve(new SecT193R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+                    + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        };
+
+        /*
+         * sect193r2
+         */
+        internal class SecT193R2Holder
+            : X9ECParametersHolder
+        {
+            private SecT193R2Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new SecT193R2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+                ECCurve curve = ConfigureCurve(new SecT193R2Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+                    + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        };
+
+        /*
          * sect233k1
          */
         internal class SecT233K1Holder
@@ -766,6 +808,8 @@ namespace Org.BouncyCastle.Crypto.EC
             DefineCurveWithOid("sect163k1", SecObjectIdentifiers.SecT163k1, SecT163K1Holder.Instance);
             DefineCurveWithOid("sect163r1", SecObjectIdentifiers.SecT163r1, SecT163R1Holder.Instance);
             DefineCurveWithOid("sect163r2", SecObjectIdentifiers.SecT163r2, SecT163R2Holder.Instance);
+            DefineCurveWithOid("sect193r1", SecObjectIdentifiers.SecT193r1, SecT193R1Holder.Instance);
+            DefineCurveWithOid("sect193r2", SecObjectIdentifiers.SecT193r2, SecT193R2Holder.Instance);
             DefineCurveWithOid("sect233k1", SecObjectIdentifiers.SecT233k1, SecT233K1Holder.Instance);
             DefineCurveWithOid("sect233r1", SecObjectIdentifiers.SecT233r1, SecT233R1Holder.Instance);
             DefineCurveWithOid("sect239k1", SecObjectIdentifiers.SecT239k1, SecT239K1Holder.Instance);
diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs
index 56d98d259..f94954d5c 100644
--- a/crypto/src/crypto/modes/CcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/CcmBlockCipher.cs
@@ -268,9 +268,10 @@ namespace Org.BouncyCastle.Crypto.Modes
                 outputLen = inLen + macSize;
                 Check.OutputLength(output, outOff, outputLen, "Output buffer too short.");
 
-                calculateMac(input, inOff, inLen, macBlock);
+                CalculateMac(input, inOff, inLen, macBlock);
 
-                ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0);   // S0
+                byte[] encMac = new byte[BlockSize];
+                ctrCipher.ProcessBlock(macBlock, 0, encMac, 0);   // S0
 
                 while (inIndex < (inOff + inLen - BlockSize))                 // S1...
                 {
@@ -287,7 +288,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 Array.Copy(block, 0, output, outIndex, inLen + inOff - inIndex);
 
-                Array.Copy(macBlock, 0, output, outOff + inLen, macSize);
+                Array.Copy(encMac, 0, output, outOff + inLen, macSize);
             }
             else
             {
@@ -323,7 +324,7 @@ namespace Org.BouncyCastle.Crypto.Modes
 
                 byte[] calculatedMacBlock = new byte[BlockSize];
 
-                calculateMac(output, outOff, outputLen, calculatedMacBlock);
+                CalculateMac(output, outOff, outputLen, calculatedMacBlock);
 
                 if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock))
                     throw new InvalidCipherTextException("mac check in CCM failed");
@@ -332,7 +333,7 @@ namespace Org.BouncyCastle.Crypto.Modes
             return outputLen;
         }
 
-        private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+        private int CalculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
         {
             IMac cMac = new CbcBlockCipherMac(cipher, macSize * 8);
 
diff --git a/crypto/src/crypto/tls/AbstractTlsServer.cs b/crypto/src/crypto/tls/AbstractTlsServer.cs
index c3e250fd8..9f549cfd1 100644
--- a/crypto/src/crypto/tls/AbstractTlsServer.cs
+++ b/crypto/src/crypto/tls/AbstractTlsServer.cs
@@ -165,9 +165,13 @@ namespace Org.BouncyCastle.Crypto.Tls
             /*
              * RFC 4429 4. The client MUST NOT include these extensions in the ClientHello message if it
              * does not propose any ECC cipher suites.
+             * 
+             * NOTE: This was overly strict as there may be ECC cipher suites that we don't recognize.
+             * Also, draft-ietf-tls-negotiated-ff-dhe will be overloading the 'elliptic_curves'
+             * extension to explicitly allow FFDHE (i.e. non-ECC) groups.
              */
-            if (!this.mEccCipherSuitesOffered && (this.mNamedCurves != null || this.mClientECPointFormats != null))
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            //if (!this.mEccCipherSuitesOffered && (this.mNamedCurves != null || this.mClientECPointFormats != null))
+            //    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
         }
 
         public virtual ProtocolVersion GetServerVersion()
diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs
index b12c43e1c..77cd5f1cc 100644
--- a/crypto/src/crypto/tls/DefaultTlsServer.cs
+++ b/crypto/src/crypto/tls/DefaultTlsServer.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual DHParameters GetDHParameters()
         {
-            return DHStandardGroups.rfc5114_1024_160;
+            return DHStandardGroups.rfc5114_2048_256;
         }
 
         protected override int[] GetCipherSuites()
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
index 27d2b8119..85f3055fb 100644
--- a/crypto/src/crypto/tls/PskTlsServer.cs
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual DHParameters GetDHParameters()
         {
-            return DHStandardGroups.rfc5114_1024_160;
+            return DHStandardGroups.rfc5114_2048_256;
         }
 
         protected override int[] GetCipherSuites()
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index 211249fcc..93ef1fa4a 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -81,6 +81,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 try
                 {
                     this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
+                    this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
                 }
                 catch (InvalidCastException e)
                 {
@@ -171,8 +172,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         public override void ProcessClientCertificate(Certificate clientCertificate)
         {
-            // TODO Extract the public key
-            // TODO If the certificate is 'fixed', take the public key as dhAgreeClientPublicKey
+            // TODO Extract the public key and validate
+
+            /*
+             * TODO If the certificate is 'fixed', take the public key as dhAgreePublicKey and check
+             * that the parameters match the server's (see 'areCompatibleParameters').
+             */
         }
 
         public override void ProcessClientKeyExchange(Stream input)
@@ -202,5 +207,18 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             throw new TlsFatalAlert(AlertDescription.internal_error);
         }
+
+        protected virtual int MinimumPrimeBits
+        {
+            get { return 1024; }
+        }
+
+        protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
+        {
+            if (parameters.P.BitLength < MinimumPrimeBits)
+                throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+            return TlsDHUtilities.ValidateDHParameters(parameters);
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index b29f75e30..727587135 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -435,26 +435,28 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             return (DHPrivateKeyParameters)kp.Private;
         }
-        
-        public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+
+        public static DHParameters ValidateDHParameters(DHParameters parameters)
         {
-            BigInteger Y = key.Y;
-            DHParameters parameters = key.Parameters;
             BigInteger p = parameters.P;
             BigInteger g = parameters.G;
 
             if (!p.IsProbablePrime(2))
-            {
                 throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-            }
             if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0)
-            {
                 throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-            }
-            if (Y.CompareTo(Two) < 0 || Y.CompareTo(p.Subtract(Two)) > 0)
-            {
+
+
+            return parameters;
+        }
+
+        public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+        {
+            DHParameters parameters = ValidateDHParameters(key.Parameters);
+
+            BigInteger Y = key.Y;
+            if (Y.CompareTo(Two) < 0 || Y.CompareTo(parameters.P.Subtract(Two)) > 0)
                 throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-            }
 
             // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
 
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index 419d4e442..9831e8cd7 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -79,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 throw new TlsFatalAlert(AlertDescription.decrypt_error);
 
             this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
-            this.mDHParameters = mDHAgreePublicKey.Parameters;
+            this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
         }
 
         protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
diff --git a/crypto/src/math/Primes.cs b/crypto/src/math/Primes.cs
new file mode 100644
index 000000000..b57977983
--- /dev/null
+++ b/crypto/src/math/Primes.cs
@@ -0,0 +1,310 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math
+{
+    public static class Primes
+    {
+        private static readonly BigInteger One = BigInteger.One;
+        private static readonly BigInteger Two = BigInteger.Two;
+        private static readonly BigInteger Three = BigInteger.Three;
+
+        /**
+         * Used to return the output from the {@linkplain #generateSTRandomPrime(Digest) Shawe-Taylor Random_Prime Routine} 
+         */
+        public class STOutput
+        {
+            private readonly BigInteger mPrime;
+            private readonly byte[] mPrimeSeed;
+            private readonly int mPrimeGenCounter;
+
+            internal STOutput(BigInteger prime, byte[] primeSeed, int primeGenCounter)
+            {
+                this.mPrime = prime;
+                this.mPrimeSeed = primeSeed;
+                this.mPrimeGenCounter = primeGenCounter;
+            }
+
+            public BigInteger Prime
+            {
+                get { return mPrime; }
+            }
+
+            public byte[] PrimeSeed
+            {
+                get { return mPrimeSeed; }
+            }
+
+            public int PrimeGenCounter
+            {
+                get { return mPrimeGenCounter; }
+            }
+        }
+
+        /**
+         * FIPS 186-4 C.6 Shawe-Taylor Random_Prime Routine
+         * 
+         * Construct a provable prime number using a hash function.
+         * 
+         * @param hash
+         *            the {@link Digest} instance to use (as "Hash()"). Cannot be null.
+         * @param length
+         *            the length (in bits) of the prime to be generated. Must be >= 2.
+         * @param inputSeed
+         *            the seed to be used for the generation of the requested prime. Cannot be null or
+         *            empty.
+         * @returns an {@link STOutput} instance containing the requested prime.
+         */
+        public static STOutput GenerateSTRandomPrime(IDigest hash, int length, byte[] inputSeed)
+        {
+            if (hash == null)
+                throw new ArgumentNullException("hash");
+            if (length < 2)
+                throw new ArgumentException("must be >= 2", "length");
+            if (inputSeed == null)
+                throw new ArgumentNullException("inputSeed");
+            if (inputSeed.Length == 0)
+                throw new ArgumentException("cannot be empty", "inputSeed");
+
+            return ImplSTRandomPrime(hash, length, Arrays.Clone(inputSeed));
+        }
+
+        private static STOutput ImplSTRandomPrime(IDigest d, int length, byte[] primeSeed)
+        {
+            int dLen = d.GetDigestSize();
+
+            if (length < 33)
+            {
+                int primeGenCounter = 0;
+
+                byte[] c0 = new byte[dLen];
+                byte[] c1 = new byte[dLen];
+
+                for (;;)
+                {
+                    Hash(d, primeSeed, c0, 0);
+                    Inc(primeSeed, 1);
+
+                    Hash(d, primeSeed, c1, 0);
+                    Inc(primeSeed, 1);
+
+                    uint c = Extract32(c0) ^ Extract32(c1);
+                    c &= (uint.MaxValue >> (32 - length));
+                    c |= (1U << (length - 1)) | 1U;
+
+                    ++primeGenCounter;
+
+                    if (IsPrime32(c))
+                    {
+                        return new STOutput(BigInteger.ValueOf((long)c), primeSeed, primeGenCounter);
+                    }
+
+                    if (primeGenCounter > (4 * length))
+                    {
+                        throw new InvalidOperationException("Too many iterations in Shawe-Taylor Random_Prime Routine");
+                    }
+                }
+            }
+
+            STOutput rec = ImplSTRandomPrime(d, (length + 3)/2, primeSeed);
+
+            {
+                BigInteger c0 = rec.Prime;
+                primeSeed = rec.PrimeSeed;
+                int primeGenCounter = rec.PrimeGenCounter;
+
+                int outlen = 8 * dLen;
+                int iterations = (length - 1)/outlen;
+
+                int oldCounter = primeGenCounter;
+
+                BigInteger x = HashGen(d, primeSeed, iterations + 1);
+                x = x.Mod(One.ShiftLeft(length - 1)).SetBit(length - 1);
+
+                BigInteger c0x2 = c0.ShiftLeft(1);
+                BigInteger tx2 = x.Subtract(One).Divide(c0x2).Add(One).ShiftLeft(1);
+                int dt = 0;
+
+                BigInteger c = tx2.Multiply(c0).Add(One);
+
+                /*
+                 * TODO Since the candidate primes are generated by constant steps ('c0x2'),
+                 * sieving could be used here in place of the 'mightBePrime' approach.
+                 */
+                for (;;)
+                {
+                    if (c.BitLength > length)
+                    {
+                        tx2 = One.ShiftLeft(length - 1).Subtract(One).Divide(c0x2).Add(One).ShiftLeft(1);
+                        c = tx2.Multiply(c0).Add(One);
+                    }
+
+                    ++primeGenCounter;
+
+                    /*
+                     * This is an optimization of the original algorithm, using trial division to screen out
+                     * many non-primes quickly.
+                     * 
+                     * NOTE: 'primeSeed' is still incremented as if we performed the full check!
+                     */
+                    if (MightBePrime(c))
+                    {
+                        BigInteger a = HashGen(d, primeSeed, iterations + 1);
+                        a = a.Mod(c.Subtract(Three)).Add(Two);
+
+                        tx2 = tx2.Add(BigInteger.ValueOf(dt));
+                        dt = 0;
+
+                        BigInteger z = a.ModPow(tx2, c);
+
+                        if (c.Gcd(z.Subtract(One)).Equals(One) && z.ModPow(c0, c).Equals(One))
+                        {
+                            return new STOutput(c, primeSeed, primeGenCounter);
+                        }
+                    }
+                    else
+                    {
+                        Inc(primeSeed, iterations + 1);
+                    }
+
+                    if (primeGenCounter >= ((4 * length) + oldCounter))
+                    {
+                        throw new InvalidOperationException("Too many iterations in Shawe-Taylor Random_Prime Routine");
+                    }
+
+                    dt += 2;
+                    c = c.Add(c0x2);
+                }
+            }
+        }
+
+        private static uint Extract32(byte[] bs)
+        {
+            uint result = 0;
+
+            int count = System.Math.Min(4, bs.Length);
+            for (int i = 0; i < count; ++i)
+            {
+                uint b = bs[bs.Length - (i + 1)];
+                result |= (b << (8 * i));
+            }
+
+            return result;
+        }
+
+        private static void Hash(IDigest d, byte[] input, byte[] output, int outPos)
+        {
+            d.BlockUpdate(input, 0, input.Length);
+            d.DoFinal(output, outPos);
+        }
+
+        private static BigInteger HashGen(IDigest d, byte[] seed, int count)
+        {
+            int dLen = d.GetDigestSize();
+            int pos = count * dLen;
+            byte[] buf = new byte[pos];
+            for (int i = 0; i < count; ++i)
+            {
+                pos -= dLen;
+                Hash(d, seed, buf, pos);
+                Inc(seed, 1);
+            }
+            return new BigInteger(1, buf);
+        }
+
+        private static void Inc(byte[] seed, int c)
+        {
+            int pos = seed.Length;
+            while (c > 0 && --pos >= 0)
+            {
+                c += seed[pos];
+                seed[pos] = (byte)c;
+                c >>= 8;
+            }
+        }
+
+        private static bool IsPrime32(uint x)
+        {
+            /*
+             * Use wheel factorization with 2, 3, 5 to select trial divisors.
+             */
+
+            if (x <= 5)
+            {
+                return x == 2 || x == 3 || x == 5;
+            }
+
+            if ((x & 1) == 0 || (x % 3) == 0 || (x % 5) == 0)
+            {
+                return false;
+            }
+
+            uint[] ds = new uint[]{ 1, 7, 11, 13, 17, 19, 23, 29 };
+            uint b = 0;
+            for (int pos = 1; ; pos = 0)
+            {
+                /*
+                 * Trial division by wheel-selected divisors
+                 */
+                while (pos < ds.Length)
+                {
+                    uint d = b + ds[pos];
+                    if (x % d == 0)
+                    {
+                        return x < 30;
+                    }
+                    ++pos;
+                }
+
+                b += 30;
+
+                if ((b >> 16 != 0) || (b * b >= x))
+                {
+                    return true;
+                }
+            }
+        }
+
+        private static bool MightBePrime(BigInteger x)
+        {
+            /*
+             * Bundle trial divisors into ~32-bit moduli then use fast tests on the ~32-bit remainders.
+             */
+            int m = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23;
+            int r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r & 1) != 0 && (r % 3) != 0 && (r % 5) != 0 && (r % 7) != 0 && (r % 11) != 0
+                && (r % 13) != 0 && (r % 17) != 0 && (r % 19) != 0 && (r % 23) != 0)
+            {
+                m = 29 * 31 * 37 * 41 * 43;
+                r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+                if ((r % 29) != 0 && (r % 31) != 0 && (r % 37) != 0 && (r % 41) != 0 && (r % 43) != 0)
+                {
+                    m = 47 * 53 * 59 * 61 * 67;
+                    r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+                    if ((r % 47) != 0 && (r % 53) != 0 && (r % 59) != 0 && (r % 61) != 0 && (r % 67) != 0)
+                    {
+                        m = 71 * 73 * 79 * 83;
+                        r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+                        if ((r % 71) != 0 && (r % 73) != 0 && (r % 79) != 0 && (r % 83) != 0)
+                        {
+                            m = 89 * 97 * 101 * 103;
+                            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+                            if ((r % 89) != 0 && (r % 97) != 0 && (r % 101) != 0 && (r % 103) != 0)
+                            {
+                                m = 107 * 109 * 113 * 127;
+                                r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+                                if ((r % 107) != 0 && (r % 109) != 0 && (r % 113) != 0 && (r % 127) != 0)
+                                {
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    }
+}
diff --git a/crypto/src/math/ec/ECFieldElement.cs b/crypto/src/math/ec/ECFieldElement.cs
index 844bed649..4d4fb3e4d 100644
--- a/crypto/src/math/ec/ECFieldElement.cs
+++ b/crypto/src/math/ec/ECFieldElement.cs
@@ -604,6 +604,9 @@ namespace Org.BouncyCastle.Math.EC
             int			k3,
             BigInteger	x)
         {
+            if (x == null || x.SignValue < 0 || x.BitLength > m)
+                throw new ArgumentException("value invalid in F2m field element", "x");
+
             if ((k2 == 0) && (k3 == 0))
             {
                 this.representation = Tpb;
diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
index 7e9d53e44..e3a923f62 100644
--- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT113FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 113)
                 throw new ArgumentException("value invalid for SecT113FieldElement", "x");
 
             this.x = SecT113Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs
index df75dfcd7..6a1d2a960 100644
--- a/crypto/src/math/ec/custom/sec/SecT131Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs
@@ -231,7 +231,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 45 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
@@ -247,7 +247,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             int k = 33;
             do
             {
-                j = (uint)(x >> k);
+                j  = (uint)(x >> k);
                 g  = u[j & 7]
                    ^ u[(j >> 3) & 7] << 3
                    ^ u[(j >> 6) & 7] << 6
diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
index d60c7ed7d..65aaf01ba 100644
--- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT131FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 131)
                 throw new ArgumentException("value invalid for SecT131FieldElement", "x");
 
             this.x = SecT131Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs
index 2a775e20d..165d5b841 100644
--- a/crypto/src/math/ec/custom/sec/SecT163Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs
@@ -230,7 +230,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 56 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
@@ -244,7 +244,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             int k = 47;
             do
             {
-                j = (uint)(x >> k);
+                j  = (uint)(x >> k);
                 g  = u[j & 7]
                    ^ u[(j >> 3) & 7] << 3
                    ^ u[(j >> 6) & 7] << 6;
diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
index 0ef421c71..3ab383a1d 100644
--- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT163FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 163)
                 throw new ArgumentException("value invalid for SecT163FieldElement", "x");
 
             this.x = SecT163Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs
new file mode 100644
index 000000000..85db061c3
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs
@@ -0,0 +1,239 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.Raw;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecT193Field
+    {
+        private const ulong M01 = 1UL;
+        private const ulong M49 = ulong.MaxValue >> 15;
+
+        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];
+        }
+
+        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);
+            Reduce63(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], x4 = xx[4], x5 = xx[5], x6 = xx[6];
+
+            x2 ^= (x6 << 63);
+            x3 ^= (x6 >>  1) ^ (x6 << 14);
+            x4 ^= (x6 >> 50);
+
+            x1 ^= (x5 << 63);
+            x2 ^= (x5 >>  1) ^ (x5 << 14);
+            x3 ^= (x5 >> 50);
+
+            x0 ^= (x4 << 63);
+            x1 ^= (x4 >>  1) ^ (x4 << 14);
+            x2 ^= (x4 >> 50);
+
+            ulong t = x3 >> 1;
+            z[0]    = x0 ^ t ^ (t << 15);
+            z[1]    = x1     ^ (t >> 49);
+            z[2]    = x2;
+            z[3]    = x3 & M01;
+        }
+
+        public static void Reduce63(ulong[] z, int zOff)
+        {
+            ulong z3     = z[zOff + 3], t = z3 >> 1;
+            z[zOff    ] ^= t ^ (t << 15);
+            z[zOff + 1] ^=     (t >> 49);
+            z[zOff + 3]  = z3 & M01;
+        }
+
+        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 << 49);
+            zz[1] = (z1 >> 15) ^ (z2 << 34);
+            zz[2] = (z2 >> 30) ^ (z3 << 19);
+            zz[3] = (z3 >> 45) ^ (z4 <<  4)
+                               ^ (z5 << 53);
+            zz[4] = (z4 >> 60) ^ (z6 << 38)
+                  ^ (z5 >> 11);
+            zz[5] = (z6 >> 26) ^ (z7 << 23);
+            zz[6] = (z7 >> 41);
+            zz[7] = 0;
+        }
+
+        protected static void ImplExpand(ulong[] x, ulong[] z)
+        {
+            ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
+            z[0] = x0 & M49;
+            z[1] = ((x0 >> 49) ^ (x1 << 15)) & M49;
+            z[2] = ((x1 >> 34) ^ (x2 << 30)) & M49;
+            z[3] = ((x2 >> 19) ^ (x3 << 45));
+        }
+
+        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 >> 49 == 0);
+            Debug.Assert(y >> 49 == 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 = 36;
+            do
+            {
+                j  = (uint)(x >> k);
+                g  = u[j & 7]
+                   ^ u[(j >> 3) & 7] << 3
+                   ^ u[(j >> 6) & 7] << 6
+                   ^ u[(j >> 9) & 7] << 9
+                   ^ u[(j >> 12) & 7] << 12;
+                l ^= (g <<  k);
+                h ^= (g >> -k);
+            }
+            while ((k -= 15) > 0);
+
+            Debug.Assert(h >> 33 == 0);
+
+            z[zOff    ] ^= l & M49;
+            z[zOff + 1] ^= (l >> 49) ^ (h << 15);
+        }
+
+        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);
+            zz[6] = (x[3] & M01);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs
new file mode 100644
index 000000000..995d2ebdd
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.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 SecT193FieldElement
+        : ECFieldElement
+    {
+        protected readonly ulong[] x;
+
+        public SecT193FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.BitLength > 193)
+                throw new ArgumentException("value invalid for SecT193FieldElement", "x");
+
+            this.x = SecT193Field.FromBigInteger(x);
+        }
+
+        public SecT193FieldElement()
+        {
+            this.x = Nat256.Create64();
+        }
+
+        protected internal SecT193FieldElement(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 "SecT193Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return 193; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            ulong[] z = Nat256.Create64();
+            SecT193Field.Add(x, ((SecT193FieldElement)b).x, z);
+            return new SecT193FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            ulong[] z = Nat256.Create64();
+            SecT193Field.AddOne(x, z);
+            return new SecT193FieldElement(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();
+            SecT193Field.Multiply(x, ((SecT193FieldElement)b).x, z);
+            return new SecT193FieldElement(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 = ((SecT193FieldElement)b).x;
+            ulong[] xx = ((SecT193FieldElement)x).x, yx = ((SecT193FieldElement)y).x;
+
+            ulong[] tt = Nat256.CreateExt64();
+            SecT193Field.MultiplyAddToExt(ax, bx, tt);
+            SecT193Field.MultiplyAddToExt(xx, yx, tt);
+
+            ulong[] z = Nat256.Create64();
+            SecT193Field.Reduce(tt, z);
+            return new SecT193FieldElement(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();
+            SecT193Field.Square(x, z);
+            return new SecT193FieldElement(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 = ((SecT193FieldElement)x).x, yx = ((SecT193FieldElement)y).x;
+
+            ulong[] tt = Nat256.CreateExt64();
+            SecT193Field.SquareAddToExt(ax, tt);
+            SecT193Field.MultiplyAddToExt(xx, yx, tt);
+
+            ulong[] z = Nat256.Create64();
+            SecT193Field.Reduce(tt, z);
+            return new SecT193FieldElement(z);
+        }
+
+        public override ECFieldElement SquarePow(int pow)
+        {
+            if (pow < 1)
+                return this;
+
+            ulong[] z = Nat256.Create64();
+            SecT193Field.SquareN(x, pow, z);
+            return new SecT193FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            return new SecT193FieldElement(
+                AbstractF2mCurve.Inverse(193, new int[] { 15 }, ToBigInteger()));
+        }
+
+        public override ECFieldElement Sqrt()
+        {
+            return SquarePow(M - 1);
+        }
+
+        public virtual int Representation
+        {
+            get { return F2mFieldElement.Tpb; }
+        }
+
+        public virtual int M
+        {
+            get { return 193; }
+        }
+
+        public virtual int K1
+        {
+            get { return 15; }
+        }
+
+        public virtual int K2
+        {
+            get { return 0; }
+        }
+
+        public virtual int K3
+        {
+            get { return 0; }
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecT193FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecT193FieldElement);
+        }
+
+        public virtual bool Equals(SecT193FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat256.Eq64(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return 1930015 ^ Arrays.GetHashCode(x, 0, 4);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
new file mode 100644
index 000000000..802954b01
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
@@ -0,0 +1,190 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecT193R1Curve
+        : AbstractF2mCurve
+    {
+        private const int SecT193R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+        protected readonly SecT193R1Point m_infinity;
+
+        public SecT193R1Curve()
+            : base(193, 15, 0, 0)
+        {
+            this.m_infinity = new SecT193R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01")));
+            this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814")));
+            this.m_order = new BigInteger(1, Hex.Decode("01000000000000000000000000C7F34A778F443ACC920EBA49"));
+            this.m_cofactor = BigInteger.Two;
+
+            this.m_coord = SecT193R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecT193R1Curve();
+        }
+
+        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 193; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecT193FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecT193R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecT193R1Point(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 <code>z<sup>2</sup> + z = beta</code>(X9.62
+         * D.1.6) The other solution is <code>z + 1</code>.
+         * 
+         * @param beta
+         *            The value to solve the quadratic equation for.
+         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+         *         <code>null</code> 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(193, rand));
+                z = zeroElement;
+                ECFieldElement w = beta;
+                for (int i = 1; i < 193; 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 193; }
+        }
+
+        public virtual bool IsTrinomial
+        {
+            get { return true; }
+        }
+
+        public virtual int K1
+        {
+            get { return 15; }
+        }
+
+        public virtual int K2
+        {
+            get { return 0; }
+        }
+
+        public virtual int K3
+        {
+            get { return 0; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Point.cs b/crypto/src/math/ec/custom/sec/SecT193R1Point.cs
new file mode 100644
index 000000000..062fce9d4
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193R1Point.cs
@@ -0,0 +1,283 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecT193R1Point
+        : AbstractF2mPoint
+    {
+        /**
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecT193R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+         */
+        public SecT193R1Point(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 SecT193R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(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 SecT193R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+        }
+    }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
new file mode 100644
index 000000000..b5345730c
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
@@ -0,0 +1,190 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecT193R2Curve
+        : AbstractF2mCurve
+    {
+        private const int SecT193R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+        protected readonly SecT193R2Point m_infinity;
+
+        public SecT193R2Curve()
+            : base(193, 15, 0, 0)
+        {
+            this.m_infinity = new SecT193R2Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B")));
+            this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE")));
+            this.m_order = new BigInteger(1, Hex.Decode("010000000000000000000000015AAB561B005413CCD4EE99D5"));
+            this.m_cofactor = BigInteger.Two;
+
+            this.m_coord = SecT193R2_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecT193R2Curve();
+        }
+
+        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 193; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecT193FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecT193R2Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecT193R2Point(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 <code>z<sup>2</sup> + z = beta</code>(X9.62
+         * D.1.6) The other solution is <code>z + 1</code>.
+         * 
+         * @param beta
+         *            The value to solve the quadratic equation for.
+         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+         *         <code>null</code> 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(193, rand));
+                z = zeroElement;
+                ECFieldElement w = beta;
+                for (int i = 1; i < 193; 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 193; }
+        }
+
+        public virtual bool IsTrinomial
+        {
+            get { return true; }
+        }
+
+        public virtual int K1
+        {
+            get { return 15; }
+        }
+
+        public virtual int K2
+        {
+            get { return 0; }
+        }
+
+        public virtual int K3
+        {
+            get { return 0; }
+        }
+    }
+}
diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Point.cs b/crypto/src/math/ec/custom/sec/SecT193R2Point.cs
new file mode 100644
index 000000000..18d89e316
--- /dev/null
+++ b/crypto/src/math/ec/custom/sec/SecT193R2Point.cs
@@ -0,0 +1,283 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecT193R2Point
+        : AbstractF2mPoint
+    {
+        /**
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecT193R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+         */
+        public SecT193R2Point(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 SecT193R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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 SecT193R2Point(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
index 165fadbf3..b36ffba2e 100644
--- a/crypto/src/math/ec/custom/sec/SecT233Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs
@@ -200,7 +200,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 59 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
@@ -215,7 +215,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             int k = 54;
             do
             {
-                j = (uint)(x >> k);
+                j  = (uint)(x >> k);
                 g  = u[j & 7]
                    ^ u[(j >> 3) & 7] << 3;
                 l ^= (g <<  k);
diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
index 439c41d37..60b204604 100644
--- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT233FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 233)
                 throw new ArgumentException("value invalid for SecT233FieldElement", "x");
 
             this.x = SecT233Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs
index 1e0824af9..6dab907dd 100644
--- a/crypto/src/math/ec/custom/sec/SecT239Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs
@@ -204,7 +204,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 60 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
@@ -219,7 +219,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             int k = 54;
             do
             {
-                j = (uint)(x >> k);
+                j  = (uint)(x >> k);
                 g  = u[j & 7]
                    ^ u[(j >> 3) & 7] << 3;
                 l ^= (g <<  k);
diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
index c89b484b1..e7bfffd1f 100644
--- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT239FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 239)
                 throw new ArgumentException("value invalid for SecT239FieldElement", "x");
 
             this.x = SecT239Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs
index 9afb27461..435787467 100644
--- a/crypto/src/math/ec/custom/sec/SecT283Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs
@@ -292,7 +292,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 57 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
@@ -306,7 +306,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             int k = 48;
             do
             {
-                j = (uint)(x >> k);
+                j  = (uint)(x >> k);
                 g  = u[j & 7]
                    ^ u[(j >> 3) & 7] << 3
                    ^ u[(j >> 6) & 7] << 6;
diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
index 09243e859..9181b8685 100644
--- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT283FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 283)
                 throw new ArgumentException("value invalid for SecT283FieldElement", "x");
 
             this.x = SecT283Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs
index d71f5b5f9..ce6f43f2e 100644
--- a/crypto/src/math/ec/custom/sec/SecT409Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs
@@ -196,7 +196,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             Debug.Assert(y >> 59 == 0);
 
             ulong[] u = new ulong[8];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             u[2] = u[1] << 1;
             u[3] = u[2] ^  y;
diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
index 6dabf6a7a..b60ceafee 100644
--- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT409FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 409)
                 throw new ArgumentException("value invalid for SecT409FieldElement", "x");
 
             this.x = SecT409Field.FromBigInteger(x);
diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs
index 0711ee4aa..921c841a9 100644
--- a/crypto/src/math/ec/custom/sec/SecT571Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs
@@ -199,7 +199,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
         protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff)
         {
             ulong[] u = new ulong[32];
-    //      u[0] = 0;
+            //u[0] = 0;
             u[1] = y;
             for (int i = 2; i < 32; i += 2)
             {
diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
index 8474c912e..a26e1e336 100644
--- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public SecT571FieldElement(BigInteger x)
         {
-            if (x == null || x.SignValue < 0)
+            if (x == null || x.SignValue < 0 || x.BitLength > 571)
                 throw new ArgumentException("value invalid for SecT571FieldElement", "x");
 
             this.x = SecT571Field.FromBigInteger(x);
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index 249b94ea6..5bde2c8fe 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -2,6 +2,7 @@ using System;
 using System.Collections;
 using System.IO;
 
+using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
@@ -104,6 +105,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 {
                     this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
                 }
+                else if (key is ECPublicBcpgKey)
+                {
+                    this.keyStrength = ECNamedCurveTable.GetByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
+                }
             }
         }
 
diff --git a/crypto/src/pkix/PkixCertPathChecker.cs b/crypto/src/pkix/PkixCertPathChecker.cs
index f22738d89..da7e82b46 100644
--- a/crypto/src/pkix/PkixCertPathChecker.cs
+++ b/crypto/src/pkix/PkixCertPathChecker.cs
@@ -1,5 +1,3 @@
-using System;
-using System.Collections;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.X509;
 
@@ -82,7 +80,7 @@ namespace Org.BouncyCastle.Pkix
          * @exception CertPathValidatorException
          *                if the specified certificate does not pass the check
          */
-        public abstract void Check(X509Certificate cert, ICollection unresolvedCritExts);
+        public abstract void Check(X509Certificate cert, ISet unresolvedCritExts);
         //throws CertPathValidatorException;
 
         /**
diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs
index ee95d3b01..70957acc7 100644
--- a/crypto/src/util/io/Streams.cs
+++ b/crypto/src/util/io/Streams.cs
@@ -83,10 +83,10 @@ namespace Org.BouncyCastle.Utilities.IO
 			int numRead;
 			while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0)
 			{
-				total += numRead;
-				if (total > limit)
+                if ((limit - total) < numRead)
 					throw new StreamOverflowException("Data Overflow");
-				outStr.Write(bs, 0, numRead);
+                total += numRead;
+                outStr.Write(bs, 0, numRead);
 			}
 			return total;
 		}
diff --git a/crypto/test/src/test/CertPathValidatorTest.cs b/crypto/test/src/test/CertPathValidatorTest.cs
index a92bb9b31..f83ac850a 100644
--- a/crypto/test/src/test/CertPathValidatorTest.cs
+++ b/crypto/test/src/test/CertPathValidatorTest.cs
@@ -290,7 +290,7 @@ namespace Org.BouncyCastle.Tests
                 return null;
             }
 
-            public override void Check(X509Certificate cert, ICollection unresolvedCritExts)
+            public override void Check(X509Certificate cert, ISet unresolvedCritExts)
             {
                 count++;
             }