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
|