summary refs log tree commit diff
path: root/crypto/src/math/ec/multiplier/WNafUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/math/ec/multiplier/WNafUtilities.cs')
-rw-r--r--crypto/src/math/ec/multiplier/WNafUtilities.cs311
1 files changed, 183 insertions, 128 deletions
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;
+            }
         }
     }
 }