diff options
Diffstat (limited to 'crypto/src/math/ec/multiplier')
8 files changed, 309 insertions, 192 deletions
diff --git a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs index 517881323..c2580c852 100644 --- a/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs +++ b/crypto/src/math/ec/multiplier/AbstractECMultiplier.cs @@ -16,9 +16,14 @@ * Although the various multipliers ought not to produce invalid output under normal * circumstances, a final check here is advised to guard against fault attacks. */ - return ECAlgorithms.ValidatePoint(result); + return CheckResult(result); } protected abstract ECPoint MultiplyPositive(ECPoint p, BigInteger k); + + protected virtual ECPoint CheckResult(ECPoint p) + { + return ECAlgorithms.ImplCheckResult(p); + } } } diff --git a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs index adaedb809..505832442 100644 --- a/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs +++ b/crypto/src/math/ec/multiplier/FixedPointCombMultiplier.cs @@ -52,11 +52,5 @@ namespace Org.BouncyCastle.Math.EC.Multiplier return R.Add(info.Offset); } - - [Obsolete("Is no longer used; remove any overrides in subclasses.")] - protected virtual int GetWidthForCombSize(int combSize) - { - return combSize > 257 ? 6 : 5; - } } } diff --git a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs index 4c0b404df..5d6af9e5d 100644 --- a/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs +++ b/crypto/src/math/ec/multiplier/FixedPointPreCompInfo.cs @@ -11,13 +11,6 @@ namespace Org.BouncyCastle.Math.EC.Multiplier protected ECPoint m_offset = null; /** - * Array holding the precomputed <code>ECPoint</code>s used for a fixed - * point multiplication. - */ - [Obsolete("Will be removed")] - protected ECPoint[] m_preComp = null; - - /** * Lookup table for the precomputed <code>ECPoint</code>s used for a fixed point multiplication. */ protected ECLookupTable m_lookupTable = null; @@ -41,13 +34,6 @@ namespace Org.BouncyCastle.Math.EC.Multiplier set { this.m_offset = value; } } - [Obsolete("Use 'LookupTable' property instead.")] - public virtual ECPoint[] PreComp - { - get { return m_preComp; } - set { this.m_preComp = value; } - } - public virtual int Width { get { return m_width; } diff --git a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs index cc7203314..88f178e24 100644 --- a/crypto/src/math/ec/multiplier/FixedPointUtilities.cs +++ b/crypto/src/math/ec/multiplier/FixedPointUtilities.cs @@ -14,36 +14,40 @@ namespace Org.BouncyCastle.Math.EC.Multiplier public static FixedPointPreCompInfo GetFixedPointPreCompInfo(PreCompInfo preCompInfo) { - if ((preCompInfo != null) && (preCompInfo is FixedPointPreCompInfo)) - { - return (FixedPointPreCompInfo)preCompInfo; - } - - return new FixedPointPreCompInfo(); + return preCompInfo as FixedPointPreCompInfo; } - [Obsolete("Use 'Precompute(ECPoint)' instead, as minWidth parameter is now ignored")] - public static FixedPointPreCompInfo Precompute(ECPoint p, int minWidth) + public static FixedPointPreCompInfo Precompute(ECPoint p) { - return Precompute(p); + return (FixedPointPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new FixedPointCallback(p)); } - public static FixedPointPreCompInfo Precompute(ECPoint p) + private class FixedPointCallback + : IPreCompCallback { - ECCurve c = p.Curve; - int minWidth = GetCombSize(c) > 257 ? 6 : 5; + private readonly ECPoint m_p; - int n = 1 << minWidth; - FixedPointPreCompInfo info = GetFixedPointPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME)); - ECPoint[] lookupTable = info.PreComp; + internal FixedPointCallback(ECPoint p) + { + this.m_p = p; + } - if (lookupTable == null || lookupTable.Length < n) + public PreCompInfo Precompute(PreCompInfo existing) { - int bits = GetCombSize(c); + FixedPointPreCompInfo existingFP = (existing is FixedPointPreCompInfo) ? (FixedPointPreCompInfo)existing : null; + + ECCurve c = m_p.Curve; + int bits = FixedPointUtilities.GetCombSize(c); + int minWidth = bits > 250 ? 6 : 5; + int n = 1 << minWidth; + + if (CheckExisting(existingFP, n)) + return existingFP; + int d = (bits + minWidth - 1) / minWidth; ECPoint[] pow2Table = new ECPoint[minWidth + 1]; - pow2Table[0] = p; + pow2Table[0] = m_p; for (int i = 1; i < minWidth; ++i) { pow2Table[i] = pow2Table[i - 1].TimesPow2(d); @@ -53,8 +57,8 @@ namespace Org.BouncyCastle.Math.EC.Multiplier pow2Table[minWidth] = pow2Table[0].Subtract(pow2Table[1]); c.NormalizeAll(pow2Table); - - lookupTable = new ECPoint[n]; + + ECPoint[] lookupTable = new ECPoint[n]; lookupTable[0] = pow2Table[0]; for (int bit = minWidth - 1; bit >= 0; --bit) @@ -70,15 +74,22 @@ namespace Org.BouncyCastle.Math.EC.Multiplier c.NormalizeAll(lookupTable); - info.LookupTable = c.CreateCacheSafeLookupTable(lookupTable, 0, lookupTable.Length); - info.Offset = pow2Table[minWidth]; - info.PreComp = lookupTable; - info.Width = minWidth; + FixedPointPreCompInfo result = new FixedPointPreCompInfo(); + result.LookupTable = c.CreateCacheSafeLookupTable(lookupTable, 0, lookupTable.Length); + result.Offset = pow2Table[minWidth]; + result.Width = minWidth; + return result; + } - c.SetPreCompInfo(p, PRECOMP_NAME, info); + private bool CheckExisting(FixedPointPreCompInfo existingFP, int n) + { + return existingFP != null && CheckTable(existingFP.LookupTable, n); } - return info; + private bool CheckTable(ECLookupTable table, int n) + { + return table != null && table.Size >= n; + } } } } diff --git a/crypto/src/math/ec/multiplier/IPreCompCallback.cs b/crypto/src/math/ec/multiplier/IPreCompCallback.cs new file mode 100644 index 000000000..e64ae834d --- /dev/null +++ b/crypto/src/math/ec/multiplier/IPreCompCallback.cs @@ -0,0 +1,9 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + public interface IPreCompCallback + { + PreCompInfo Precompute(PreCompInfo existing); + } +} diff --git a/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs b/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs new file mode 100644 index 000000000..7ec2cbb95 --- /dev/null +++ b/crypto/src/math/ec/multiplier/ValidityPreCompInfo.cs @@ -0,0 +1,44 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Multiplier +{ + internal class ValidityPreCompInfo + : PreCompInfo + { + internal static readonly string PRECOMP_NAME = "bc_validity"; + + private bool failed = false; + private bool curveEquationPassed = false; + private bool orderPassed = false; + + internal bool HasFailed() + { + return failed; + } + + internal void ReportFailed() + { + failed = true; + } + + internal bool HasCurveEquationPassed() + { + return curveEquationPassed; + } + + internal void ReportCurveEquationPassed() + { + curveEquationPassed = true; + } + + internal bool HasOrderPassed() + { + return orderPassed; + } + + internal void ReportOrderPassed() + { + orderPassed = true; + } + } +} diff --git a/crypto/src/math/ec/multiplier/WNafUtilities.cs b/crypto/src/math/ec/multiplier/WNafUtilities.cs index 7d565dfbd..e893abd49 100644 --- a/crypto/src/math/ec/multiplier/WNafUtilities.cs +++ b/crypto/src/math/ec/multiplier/WNafUtilities.cs @@ -287,12 +287,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo) { - if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo)) - { - return (WNafPreCompInfo)preCompInfo; - } - - return new WNafPreCompInfo(); + return preCompInfo as WNafPreCompInfo; } /** @@ -333,106 +328,178 @@ namespace Org.BouncyCastle.Math.EC.Multiplier WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated); ECPoint q = pointMap.Map(p); - WNafPreCompInfo wnafPreCompQ = GetWNafPreCompInfo(c.GetPreCompInfo(q, PRECOMP_NAME)); + c.Precompute(q, PRECOMP_NAME, new MapPointCallback(wnafPreCompP, includeNegated, pointMap)); + return q; + } - ECPoint twiceP = wnafPreCompP.Twice; - if (twiceP != null) - { - ECPoint twiceQ = pointMap.Map(twiceP); - wnafPreCompQ.Twice = twiceQ; - } + public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated) + { + return (WNafPreCompInfo)p.Curve.Precompute(p, PRECOMP_NAME, new WNafCallback(p, width, includeNegated)); + } + + private static byte[] Trim(byte[] a, int length) + { + byte[] result = new byte[length]; + Array.Copy(a, 0, result, 0, result.Length); + return result; + } + + private static int[] Trim(int[] a, int length) + { + int[] result = new int[length]; + Array.Copy(a, 0, result, 0, result.Length); + return result; + } + + private static ECPoint[] ResizeTable(ECPoint[] a, int length) + { + ECPoint[] result = new ECPoint[length]; + Array.Copy(a, 0, result, 0, a.Length); + return result; + } + + private class MapPointCallback + : IPreCompCallback + { + private readonly WNafPreCompInfo m_wnafPreCompP; + private readonly bool m_includeNegated; + private readonly ECPointMap m_pointMap; - ECPoint[] preCompP = wnafPreCompP.PreComp; - ECPoint[] preCompQ = new ECPoint[preCompP.Length]; - for (int i = 0; i < preCompP.Length; ++i) + internal MapPointCallback(WNafPreCompInfo wnafPreCompP, bool includeNegated, ECPointMap pointMap) { - preCompQ[i] = pointMap.Map(preCompP[i]); + this.m_wnafPreCompP = wnafPreCompP; + this.m_includeNegated = includeNegated; + this.m_pointMap = pointMap; } - wnafPreCompQ.PreComp = preCompQ; - if (includeNegated) + public PreCompInfo Precompute(PreCompInfo existing) { - ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length]; - for (int i = 0; i < preCompNegQ.Length; ++i) + WNafPreCompInfo result = new WNafPreCompInfo(); + + ECPoint twiceP = m_wnafPreCompP.Twice; + if (twiceP != null) { - preCompNegQ[i] = preCompQ[i].Negate(); + ECPoint twiceQ = m_pointMap.Map(twiceP); + result.Twice = twiceQ; } - wnafPreCompQ.PreCompNeg = preCompNegQ; - } - c.SetPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ); + ECPoint[] preCompP = m_wnafPreCompP.PreComp; + ECPoint[] preCompQ = new ECPoint[preCompP.Length]; + for (int i = 0; i < preCompP.Length; ++i) + { + preCompQ[i] = m_pointMap.Map(preCompP[i]); + } + result.PreComp = preCompQ; - return q; + if (m_includeNegated) + { + ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length]; + for (int i = 0; i < preCompNegQ.Length; ++i) + { + preCompNegQ[i] = preCompQ[i].Negate(); + } + result.PreCompNeg = preCompNegQ; + } + + return result; + } } - public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated) + private class WNafCallback + : IPreCompCallback { - ECCurve c = p.Curve; - WNafPreCompInfo wnafPreCompInfo = GetWNafPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME)); + private readonly ECPoint m_p; + private readonly int m_width; + private readonly bool m_includeNegated; - int iniPreCompLen = 0, reqPreCompLen = 1 << System.Math.Max(0, width - 2); - - ECPoint[] preComp = wnafPreCompInfo.PreComp; - if (preComp == null) + internal WNafCallback(ECPoint p, int width, bool includeNegated) { - preComp = EMPTY_POINTS; - } - else - { - iniPreCompLen = preComp.Length; + this.m_p = p; + this.m_width = width; + this.m_includeNegated = includeNegated; } - if (iniPreCompLen < reqPreCompLen) + public PreCompInfo Precompute(PreCompInfo existing) { - preComp = ResizeTable(preComp, reqPreCompLen); + WNafPreCompInfo existingWNaf = existing as WNafPreCompInfo; + + int reqPreCompLen = 1 << System.Math.Max(0, m_width - 2); + + if (CheckExisting(existingWNaf, reqPreCompLen, m_includeNegated)) + return existingWNaf; - if (reqPreCompLen == 1) + ECCurve c = m_p.Curve; + ECPoint[] preComp = null, preCompNeg = null; + ECPoint twiceP = null; + + if (existingWNaf != null) + { + preComp = existingWNaf.PreComp; + preCompNeg = existingWNaf.PreCompNeg; + twiceP = existingWNaf.Twice; + } + + int iniPreCompLen = 0; + if (preComp == null) { - preComp[0] = p.Normalize(); + preComp = EMPTY_POINTS; } else { - int curPreCompLen = iniPreCompLen; - if (curPreCompLen == 0) - { - preComp[0] = p; - curPreCompLen = 1; - } + iniPreCompLen = preComp.Length; + } - ECFieldElement iso = null; + if (iniPreCompLen < reqPreCompLen) + { + preComp = WNafUtilities.ResizeTable(preComp, reqPreCompLen); - if (reqPreCompLen == 2) + if (reqPreCompLen == 1) { - preComp[1] = p.ThreeTimes(); + preComp[0] = m_p.Normalize(); } else { - ECPoint twiceP = wnafPreCompInfo.Twice, last = preComp[curPreCompLen - 1]; - if (twiceP == null) + int curPreCompLen = iniPreCompLen; + if (curPreCompLen == 0) + { + preComp[0] = m_p; + curPreCompLen = 1; + } + + ECFieldElement iso = null; + + if (reqPreCompLen == 2) + { + preComp[1] = m_p.ThreeTimes(); + } + else { - twiceP = preComp[0].Twice(); - wnafPreCompInfo.Twice = twiceP; - - /* - * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism - * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This - * also requires scaling the initial point's X, Y coordinates, and reversing the - * isomorphism as part of the subsequent normalization. - * - * NOTE: The correctness of this optimization depends on: - * 1) additions do not use the curve's A, B coefficients. - * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ... - */ - if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64) + ECPoint isoTwiceP = twiceP, last = preComp[curPreCompLen - 1]; + if (isoTwiceP == null) { - switch (c.CoordinateSystem) + isoTwiceP = preComp[0].Twice(); + twiceP = isoTwiceP; + + /* + * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism + * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This + * also requires scaling the initial point's X, Y coordinates, and reversing the + * isomorphism as part of the subsequent normalization. + * + * NOTE: The correctness of this optimization depends on: + * 1) additions do not use the curve's A, B coefficients. + * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ... + */ + if (!twiceP.IsInfinity && ECAlgorithms.IsFpCurve(c) && c.FieldSize >= 64) { + switch (c.CoordinateSystem) + { case ECCurve.COORD_JACOBIAN: case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: case ECCurve.COORD_JACOBIAN_MODIFIED: { iso = twiceP.GetZCoord(0); - twiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(), + isoTwiceP = c.CreatePoint(twiceP.XCoord.ToBigInteger(), twiceP.YCoord.ToBigInteger()); ECFieldElement iso2 = iso.Square(), iso3 = iso2.Multiply(iso); @@ -444,81 +511,69 @@ namespace Org.BouncyCastle.Math.EC.Multiplier } break; } + } } } - } - while (curPreCompLen < reqPreCompLen) - { - /* - * Compute the new ECPoints for the precomputation array. The values 1, 3, - * 5, ..., 2^(width-1)-1 times p are computed - */ - preComp[curPreCompLen++] = last = last.Add(twiceP); + while (curPreCompLen < reqPreCompLen) + { + /* + * Compute the new ECPoints for the precomputation array. The values 1, 3, + * 5, ..., 2^(width-1)-1 times p are computed + */ + preComp[curPreCompLen++] = last = last.Add(isoTwiceP); + } } - } - /* - * Having oft-used operands in affine form makes operations faster. - */ - c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso); + /* + * Having oft-used operands in affine form makes operations faster. + */ + c.NormalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso); + } } - } - - wnafPreCompInfo.PreComp = preComp; - - if (includeNegated) - { - ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg; - int pos; - if (preCompNeg == null) - { - pos = 0; - preCompNeg = new ECPoint[reqPreCompLen]; - } - else + if (m_includeNegated) { - pos = preCompNeg.Length; - if (pos < reqPreCompLen) + int pos; + if (preCompNeg == null) { - preCompNeg = ResizeTable(preCompNeg, reqPreCompLen); + pos = 0; + preCompNeg = new ECPoint[reqPreCompLen]; + } + else + { + pos = preCompNeg.Length; + if (pos < reqPreCompLen) + { + preCompNeg = WNafUtilities.ResizeTable(preCompNeg, reqPreCompLen); + } } - } - while (pos < reqPreCompLen) - { - preCompNeg[pos] = preComp[pos].Negate(); - ++pos; + while (pos < reqPreCompLen) + { + preCompNeg[pos] = preComp[pos].Negate(); + ++pos; + } } - wnafPreCompInfo.PreCompNeg = preCompNeg; + WNafPreCompInfo result = new WNafPreCompInfo(); + result.PreComp = preComp; + result.PreCompNeg = preCompNeg; + result.Twice = twiceP; + return result; } - c.SetPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo); - - return wnafPreCompInfo; - } - - private static byte[] Trim(byte[] a, int length) - { - byte[] result = new byte[length]; - Array.Copy(a, 0, result, 0, result.Length); - return result; - } - - private static int[] Trim(int[] a, int length) - { - int[] result = new int[length]; - Array.Copy(a, 0, result, 0, result.Length); - return result; - } + private bool CheckExisting(WNafPreCompInfo existingWNaf, int reqPreCompLen, bool includeNegated) + { + return existingWNaf != null + && CheckTable(existingWNaf.PreComp, reqPreCompLen) + && (!includeNegated || CheckTable(existingWNaf.PreCompNeg, reqPreCompLen)); + } - private static ECPoint[] ResizeTable(ECPoint[] a, int length) - { - ECPoint[] result = new ECPoint[length]; - Array.Copy(a, 0, result, 0, a.Length); - return result; + private bool CheckTable(ECPoint[] table, int reqLen) + { + return table != null && table.Length >= reqLen; + } } } } diff --git a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs index 1e7ddae91..4dce54440 100644 --- a/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs +++ b/crypto/src/math/ec/multiplier/WTauNafMultiplier.cs @@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10); - return MultiplyWTnaf(p, rho, curve.GetPreCompInfo(p, PRECOMP_NAME), a, mu); + return MultiplyWTnaf(p, rho, a, mu); } /** @@ -50,7 +50,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier * @return <code>p</code> multiplied by <code>λ</code>. */ private AbstractF2mPoint MultiplyWTnaf(AbstractF2mPoint p, ZTauElement lambda, - PreCompInfo preCompInfo, sbyte a, sbyte mu) + sbyte a, sbyte mu) { ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1; @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width, BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha); - return MultiplyFromWTnaf(p, u, preCompInfo); + return MultiplyFromWTnaf(p, u); } /** @@ -71,24 +71,14 @@ namespace Org.BouncyCastle.Math.EC.Multiplier * @param u The the WTNAF of <code>λ</code>.. * @return <code>λ * p</code> */ - private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u, PreCompInfo preCompInfo) + private static AbstractF2mPoint MultiplyFromWTnaf(AbstractF2mPoint p, sbyte[] u) { AbstractF2mCurve curve = (AbstractF2mCurve)p.Curve; sbyte a = (sbyte)curve.A.ToBigInteger().IntValue; - AbstractF2mPoint[] pu; - if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo)) - { - pu = Tnaf.GetPreComp(p, a); - - WTauNafPreCompInfo pre = new WTauNafPreCompInfo(); - pre.PreComp = pu; - curve.SetPreCompInfo(p, PRECOMP_NAME, pre); - } - else - { - pu = ((WTauNafPreCompInfo)preCompInfo).PreComp; - } + WTauNafCallback callback = new WTauNafCallback(p, a); + WTauNafPreCompInfo preCompInfo = (WTauNafPreCompInfo)curve.Precompute(p, PRECOMP_NAME, callback); + AbstractF2mPoint[] pu = preCompInfo.PreComp; // TODO Include negations in precomp (optionally) and use from here AbstractF2mPoint[] puNeg = new AbstractF2mPoint[pu.Length]; @@ -121,5 +111,28 @@ namespace Org.BouncyCastle.Math.EC.Multiplier } return q; } + + private class WTauNafCallback + : IPreCompCallback + { + private readonly AbstractF2mPoint m_p; + private readonly sbyte m_a; + + internal WTauNafCallback(AbstractF2mPoint p, sbyte a) + { + this.m_p = p; + this.m_a = a; + } + + public PreCompInfo Precompute(PreCompInfo existing) + { + if (existing is WTauNafPreCompInfo) + return existing; + + WTauNafPreCompInfo result = new WTauNafPreCompInfo(); + result.PreComp = Tnaf.GetPreComp(m_p, m_a); + return result; + } + } } } |