summary refs log tree commit diff
path: root/crypto/src/math/ec/ECCurve.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/math/ec/ECCurve.cs')
-rw-r--r--crypto/src/math/ec/ECCurve.cs82
1 files changed, 81 insertions, 1 deletions
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index f011b1baf..2b193ba06 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -677,6 +677,9 @@ namespace Org.BouncyCastle.Math.EC
     {
         private const int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
 
+        private static readonly IDictionary knownQs = Platform.CreateHashtable();
+        private static readonly SecureRandom random = new SecureRandom();
+
         protected readonly BigInteger m_q, m_r;
         protected readonly FpPoint m_infinity;
 
@@ -687,9 +690,42 @@ namespace Org.BouncyCastle.Math.EC
         }
 
         public FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
+            : this(q, a, b, order, cofactor, false)
+        {
+        }
+
+        internal FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor, bool isInternal)
             : base(q)
         {
-            this.m_q = q;
+            if (isInternal)
+            {
+                this.m_q = q;
+                knownQs.add(q);
+            }
+            else if (knownQs.contains(q))
+            {
+                this.m_q = q;
+            }
+            else
+            {
+                int maxBitLength = AsInteger("Org.BouncyCastle.EC.Fp_MaxSize", 1042); // 2 * 521
+                int certainty = AsInteger("Org.BouncyCastle.EC.Fp_Certainty", 100);
+
+                int qBitLength = q.BitLength;
+                if (maxBitLength < qBitLength)
+                {
+                    throw new ArgumentException("Fp q value out of range");
+                }
+
+                if (Primes.HasAnySmallFactors(q) || !Primes.IsMRProbablePrime(
+                    q, random, getNumberOfIterations(qBitLength, certainty)))
+                {
+                    throw new ArgumentException("Fp q value not prime");
+                }
+
+                this.m_q = q;
+            }
+
             this.m_r = FpFieldElement.CalculateResidue(q);
             this.m_infinity = new FpPoint(this, null, null, false);
 
@@ -790,6 +826,50 @@ namespace Org.BouncyCastle.Math.EC
 
             return base.ImportPoint(p);
         }
+
+        private int GetNumberOfIterations(int bits, int certainty)
+        {
+            /*
+             * NOTE: We enforce a minimum 'certainty' of 100 for bits >= 1024 (else 80). Where the
+             * certainty is higher than the FIPS 186-4 tables (C.2/C.3) cater to, extra iterations
+             * are added at the "worst case rate" for the excess.
+             */
+            if (bits >= 1536)
+            {
+                return  certainty <= 100 ? 3
+                    :   certainty <= 128 ? 4
+                    :   4 + (certainty - 128 + 1) / 2;
+            }
+            else if (bits >= 1024)
+            {
+                return  certainty <= 100 ? 4
+                    :   certainty <= 112 ? 5
+                    :   5 + (certainty - 112 + 1) / 2;
+            }
+            else if (bits >= 512)
+            {
+                return  certainty <= 80  ? 5
+                    :   certainty <= 100 ? 7
+                    :   7 + (certainty - 100 + 1) / 2;
+            }
+            else
+            {
+                return  certainty <= 80  ? 40
+                    :   40 + (certainty - 80 + 1) / 2;
+            }
+        }
+
+        int AsInteger(string envVariable, int defaultValue)
+        {
+            String v = Platform.GetEnvironmentVariable(envVariable);
+
+            if (v == null)
+            {
+                return defaultValue;
+            }
+
+            return Int32.Parse(v);
+        }
     }
 
     public abstract class AbstractF2mCurve