summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-02-26 20:13:52 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-02-26 20:13:52 +0700
commit57d401f1c1919e507eb42ac0964a8b5d61ee6049 (patch)
tree413d79b8d57700b9270ab4533787474910e44822 /crypto/src
parentOptimize Sqrt() for custom curve secp224k1 (diff)
downloadBouncyCastle.NET-ed25519-57d401f1c1919e507eb42ac0964a8b5d61ee6049.tar.xz
Optimization for custom curve reduction when only a few bits need reducing; used to delay reduction in point doubling.
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/math/ec/custom/sec/Nat192.cs57
-rw-r--r--crypto/src/math/ec/custom/sec/Nat224.cs17
-rw-r--r--crypto/src/math/ec/custom/sec/Nat256.cs17
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192K1Field.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192K1Point.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192R1Field.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP192R1Point.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224K1Field.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224K1Point.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224R1Field.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP224R1Point.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256K1Field.cs12
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256K1Point.cs9
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1Field.cs36
-rw-r--r--crypto/src/math/ec/custom/sec/SecP256R1Point.cs9
15 files changed, 205 insertions, 30 deletions
diff --git a/crypto/src/math/ec/custom/sec/Nat192.cs b/crypto/src/math/ec/custom/sec/Nat192.cs

index 6d908d1ca..35bf75445 100644 --- a/crypto/src/math/ec/custom/sec/Nat192.cs +++ b/crypto/src/math/ec/custom/sec/Nat192.cs
@@ -108,6 +108,15 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return (uint)c; } + public static uint AddWord(uint x, uint[] z, int zOff) + { + Debug.Assert(zOff <= 5); + ulong c = (ulong)x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Inc(z, zOff + 1); + } + public static uint AddWordExt(uint x, uint[] zz, int zzOff) { Debug.Assert(zzOff <= 11); @@ -140,6 +149,19 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return -1; } + public static int DecExt(uint[] z, int zOff) + { + Debug.Assert(zOff <= 12); + for (int i = zOff; i < 12; ++i) + { + if (--z[i] != uint.MaxValue) + { + return 0; + } + } + return -1; + } + public static uint[] FromBigInteger(BigInteger x) { if (x.SignValue < 0 || x.BitLength > 192) @@ -400,6 +422,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return c == 0 ? 0 : Inc(z, zOff + 4); } + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <=3); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Inc(z, zOff + 3); + } + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) { Debug.Assert(zOff <= 3); @@ -695,6 +734,24 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return (int)c; } + public static int SubWord(uint x, uint[] z, int zOff) + { + Debug.Assert(zOff <= 5); + long c = (long)z[zOff + 0] - x; + z[zOff + 0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Dec(z, zOff + 1); + } + + public static int SubWordExt(uint x, uint[] zz, int zzOff) + { + Debug.Assert(zzOff <= 11); + long c = (long)zz[zzOff + 0] - x; + zz[zzOff + 0] = (uint)c; + c >>= 32; + return c == 0 ? 0 : DecExt(zz, zzOff + 1); + } + public static BigInteger ToBigInteger(uint[] x) { byte[] bs = new byte[24]; diff --git a/crypto/src/math/ec/custom/sec/Nat224.cs b/crypto/src/math/ec/custom/sec/Nat224.cs
index 72950e8a6..a391fc248 100644 --- a/crypto/src/math/ec/custom/sec/Nat224.cs +++ b/crypto/src/math/ec/custom/sec/Nat224.cs
@@ -730,6 +730,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return c == 0 ? 0 : Inc(z, zOff + 4); } + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 4); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Inc(z, zOff + 3); + } + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) { Debug.Assert(zOff <= 4); diff --git a/crypto/src/math/ec/custom/sec/Nat256.cs b/crypto/src/math/ec/custom/sec/Nat256.cs
index c846f56fb..aa6f4e5eb 100644 --- a/crypto/src/math/ec/custom/sec/Nat256.cs +++ b/crypto/src/math/ec/custom/sec/Nat256.cs
@@ -781,6 +781,23 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return c == 0 ? 0 : Inc(z, zOff + 4); } + public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff) + { + Debug.Assert(x >> 31 == 0); + Debug.Assert(zOff <= 5); + ulong c = 0, yVal = y; + c += yVal * x + z[zOff + 0]; + z[zOff + 0] = (uint)c; + c >>= 32; + c += yVal + z[zOff + 1]; + z[zOff + 1] = (uint)c; + c >>= 32; + c += z[zOff + 2]; + z[zOff + 2] = (uint)c; + c >>= 32; + return c == 0 ? 0 : Inc(z, zOff + 3); + } + public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff) { Debug.Assert(zOff <= 5); diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Field.cs b/crypto/src/math/ec/custom/sec/SecP192K1Field.cs
index 832db0fbe..eef42eecc 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Field.cs
@@ -97,6 +97,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + uint c = Nat192.Mul33WordAdd(PInv33, x, z, 0); + + Debug.Assert(c == 0 || c == 1); + + if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P))) + { + Nat192.AddDWord(PInv, z, 0); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat192.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs
index 364c62480..1c6573aca 100644 --- a/crypto/src/math/ec/custom/sec/SecP192K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192K1Point.cs
@@ -205,12 +205,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP192K1Field.Multiply(Y1Squared, X1.x, S); - SecP192K1Field.Twice(S, S); - SecP192K1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(6, S, 2, 0); + SecP192K1Field.Reduce32(c, S); - SecP192K1Field.Twice(T, t1); - SecP192K1Field.Twice(t1, t1); - SecP192K1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(6, T, 3, 0, t1); + SecP192K1Field.Reduce32(c, t1); SecP192K1FieldElement X3 = new SecP192K1FieldElement(T); SecP192K1Field.Square(M, X3.x); diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Field.cs b/crypto/src/math/ec/custom/sec/SecP192R1Field.cs
index fdb1fa863..3871d9abb 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Field.cs
@@ -131,6 +131,15 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + uint c = Nat192.AddWord(x, z, 0) + Nat192.AddWord(x, z, 2); + if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P))) + { + Nat192.Sub(z, P, z); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat192.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs
index 0dd81f0c7..29a26c941 100644 --- a/crypto/src/math/ec/custom/sec/SecP192R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP192R1Point.cs
@@ -217,12 +217,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP192R1Field.Multiply(Y1Squared, X1.x, S); - SecP192R1Field.Twice(S, S); - SecP192R1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(6, S, 2, 0); + SecP192R1Field.Reduce32(c, S); - SecP192R1Field.Twice(T, t1); - SecP192R1Field.Twice(t1, t1); - SecP192R1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(6, T, 3, 0, t1); + SecP192R1Field.Reduce32(c, t1); SecP192R1FieldElement X3 = new SecP192R1FieldElement(T); SecP192R1Field.Square(M, X3.x); diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Field.cs b/crypto/src/math/ec/custom/sec/SecP224K1Field.cs
index edc938d22..ce07eff67 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Field.cs
@@ -98,6 +98,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + uint c = Nat224.Mul33WordAdd(PInv33, x, z, 0); + + Debug.Assert(c == 0 || c == 1); + + if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P))) + { + Nat224.AddDWord(PInv, z, 0); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat224.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs
index f85c64981..c7119401d 100644 --- a/crypto/src/math/ec/custom/sec/SecP224K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224K1Point.cs
@@ -205,12 +205,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP224K1Field.Multiply(Y1Squared, X1.x, S); - SecP224K1Field.Twice(S, S); - SecP224K1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(7, S, 2, 0); + SecP224K1Field.Reduce32(c, S); - SecP224K1Field.Twice(T, t1); - SecP224K1Field.Twice(t1, t1); - SecP224K1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(7, T, 3, 0, t1); + SecP224K1Field.Reduce32(c, t1); SecP224K1FieldElement X3 = new SecP224K1FieldElement(T); SecP224K1Field.Square(M, X3.x); diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Field.cs b/crypto/src/math/ec/custom/sec/SecP224R1Field.cs
index 4eb04325a..1cb3fe352 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Field.cs
@@ -137,6 +137,15 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + int c = Nat224.SubWord(x, z, 0) + (int)Nat224.AddWord(x, z, 3); + if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P))) + { + Nat224.Sub(z, P, z); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat224.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs
index 251415179..31cef6929 100644 --- a/crypto/src/math/ec/custom/sec/SecP224R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP224R1Point.cs
@@ -217,12 +217,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP224R1Field.Multiply(Y1Squared, X1.x, S); - SecP224R1Field.Twice(S, S); - SecP224R1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(7, S, 2, 0); + SecP224R1Field.Reduce32(c, S); - SecP224R1Field.Twice(T, t1); - SecP224R1Field.Twice(t1, t1); - SecP224R1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(7, T, 3, 0, t1); + SecP224R1Field.Reduce32(c, t1); SecP224R1FieldElement X3 = new SecP224R1FieldElement(T); SecP224R1Field.Square(M, X3.x); diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Field.cs b/crypto/src/math/ec/custom/sec/SecP256K1Field.cs
index b3c964982..8852339d3 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Field.cs
@@ -99,6 +99,18 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + uint c = Nat256.Mul33WordAdd(PInv33, x, z, 0); + + Debug.Assert(c == 0 || c == 1); + + if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P))) + { + Nat256.AddDWord(PInv, z, 0); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat256.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs
index d981911a6..d8e1eb83a 100644 --- a/crypto/src/math/ec/custom/sec/SecP256K1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256K1Point.cs
@@ -205,12 +205,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP256K1Field.Multiply(Y1Squared, X1.x, S); - SecP256K1Field.Twice(S, S); - SecP256K1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(8, S, 2, 0); + SecP256K1Field.Reduce32(c, S); - SecP256K1Field.Twice(T, t1); - SecP256K1Field.Twice(t1, t1); - SecP256K1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(8, T, 3, 0, t1); + SecP256K1Field.Reduce32(c, t1); SecP256K1FieldElement X3 = new SecP256K1FieldElement(T); SecP256K1Field.Square(M, X3.x); diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Field.cs b/crypto/src/math/ec/custom/sec/SecP256R1Field.cs
index 88a13f513..9e366bffe 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Field.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Field.cs
@@ -145,6 +145,42 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec } } + public static void Reduce32(uint x, uint[] z) + { + long xx08 = x; + + long cc = 0; + cc += (long)z[0] + xx08; + z[0] = (uint)cc; + cc >>= 32; + cc += (long)z[1]; + z[1] = (uint)cc; + cc >>= 32; + cc += (long)z[2]; + z[2] = (uint)cc; + cc >>= 32; + cc += (long)z[3] - xx08; + z[3] = (uint)cc; + cc >>= 32; + cc += (long)z[4]; + z[4] = (uint)cc; + cc >>= 32; + cc += (long)z[5]; + z[5] = (uint)cc; + cc >>= 32; + cc += (long)z[6] - xx08; + z[6] = (uint)cc; + cc >>= 32; + cc += (long)z[7] + xx08; + z[7] = (uint)cc; + cc >>= 32; + + if (cc != 0 || (z[7] == P7 && Nat256.Gte(z, P))) + { + Nat256.Sub(z, P, z); + } + } + public static void Square(uint[] x, uint[] z) { uint[] tt = Nat256.CreateExt(); diff --git a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs
index be54e0dda..e25ff5f7a 100644 --- a/crypto/src/math/ec/custom/sec/SecP256R1Point.cs +++ b/crypto/src/math/ec/custom/sec/SecP256R1Point.cs
@@ -217,12 +217,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec uint[] S = Y1Squared; SecP256R1Field.Multiply(Y1Squared, X1.x, S); - SecP256R1Field.Twice(S, S); - SecP256R1Field.Twice(S, S); + uint c = Nat.ShiftUpBits(8, S, 2, 0); + SecP256R1Field.Reduce32(c, S); - SecP256R1Field.Twice(T, t1); - SecP256R1Field.Twice(t1, t1); - SecP256R1Field.Twice(t1, t1); + c = Nat.ShiftUpBits(8, T, 3, 0, t1); + SecP256R1Field.Reduce32(c, t1); SecP256R1FieldElement X3 = new SecP256R1FieldElement(T); SecP256R1Field.Square(M, X3.x);