diff options
Diffstat (limited to 'crypto')
36 files changed, 2073 insertions, 117 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 80d0e3e8b..93ca2cf23 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -5529,6 +5529,36 @@ BuildAction = "Compile" /> <File + RelPath = "src\math\ec\custom\sec\SecT193Field.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\math\ec\custom\sec\SecT193FieldElement.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\math\ec\custom\sec\SecT193R1Curve.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\math\ec\custom\sec\SecT193R1Point.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\math\ec\custom\sec\SecT193R2Curve.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\math\ec\custom\sec\SecT193R2Point.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\math\ec\custom\sec\SecT233Field.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/x9/X9ECParametersHolder.cs b/crypto/src/asn1/x9/X9ECParametersHolder.cs index f0a320094..e802b738c 100644 --- a/crypto/src/asn1/x9/X9ECParametersHolder.cs +++ b/crypto/src/asn1/x9/X9ECParametersHolder.cs @@ -10,15 +10,15 @@ namespace Org.BouncyCastle.Asn1.X9 { lock (this) { - if (parameters == null) - { - parameters = CreateParameters(); - } + if (parameters == null) + { + parameters = CreateParameters(); + } return parameters; } } - } + } protected abstract X9ECParameters CreateParameters(); } diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs index 3c69fbdf5..2e08cd090 100644 --- a/crypto/src/bcpg/BcpgInputStream.cs +++ b/crypto/src/bcpg/BcpgInputStream.cs @@ -105,19 +105,15 @@ namespace Org.BouncyCastle.Bcpg next = true; } - if (nextB >= 0) + if (nextB < 0) + return (PacketTag)nextB; + + int maskB = nextB & 0x3f; + if ((nextB & 0x40) == 0) // old { - if ((nextB & 0x40) != 0) // new - { - return (PacketTag)(nextB & 0x3f); - } - else // old - { - return (PacketTag)((nextB & 0x3f) >> 2); - } + maskB >>= 2; } - - return (PacketTag) nextB; + return (PacketTag)maskB; } public Packet ReadPacket() diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs index 20af29a50..581286a3f 100644 --- a/crypto/src/cms/SignerInformation.cs +++ b/crypto/src/cms/SignerInformation.cs @@ -345,9 +345,12 @@ namespace Org.BouncyCastle.Cms // if (sigParams != null) // throw new CmsException("unrecognised signature parameters provided"); - string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid); + string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid); - sig = Helper.GetSignatureInstance(signatureName); + sig = Helper.GetSignatureInstance(signatureName); + + //sig = Helper.GetSignatureInstance(this.EncryptionAlgOid); + //sig = SignerUtilities.GetSigner(sigAlgOid); } try diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs index 9b7935523..0f13b4571 100644 --- a/crypto/src/crypto/ec/CustomNamedCurves.cs +++ b/crypto/src/crypto/ec/CustomNamedCurves.cs @@ -516,6 +516,48 @@ namespace Org.BouncyCastle.Crypto.EC }; /* + * sect193r1 + */ + internal class SecT193R1Holder + : X9ECParametersHolder + { + private SecT193R1Holder() { } + + internal static readonly X9ECParametersHolder Instance = new SecT193R1Holder(); + + protected override X9ECParameters CreateParameters() + { + byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30"); + ECCurve curve = ConfigureCurve(new SecT193R1Curve()); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1" + + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05")); + return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S); + } + }; + + /* + * sect193r2 + */ + internal class SecT193R2Holder + : X9ECParametersHolder + { + private SecT193R2Holder() { } + + internal static readonly X9ECParametersHolder Instance = new SecT193R2Holder(); + + protected override X9ECParameters CreateParameters() + { + byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211"); + ECCurve curve = ConfigureCurve(new SecT193R2Curve()); + ECPoint G = curve.DecodePoint(Hex.Decode("04" + + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F" + + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C")); + return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S); + } + }; + + /* * sect233k1 */ internal class SecT233K1Holder @@ -766,6 +808,8 @@ namespace Org.BouncyCastle.Crypto.EC DefineCurveWithOid("sect163k1", SecObjectIdentifiers.SecT163k1, SecT163K1Holder.Instance); DefineCurveWithOid("sect163r1", SecObjectIdentifiers.SecT163r1, SecT163R1Holder.Instance); DefineCurveWithOid("sect163r2", SecObjectIdentifiers.SecT163r2, SecT163R2Holder.Instance); + DefineCurveWithOid("sect193r1", SecObjectIdentifiers.SecT193r1, SecT193R1Holder.Instance); + DefineCurveWithOid("sect193r2", SecObjectIdentifiers.SecT193r2, SecT193R2Holder.Instance); DefineCurveWithOid("sect233k1", SecObjectIdentifiers.SecT233k1, SecT233K1Holder.Instance); DefineCurveWithOid("sect233r1", SecObjectIdentifiers.SecT233r1, SecT233R1Holder.Instance); DefineCurveWithOid("sect239k1", SecObjectIdentifiers.SecT239k1, SecT239K1Holder.Instance); diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs index 9d7f76c05..164c43ee9 100644 --- a/crypto/src/crypto/engines/AesEngine.cs +++ b/crypto/src/crypto/engines/AesEngine.cs @@ -237,12 +237,22 @@ namespace Org.BouncyCastle.Crypto.Engines private const uint m1 = 0x80808080; private const uint m2 = 0x7f7f7f7f; private const uint m3 = 0x0000001b; + private const uint m4 = 0xC0C0C0C0; + private const uint m5 = 0x3f3f3f3f; private static uint FFmulX(uint x) { return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3); } + private static uint FFmulX2(uint x) + { + uint t0 = (x & m5) << 2; + uint t1 = (x & m4); + t1 ^= (t1 >> 1); + return t0 ^ (t1 >> 2) ^ (t1 >> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -255,12 +265,13 @@ namespace Org.BouncyCastle.Crypto.Engines private static uint Inv_Mcol(uint x) { - uint f2 = FFmulX(x); - uint f4 = FFmulX(f2); - uint f8 = FFmulX(f4); - uint f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + uint t0, t1; + t0 = x; + t1 = t0 ^ Shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ Shift(t1, 16); + return t0; } private static uint SubWord(uint x) diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs index a1b544568..38ce1a946 100644 --- a/crypto/src/crypto/engines/AesFastEngine.cs +++ b/crypto/src/crypto/engines/AesFastEngine.cs @@ -573,12 +573,22 @@ namespace Org.BouncyCastle.Crypto.Engines private const uint m1 = 0x80808080; private const uint m2 = 0x7f7f7f7f; private const uint m3 = 0x0000001b; + private const uint m4 = 0xC0C0C0C0; + private const uint m5 = 0x3f3f3f3f; private static uint FFmulX(uint x) { return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3); } + private static uint FFmulX2(uint x) + { + uint t0 = (x & m5) << 2; + uint t1 = (x & m4); + t1 ^= (t1 >> 1); + return t0 ^ (t1 >> 2) ^ (t1 >> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -591,12 +601,13 @@ namespace Org.BouncyCastle.Crypto.Engines private static uint Inv_Mcol(uint x) { - uint f2 = FFmulX(x); - uint f4 = FFmulX(f2); - uint f8 = FFmulX(f4); - uint f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + uint t0, t1; + t0 = x; + t1 = t0 ^ Shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ Shift(t1, 16); + return t0; } private static uint SubWord(uint x) diff --git a/crypto/src/crypto/engines/AesLightEngine.cs b/crypto/src/crypto/engines/AesLightEngine.cs index a6b9e3bd4..a42b34971 100644 --- a/crypto/src/crypto/engines/AesLightEngine.cs +++ b/crypto/src/crypto/engines/AesLightEngine.cs @@ -126,12 +126,22 @@ namespace Org.BouncyCastle.Crypto.Engines private const uint m1 = 0x80808080; private const uint m2 = 0x7f7f7f7f; private const uint m3 = 0x0000001b; + private const uint m4 = 0xC0C0C0C0; + private const uint m5 = 0x3f3f3f3f; private static uint FFmulX(uint x) { return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3); } + private static uint FFmulX2(uint x) + { + uint t0 = (x & m5) << 2; + uint t1 = (x & m4); + t1 ^= (t1 >> 1); + return t0 ^ (t1 >> 2) ^ (t1 >> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -144,18 +154,21 @@ namespace Org.BouncyCastle.Crypto.Engines private static uint Mcol(uint x) { - uint f2 = FFmulX(x); - return f2 ^ Shift(x ^ f2, 8) ^ Shift(x, 16) ^ Shift(x, 24); + uint t0, t1; + t0 = Shift(x, 8); + t1 = x ^ t0; + return Shift(t1, 16) ^ t0 ^ FFmulX(t1); } private static uint Inv_Mcol(uint x) { - uint f2 = FFmulX(x); - uint f4 = FFmulX(f2); - uint f8 = FFmulX(f4); - uint f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + uint t0, t1; + t0 = x; + t1 = t0 ^ Shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ Shift(t1, 16); + return t0; } private static uint SubWord(uint x) diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs index de41d88f4..d8ab2ca73 100644 --- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -46,6 +46,13 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm return tmp; } + internal static ulong[] OneAsUlongs() + { + ulong[] tmp = new ulong[2]; + tmp[0] = 1UL << 63; + return tmp; + } + internal static byte[] AsBytes(uint[] x) { return Pack.UInt32_To_BE(x); @@ -56,6 +63,18 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm Pack.UInt32_To_BE(x, z, 0); } + internal static byte[] AsBytes(ulong[] x) + { + byte[] z = new byte[16]; + Pack.UInt64_To_BE(x, z, 0); + return z; + } + + internal static void AsBytes(ulong[] x, byte[] z) + { + Pack.UInt64_To_BE(x, z, 0); + } + internal static uint[] AsUints(byte[] bs) { uint[] output = new uint[4]; @@ -68,6 +87,18 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm Pack.BE_To_UInt32(bs, 0, output); } + internal static ulong[] AsUlongs(byte[] x) + { + ulong[] z = new ulong[2]; + Pack.BE_To_UInt64(x, 0, z); + return z; + } + + public static void AsUlongs(byte[] x, ulong[] z) + { + Pack.BE_To_UInt64(x, 0, z); + } + internal static void Multiply(byte[] x, byte[] y) { uint[] t1 = GcmUtilities.AsUints(x); @@ -80,7 +111,7 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm { uint r00 = x[0], r01 = x[1], r02 = x[2], r03 = x[3]; uint r10 = 0, r11 = 0, r12 = 0, r13 = 0; - + for (int i = 0; i < 4; ++i) { int bits = (int)y[i]; @@ -93,9 +124,9 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm r13 ^= (r03 & m1); uint m2 = (uint)((int)(r03 << 31) >> 8); - r03 = (r03 >> 1) | (r02 << 63); - r02 = (r02 >> 1) | (r01 << 63); - r01 = (r01 >> 1) | (r00 << 63); + r03 = (r03 >> 1) | (r02 << 31); + r02 = (r02 >> 1) | (r01 << 31); + r01 = (r01 >> 1) | (r00 << 31); r00 = (r00 >> 1) ^ (m2 & E1); } } @@ -119,7 +150,7 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm r10 ^= (r00 & m1); r11 ^= (r01 & m1); - ulong m2 = (r01 << 63) >> 8; + ulong m2 = (ulong)((long)(r01 << 63) >> 8); r01 = (r01 >> 1) | (r00 << 63); r00 = (r00 >> 1) ^ (m2 & E1L); } @@ -272,5 +303,17 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm z[2] = x[2] ^ y[2]; z[3] = x[3] ^ y[3]; } + + internal static void Xor(ulong[] x, ulong[] y) + { + x[0] ^= y[0]; + x[1] ^= y[1]; + } + + internal static void Xor(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + } } } diff --git a/crypto/src/crypto/parameters/DHParameters.cs b/crypto/src/crypto/parameters/DHParameters.cs index a0544e73b..4258df5c5 100644 --- a/crypto/src/crypto/parameters/DHParameters.cs +++ b/crypto/src/crypto/parameters/DHParameters.cs @@ -91,6 +91,7 @@ namespace Org.BouncyCastle.Crypto.Parameters throw new ArgumentException("m value must be < bitlength of p", "m"); if (l != 0) { + // TODO Check this against the Java version, which has 'l > p.BitLength' here if (l >= p.BitLength) throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l"); if (l < m) diff --git a/crypto/src/crypto/util/Pack.cs b/crypto/src/crypto/util/Pack.cs index 087cb7cea..dc00ab450 100644 --- a/crypto/src/crypto/util/Pack.cs +++ b/crypto/src/crypto/util/Pack.cs @@ -117,6 +117,22 @@ namespace Org.BouncyCastle.Crypto.Utilities UInt32_To_BE((uint)(n), bs, off + 4); } + internal static byte[] UInt64_To_BE(ulong[] ns) + { + byte[] bs = new byte[8 * ns.Length]; + UInt64_To_BE(ns, bs, 0); + return bs; + } + + internal static void UInt64_To_BE(ulong[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.Length; ++i) + { + UInt64_To_BE(ns[i], bs, off); + off += 8; + } + } + internal static ulong BE_To_UInt64(byte[] bs) { uint hi = BE_To_UInt32(bs); @@ -131,6 +147,15 @@ namespace Org.BouncyCastle.Crypto.Utilities return ((ulong)hi << 32) | (ulong)lo; } + internal static void BE_To_UInt64(byte[] bs, int off, ulong[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = BE_To_UInt64(bs, off); + off += 8; + } + } + internal static void UInt16_To_LE(ushort n, byte[] bs) { bs[0] = (byte)(n); diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs index dbb645e6f..640c6e787 100644 --- a/crypto/src/math/ec/custom/sec/SecT113Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs @@ -37,6 +37,35 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat128.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion + + ulong[] t0 = Nat128.Create64(); + ulong[] t1 = Nat128.Create64(); + + Square(x, t0); + Multiply(t0, x, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 3, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 7, t0); + Multiply(t0, t1, t0); + SquareN(t0, 14, t1); + Multiply(t1, t0, t1); + SquareN(t1, 28, t0); + Multiply(t0, t1, t0); + SquareN(t0, 56, t1); + Multiply(t1, t0, t1); + Square(t1, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat128.CreateExt64(); diff --git a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs index e3a923f62..f217e28cb 100644 --- a/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT113FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT113FieldElement( - AbstractF2mCurve.Inverse(113, new int[]{ 9 }, ToBigInteger())); + ulong[] z = Nat128.Create64(); + SecT113Field.Invert(x, z); + return new SecT113FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs index df75dfcd7..47f97078c 100644 --- a/crypto/src/math/ec/custom/sec/SecT131Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs @@ -40,6 +40,35 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat192.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion + + ulong[] t0 = Nat192.Create64(); + ulong[] t1 = Nat192.Create64(); + + Square(x, t0); + Multiply(t0, x, t0); + SquareN(t0, 2, t1); + Multiply(t1, t0, t1); + SquareN(t1, 4, t0); + Multiply(t0, t1, t0); + SquareN(t0, 8, t1); + Multiply(t1, t0, t1); + SquareN(t1, 16, t0); + Multiply(t0, t1, t0); + SquareN(t0, 32, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 65, t0); + Multiply(t0, t1, t0); + Square(t0, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat192.CreateExt64(); @@ -231,7 +260,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 45 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; @@ -247,7 +276,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec int k = 33; do { - j = (uint)(x >> k); + j = (uint)(x >> k); g = u[j & 7] ^ u[(j >> 3) & 7] << 3 ^ u[(j >> 6) & 7] << 6 diff --git a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs index 65aaf01ba..0ea00ea07 100644 --- a/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT131FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT131FieldElement( - AbstractF2mCurve.Inverse(131, new int[] { 2, 3, 8 }, ToBigInteger())); + ulong[] z = Nat192.Create64(); + SecT131Field.Invert(x, z); + return new SecT131FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs index 2a775e20d..f921a5bc7 100644 --- a/crypto/src/math/ec/custom/sec/SecT163Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs @@ -41,6 +41,47 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat192.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion with bases { 2, 3 } + + ulong[] t0 = Nat192.Create64(); + ulong[] t1 = Nat192.Create64(); + + Square(x, t0); + + // 3 | 162 + SquareN(t0, 1, t1); + Multiply(t0, t1, t0); + SquareN(t1, 1, t1); + Multiply(t0, t1, t0); + + // 3 | 54 + SquareN(t0, 3, t1); + Multiply(t0, t1, t0); + SquareN(t1, 3, t1); + Multiply(t0, t1, t0); + + // 3 | 18 + SquareN(t0, 9, t1); + Multiply(t0, t1, t0); + SquareN(t1, 9, t1); + Multiply(t0, t1, t0); + + // 3 | 6 + SquareN(t0, 27, t1); + Multiply(t0, t1, t0); + SquareN(t1, 27, t1); + Multiply(t0, t1, t0); + + // 2 | 2 + SquareN(t0, 81, t1); + Multiply(t0, t1, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat192.CreateExt64(); @@ -230,7 +271,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 56 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; @@ -244,7 +285,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec int k = 47; do { - j = (uint)(x >> k); + j = (uint)(x >> k); g = u[j & 7] ^ u[(j >> 3) & 7] << 3 ^ u[(j >> 6) & 7] << 6; diff --git a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs index 3ab383a1d..c7a0b5639 100644 --- a/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT163FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT163FieldElement( - AbstractF2mCurve.Inverse(163, new int[] { 3, 6, 7 }, ToBigInteger())); + ulong[] z = Nat192.Create64(); + SecT163Field.Invert(x, z); + return new SecT163FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs new file mode 100644 index 000000000..5154f1e0a --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs @@ -0,0 +1,282 @@ +using System; +using System.Diagnostics; + +using Org.BouncyCastle.Math.Raw; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193Field + { + private const ulong M01 = 1UL; + private const ulong M49 = ulong.MaxValue >> 15; + + public static void Add(ulong[] x, ulong[] y, ulong[] z) + { + z[0] = x[0] ^ y[0]; + z[1] = x[1] ^ y[1]; + z[2] = x[2] ^ y[2]; + z[3] = x[3] ^ y[3]; + } + + public static void AddExt(ulong[] xx, ulong[] yy, ulong[] zz) + { + zz[0] = xx[0] ^ yy[0]; + zz[1] = xx[1] ^ yy[1]; + zz[2] = xx[2] ^ yy[2]; + zz[3] = xx[3] ^ yy[3]; + zz[4] = xx[4] ^ yy[4]; + zz[5] = xx[5] ^ yy[5]; + zz[6] = xx[6] ^ yy[6]; + } + + public static void AddOne(ulong[] x, ulong[] z) + { + z[0] = x[0] ^ 1UL; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + } + + public static ulong[] FromBigInteger(BigInteger x) + { + ulong[] z = Nat256.FromBigInteger64(x); + Reduce63(z, 0); + return z; + } + + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat256.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion with bases { 2, 3 } + + ulong[] t0 = Nat256.Create64(); + ulong[] t1 = Nat256.Create64(); + + Square(x, t0); + + // 3 | 192 + SquareN(t0, 1, t1); + Multiply(t0, t1, t0); + SquareN(t1, 1, t1); + Multiply(t0, t1, t0); + + // 2 | 64 + SquareN(t0, 3, t1); + Multiply(t0, t1, t0); + + // 2 | 32 + SquareN(t0, 6, t1); + Multiply(t0, t1, t0); + + // 2 | 16 + SquareN(t0, 12, t1); + Multiply(t0, t1, t0); + + // 2 | 8 + SquareN(t0, 24, t1); + Multiply(t0, t1, t0); + + // 2 | 4 + SquareN(t0, 48, t1); + Multiply(t0, t1, t0); + + // 2 | 2 + SquareN(t0, 96, t1); + Multiply(t0, t1, z); + } + + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + Reduce(tt, z); + } + + public static void MultiplyAddToExt(ulong[] x, ulong[] y, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplMultiply(x, y, tt); + AddExt(zz, tt, zz); + } + + public static void Reduce(ulong[] xx, ulong[] z) + { + ulong x0 = xx[0], x1 = xx[1], x2 = xx[2], x3 = xx[3], x4 = xx[4], x5 = xx[5], x6 = xx[6]; + + x2 ^= (x6 << 63); + x3 ^= (x6 >> 1) ^ (x6 << 14); + x4 ^= (x6 >> 50); + + x1 ^= (x5 << 63); + x2 ^= (x5 >> 1) ^ (x5 << 14); + x3 ^= (x5 >> 50); + + x0 ^= (x4 << 63); + x1 ^= (x4 >> 1) ^ (x4 << 14); + x2 ^= (x4 >> 50); + + ulong t = x3 >> 1; + z[0] = x0 ^ t ^ (t << 15); + z[1] = x1 ^ (t >> 49); + z[2] = x2; + z[3] = x3 & M01; + } + + public static void Reduce63(ulong[] z, int zOff) + { + ulong z3 = z[zOff + 3], t = z3 >> 1; + z[zOff ] ^= t ^ (t << 15); + z[zOff + 1] ^= (t >> 49); + z[zOff + 3] = z3 & M01; + } + + public static void Square(ulong[] x, ulong[] z) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + } + + public static void SquareAddToExt(ulong[] x, ulong[] zz) + { + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + AddExt(zz, tt, zz); + } + + public static void SquareN(ulong[] x, int n, ulong[] z) + { + Debug.Assert(n > 0); + + ulong[] tt = Nat256.CreateExt64(); + ImplSquare(x, tt); + Reduce(tt, z); + + while (--n > 0) + { + ImplSquare(z, tt); + Reduce(tt, z); + } + } + + protected static void ImplCompactExt(ulong[] zz) + { + ulong z0 = zz[0], z1 = zz[1], z2 = zz[2], z3 = zz[3], z4 = zz[4], z5 = zz[5], z6 = zz[6], z7 = zz[7]; + zz[0] = z0 ^ (z1 << 49); + zz[1] = (z1 >> 15) ^ (z2 << 34); + zz[2] = (z2 >> 30) ^ (z3 << 19); + zz[3] = (z3 >> 45) ^ (z4 << 4) + ^ (z5 << 53); + zz[4] = (z4 >> 60) ^ (z6 << 38) + ^ (z5 >> 11); + zz[5] = (z6 >> 26) ^ (z7 << 23); + zz[6] = (z7 >> 41); + zz[7] = 0; + } + + protected static void ImplExpand(ulong[] x, ulong[] z) + { + ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3]; + z[0] = x0 & M49; + z[1] = ((x0 >> 49) ^ (x1 << 15)) & M49; + z[2] = ((x1 >> 34) ^ (x2 << 30)) & M49; + z[3] = ((x2 >> 19) ^ (x3 << 45)); + } + + protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) + { + /* + * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. + */ + + ulong[] f = new ulong[4], g = new ulong[4]; + ImplExpand(x, f); + ImplExpand(y, g); + + ImplMulwAcc(f[0], g[0], zz, 0); + ImplMulwAcc(f[1], g[1], zz, 1); + ImplMulwAcc(f[2], g[2], zz, 2); + ImplMulwAcc(f[3], g[3], zz, 3); + + // U *= (1 - t^n) + for (int i = 5; i > 0; --i) + { + zz[i] ^= zz[i - 1]; + } + + ImplMulwAcc(f[0] ^ f[1], g[0] ^ g[1], zz, 1); + ImplMulwAcc(f[2] ^ f[3], g[2] ^ g[3], zz, 3); + + // V *= (1 - t^2n) + for (int i = 7; i > 1; --i) + { + zz[i] ^= zz[i - 2]; + } + + // Double-length recursion + { + ulong c0 = f[0] ^ f[2], c1 = f[1] ^ f[3]; + ulong d0 = g[0] ^ g[2], d1 = g[1] ^ g[3]; + ImplMulwAcc(c0 ^ c1, d0 ^ d1, zz, 3); + ulong[] t = new ulong[3]; + ImplMulwAcc(c0, d0, t, 0); + ImplMulwAcc(c1, d1, t, 1); + ulong t0 = t[0], t1 = t[1], t2 = t[2]; + zz[2] ^= t0; + zz[3] ^= t0 ^ t1; + zz[4] ^= t2 ^ t1; + zz[5] ^= t2; + } + + ImplCompactExt(zz); + } + + protected static void ImplMulwAcc(ulong x, ulong y, ulong[] z, int zOff) + { + Debug.Assert(x >> 49 == 0); + Debug.Assert(y >> 49 == 0); + + ulong[] u = new ulong[8]; + //u[0] = 0; + u[1] = y; + u[2] = u[1] << 1; + u[3] = u[2] ^ y; + u[4] = u[2] << 1; + u[5] = u[4] ^ y; + u[6] = u[3] << 1; + u[7] = u[6] ^ y; + + uint j = (uint)x; + ulong g, h = 0, l = u[j & 7] + ^ (u[(j >> 3) & 7] << 3); + int k = 36; + do + { + j = (uint)(x >> k); + g = u[j & 7] + ^ u[(j >> 3) & 7] << 3 + ^ u[(j >> 6) & 7] << 6 + ^ u[(j >> 9) & 7] << 9 + ^ u[(j >> 12) & 7] << 12; + l ^= (g << k); + h ^= (g >> -k); + } + while ((k -= 15) > 0); + + Debug.Assert(h >> 33 == 0); + + z[zOff ] ^= l & M49; + z[zOff + 1] ^= (l >> 49) ^ (h << 15); + } + + protected static void ImplSquare(ulong[] x, ulong[] zz) + { + Interleave.Expand64To128(x[0], zz, 0); + Interleave.Expand64To128(x[1], zz, 2); + Interleave.Expand64To128(x[2], zz, 4); + zz[6] = (x[3] & M01); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs new file mode 100644 index 000000000..eba4d10e6 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193FieldElement.cs @@ -0,0 +1,214 @@ +using System; + +using Org.BouncyCastle.Math.Raw; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193FieldElement + : ECFieldElement + { + protected readonly ulong[] x; + + public SecT193FieldElement(BigInteger x) + { + if (x == null || x.SignValue < 0 || x.BitLength > 193) + throw new ArgumentException("value invalid for SecT193FieldElement", "x"); + + this.x = SecT193Field.FromBigInteger(x); + } + + public SecT193FieldElement() + { + this.x = Nat256.Create64(); + } + + protected internal SecT193FieldElement(ulong[] x) + { + this.x = x; + } + + public override bool IsOne + { + get { return Nat256.IsOne64(x); } + } + + public override bool IsZero + { + get { return Nat256.IsZero64(x); } + } + + public override bool TestBitZero() + { + return (x[0] & 1UL) != 0UL; + } + + public override BigInteger ToBigInteger() + { + return Nat256.ToBigInteger64(x); + } + + public override string FieldName + { + get { return "SecT193Field"; } + } + + public override int FieldSize + { + get { return 193; } + } + + public override ECFieldElement Add(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT193Field.Add(x, ((SecT193FieldElement)b).x, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement AddOne() + { + ulong[] z = Nat256.Create64(); + SecT193Field.AddOne(x, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement Subtract(ECFieldElement b) + { + // Addition and Subtraction are the same in F2m + return Add(b); + } + + public override ECFieldElement Multiply(ECFieldElement b) + { + ulong[] z = Nat256.Create64(); + SecT193Field.Multiply(x, ((SecT193FieldElement)b).x, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return MultiplyPlusProduct(b, x, y); + } + + public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x, bx = ((SecT193FieldElement)b).x; + ulong[] xx = ((SecT193FieldElement)x).x, yx = ((SecT193FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT193Field.MultiplyAddToExt(ax, bx, tt); + SecT193Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT193Field.Reduce(tt, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement Divide(ECFieldElement b) + { + return Multiply(b.Invert()); + } + + public override ECFieldElement Negate() + { + return this; + } + + public override ECFieldElement Square() + { + ulong[] z = Nat256.Create64(); + SecT193Field.Square(x, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return SquarePlusProduct(x, y); + } + + public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y) + { + ulong[] ax = this.x; + ulong[] xx = ((SecT193FieldElement)x).x, yx = ((SecT193FieldElement)y).x; + + ulong[] tt = Nat256.CreateExt64(); + SecT193Field.SquareAddToExt(ax, tt); + SecT193Field.MultiplyAddToExt(xx, yx, tt); + + ulong[] z = Nat256.Create64(); + SecT193Field.Reduce(tt, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement SquarePow(int pow) + { + if (pow < 1) + return this; + + ulong[] z = Nat256.Create64(); + SecT193Field.SquareN(x, pow, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement Invert() + { + ulong[] z = Nat256.Create64(); + SecT193Field.Invert(x, z); + return new SecT193FieldElement(z); + } + + public override ECFieldElement Sqrt() + { + return SquarePow(M - 1); + } + + public virtual int Representation + { + get { return F2mFieldElement.Tpb; } + } + + public virtual int M + { + get { return 193; } + } + + public virtual int K1 + { + get { return 15; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + + public override bool Equals(object obj) + { + return Equals(obj as SecT193FieldElement); + } + + public override bool Equals(ECFieldElement other) + { + return Equals(other as SecT193FieldElement); + } + + public virtual bool Equals(SecT193FieldElement other) + { + if (this == other) + return true; + if (null == other) + return false; + return Nat256.Eq64(x, other.x); + } + + public override int GetHashCode() + { + return 1930015 ^ Arrays.GetHashCode(x, 0, 4); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs new file mode 100644 index 000000000..802954b01 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs @@ -0,0 +1,190 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193R1Curve + : AbstractF2mCurve + { + private const int SecT193R1_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT193R1Point m_infinity; + + public SecT193R1Curve() + : base(193, 15, 0, 0) + { + this.m_infinity = new SecT193R1Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814"))); + this.m_order = new BigInteger(1, Hex.Decode("01000000000000000000000000C7F34A778F443ACC920EBA49")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT193R1_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT193R1Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 193; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT193FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT193R1Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT193R1Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 + * D.1.6) The other solution is <code>z + 1</code>. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for <code>z<sup>2</sup> + z = beta</code> or + * <code>null</code> if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(193, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 193; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 193; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 15; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Point.cs b/crypto/src/math/ec/custom/sec/SecT193R1Point.cs new file mode 100644 index 000000000..062fce9d4 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193R1Point.cs @@ -0,0 +1,283 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193R1Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT193R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT193R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT193R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT193R1Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT193R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT193R1Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT193R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT193R1Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT193R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT193R1Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT193R1Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT193R1Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs new file mode 100644 index 000000000..b5345730c --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs @@ -0,0 +1,190 @@ +using System; + +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193R2Curve + : AbstractF2mCurve + { + private const int SecT193R2_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; + + protected readonly SecT193R2Point m_infinity; + + public SecT193R2Curve() + : base(193, 15, 0, 0) + { + this.m_infinity = new SecT193R2Point(this, null, null); + + this.m_a = FromBigInteger(new BigInteger(1, Hex.Decode("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B"))); + this.m_b = FromBigInteger(new BigInteger(1, Hex.Decode("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE"))); + this.m_order = new BigInteger(1, Hex.Decode("010000000000000000000000015AAB561B005413CCD4EE99D5")); + this.m_cofactor = BigInteger.Two; + + this.m_coord = SecT193R2_DEFAULT_COORDS; + } + + protected override ECCurve CloneCurve() + { + return new SecT193R2Curve(); + } + + public override bool SupportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_LAMBDA_PROJECTIVE: + return true; + default: + return false; + } + } + + public override ECPoint Infinity + { + get { return m_infinity; } + } + + public override int FieldSize + { + get { return 193; } + } + + public override ECFieldElement FromBigInteger(BigInteger x) + { + return new SecT193FieldElement(x); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression) + { + return new SecT193R2Point(this, x, y, withCompression); + } + + protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + { + return new SecT193R2Point(this, x, y, zs, withCompression); + } + + public override bool IsKoblitz + { + get { return false; } + } + + /** + * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). + * + * @param yTilde + * ~yp, an indication bit for the decompression of yp. + * @param X1 + * The field element xp. + * @return the decompressed point. + */ + protected override ECPoint DecompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = FromBigInteger(X1), y = null; + if (x.IsZero) + { + y = B.Sqrt(); + } + else + { + ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x); + ECFieldElement z = SolveQuadraticEquation(beta); + if (z != null) + { + if (z.TestBitZero() != (yTilde == 1)) + { + z = z.AddOne(); + } + + switch (this.CoordinateSystem) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.Add(x); + break; + } + default: + { + y = z.Multiply(x); + break; + } + } + } + } + + if (y == null) + throw new ArgumentException("Invalid point compression"); + + return this.CreateRawPoint(x, y, true); + } + + /** + * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62 + * D.1.6) The other solution is <code>z + 1</code>. + * + * @param beta + * The value to solve the quadratic equation for. + * @return the solution for <code>z<sup>2</sup> + z = beta</code> or + * <code>null</code> if no solution exists. + */ + private ECFieldElement SolveQuadraticEquation(ECFieldElement beta) + { + if (beta.IsZero) + { + return beta; + } + + ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero); + + ECFieldElement z = null; + ECFieldElement gamma = null; + + Random rand = new Random(); + do + { + ECFieldElement t = FromBigInteger(new BigInteger(193, rand)); + z = zeroElement; + ECFieldElement w = beta; + for (int i = 1; i < 193; i++) + { + ECFieldElement w2 = w.Square(); + z = z.Square().Add(w2.Multiply(t)); + w = w2.Add(beta); + } + if (!w.IsZero) + return null; + gamma = z.Square().Add(z); + } + while (gamma.IsZero); + + return z; + } + + public virtual int M + { + get { return 193; } + } + + public virtual bool IsTrinomial + { + get { return true; } + } + + public virtual int K1 + { + get { return 15; } + } + + public virtual int K2 + { + get { return 0; } + } + + public virtual int K3 + { + get { return 0; } + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Point.cs b/crypto/src/math/ec/custom/sec/SecT193R2Point.cs new file mode 100644 index 000000000..18d89e316 --- /dev/null +++ b/crypto/src/math/ec/custom/sec/SecT193R2Point.cs @@ -0,0 +1,283 @@ +using System; + +namespace Org.BouncyCastle.Math.EC.Custom.Sec +{ + internal class SecT193R2Point + : AbstractF2mPoint + { + /** + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecT193R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y) + : this(curve, x, y, false) + { + } + + /** + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)} + */ + public SecT193R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression) + : base(curve, x, y, withCompression) + { + if ((x == null) != (y == null)) + throw new ArgumentException("Exactly one of the field elements is null"); + } + + internal SecT193R2Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression) + : base(curve, x, y, zs, withCompression) + { + } + + protected override ECPoint Detach() + { + return new SecT193R2Point(null, AffineXCoord, AffineYCoord); + } + + public override ECFieldElement YCoord + { + get + { + ECFieldElement X = RawXCoord, L = RawYCoord; + + if (this.IsInfinity || X.IsZero) + return L; + + // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly + ECFieldElement Y = L.Add(X).Multiply(X); + + ECFieldElement Z = RawZCoords[0]; + if (!Z.IsOne) + { + Y = Y.Divide(Z); + } + + return Y; + } + } + + protected internal override bool CompressionYTilde + { + get + { + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return false; + + ECFieldElement Y = this.RawYCoord; + + // Y is actually Lambda (X + Y/X) here + return Y.TestBitZero() != X.TestBitZero(); + } + } + + public override ECPoint Add(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return this; + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + ECFieldElement X2 = b.RawXCoord; + + if (X1.IsZero) + { + if (X2.IsZero) + return curve.Infinity; + + return b.Add(this); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement U2 = X2, S2 = L2; + if (!Z1IsOne) + { + U2 = U2.Multiply(Z1); + S2 = S2.Multiply(Z1); + } + + bool Z2IsOne = Z2.IsOne; + ECFieldElement U1 = X1, S1 = L1; + if (!Z2IsOne) + { + U1 = U1.Multiply(Z2); + S1 = S1.Multiply(Z2); + } + + ECFieldElement A = S1.Add(S2); + ECFieldElement B = U1.Add(U2); + + if (B.IsZero) + { + if (A.IsZero) + return Twice(); + + return curve.Infinity; + } + + ECFieldElement X3, L3, Z3; + if (X2.IsZero) + { + // TODO This can probably be optimized quite a bit + ECPoint p = this.Normalize(); + X1 = p.XCoord; + ECFieldElement Y1 = p.YCoord; + + ECFieldElement Y2 = L2; + ECFieldElement L = Y1.Add(Y2).Divide(X1); + + X3 = L.Square().Add(L).Add(X1).Add(curve.A); + if (X3.IsZero) + { + return new SecT193R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1); + L3 = Y3.Divide(X3).Add(X3); + Z3 = curve.FromBigInteger(BigInteger.One); + } + else + { + B = B.Square(); + + ECFieldElement AU1 = A.Multiply(U1); + ECFieldElement AU2 = A.Multiply(U2); + + X3 = AU1.Multiply(AU2); + if (X3.IsZero) + { + return new SecT193R2Point(curve, X3, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement ABZ2 = A.Multiply(B); + if (!Z2IsOne) + { + ABZ2 = ABZ2.Multiply(Z2); + } + + L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1)); + + Z3 = ABZ2; + if (!Z1IsOne) + { + Z3 = Z3.Multiply(Z1); + } + } + + return new SecT193R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Twice() + { + if (this.IsInfinity) + { + return this; + } + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return curve.Infinity; + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + + bool Z1IsOne = Z1.IsOne; + ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1); + ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square(); + ECFieldElement a = curve.A; + ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq); + ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq); + if (T.IsZero) + { + return new SecT193R2Point(curve, T, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = T.Square(); + ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq); + + ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1); + ECFieldElement L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3); + + return new SecT193R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint TwicePlus(ECPoint b) + { + if (this.IsInfinity) + return b; + if (b.IsInfinity) + return Twice(); + + ECCurve curve = this.Curve; + + ECFieldElement X1 = this.RawXCoord; + if (X1.IsZero) + { + // A point with X == 0 is it's own Additive inverse + return b; + } + + ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0]; + if (X2.IsZero || !Z2.IsOne) + { + return Twice().Add(b); + } + + ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0]; + ECFieldElement L2 = b.RawYCoord; + + ECFieldElement X1Sq = X1.Square(); + ECFieldElement L1Sq = L1.Square(); + ECFieldElement Z1Sq = Z1.Square(); + ECFieldElement L1Z1 = L1.Multiply(Z1); + + ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1); + ECFieldElement L2plus1 = L2.AddOne(); + ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq); + ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq); + ECFieldElement B = X2Z1Sq.Add(T).Square(); + + if (B.IsZero) + { + if (A.IsZero) + return b.Twice(); + + return curve.Infinity; + } + + if (A.IsZero) + { + return new SecT193R2Point(curve, A, curve.B.Sqrt(), IsCompressed); + } + + ECFieldElement X3 = A.Square().Multiply(X2Z1Sq); + ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq); + ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3); + + return new SecT193R2Point(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed); + } + + public override ECPoint Negate() + { + if (this.IsInfinity) + return this; + + ECFieldElement X = this.RawXCoord; + if (X.IsZero) + return this; + + // L is actually Lambda (X + Y/X) here + ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0]; + return new SecT193R2Point(Curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed); + } + } +} diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs index 165fadbf3..a2f73fd5d 100644 --- a/crypto/src/math/ec/custom/sec/SecT233Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs @@ -45,6 +45,39 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat256.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion + + ulong[] t0 = Nat256.Create64(); + ulong[] t1 = Nat256.Create64(); + + Square(x, t0); + Multiply(t0, x, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 3, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 7, t0); + Multiply(t0, t1, t0); + SquareN(t0, 14, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 29, t0); + Multiply(t0, t1, t0); + SquareN(t0, 58, t1); + Multiply(t1, t0, t1); + SquareN(t1, 116, t0); + Multiply(t0, t1, t0); + Square(t0, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -200,7 +233,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 59 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; @@ -215,7 +248,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec int k = 54; do { - j = (uint)(x >> k); + j = (uint)(x >> k); g = u[j & 7] ^ u[(j >> 3) & 7] << 3; l ^= (g << k); diff --git a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs index 60b204604..a9041efde 100644 --- a/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT233FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT233FieldElement( - AbstractF2mCurve.Inverse(233, new int[] { 74 }, ToBigInteger())); + ulong[] z = Nat256.Create64(); + SecT233Field.Invert(x, z); + return new SecT233FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs index 1e0824af9..6b8ad696f 100644 --- a/crypto/src/math/ec/custom/sec/SecT239Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs @@ -45,6 +45,43 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat256.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion + + ulong[] t0 = Nat256.Create64(); + ulong[] t1 = Nat256.Create64(); + + Square(x, t0); + Multiply(t0, x, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 3, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 7, t0); + Multiply(t0, t1, t0); + SquareN(t0, 14, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 29, t0); + Multiply(t0, t1, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 59, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 119, t0); + Multiply(t0, t1, t0); + Square(t0, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat256.CreateExt64(); @@ -204,7 +241,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 60 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; @@ -219,7 +256,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec int k = 54; do { - j = (uint)(x >> k); + j = (uint)(x >> k); g = u[j & 7] ^ u[(j >> 3) & 7] << 3; l ^= (g << k); diff --git a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs index e7bfffd1f..de074c55f 100644 --- a/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT239FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT239FieldElement( - AbstractF2mCurve.Inverse(239, new int[] { 158 }, ToBigInteger())); + ulong[] z = Nat256.Create64(); + SecT239Field.Invert(x, z); + return new SecT239FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs index 9afb27461..903ea02ff 100644 --- a/crypto/src/math/ec/custom/sec/SecT283Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs @@ -48,6 +48,41 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat320.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion + + ulong[] t0 = Nat320.Create64(); + ulong[] t1 = Nat320.Create64(); + + Square(x, t0); + Multiply(t0, x, t0); + SquareN(t0, 2, t1); + Multiply(t1, t0, t1); + SquareN(t1, 4, t0); + Multiply(t0, t1, t0); + SquareN(t0, 8, t1); + Multiply(t1, t0, t1); + Square(t1, t1); + Multiply(t1, x, t1); + SquareN(t1, 17, t0); + Multiply(t0, t1, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 35, t1); + Multiply(t1, t0, t1); + SquareN(t1, 70, t0); + Multiply(t0, t1, t0); + Square(t0, t0); + Multiply(t0, x, t0); + SquareN(t0, 141, t1); + Multiply(t1, t0, t1); + Square(t1, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat320.CreateExt64(); @@ -292,7 +327,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 57 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; @@ -306,7 +341,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec int k = 48; do { - j = (uint)(x >> k); + j = (uint)(x >> k); g = u[j & 7] ^ u[(j >> 3) & 7] << 3 ^ u[(j >> 6) & 7] << 6; diff --git a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs index 9181b8685..e02108f73 100644 --- a/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT283FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT283FieldElement( - AbstractF2mCurve.Inverse(283, new int[] { 5, 7, 12 }, ToBigInteger())); + ulong[] z = Nat320.Create64(); + SecT283Field.Invert(x, z); + return new SecT283FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs index d71f5b5f9..84eada96e 100644 --- a/crypto/src/math/ec/custom/sec/SecT409Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs @@ -47,6 +47,57 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat448.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion with bases { 2, 3 } + + ulong[] t0 = Nat448.Create64(); + ulong[] t1 = Nat448.Create64(); + ulong[] t2 = Nat448.Create64(); + + Square(x, t0); + + // 3 | 408 + SquareN(t0, 1, t1); + Multiply(t0, t1, t0); + SquareN(t1, 1, t1); + Multiply(t0, t1, t0); + + // 2 | 136 + SquareN(t0, 3, t1); + Multiply(t0, t1, t0); + + // 2 | 68 + SquareN(t0, 6, t1); + Multiply(t0, t1, t0); + + // 2 | 34 + SquareN(t0, 12, t1); + Multiply(t0, t1, t2); + + // ! {2,3} | 17 + SquareN(t2, 24, t0); + SquareN(t0, 24, t1); + Multiply(t0, t1, t0); + + // 2 | 8 + SquareN(t0, 48, t1); + Multiply(t0, t1, t0); + + // 2 | 4 + SquareN(t0, 96, t1); + Multiply(t0, t1, t0); + + // 2 | 2 + SquareN(t0, 192, t1); + Multiply(t0, t1, t0); + + Multiply(t0, t2, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat448.CreateExt64(); @@ -196,7 +247,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(y >> 59 == 0); ulong[] u = new ulong[8]; - // u[0] = 0; + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; u[3] = u[2] ^ y; diff --git a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs index b60ceafee..581ea73df 100644 --- a/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT409FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT409FieldElement( - AbstractF2mCurve.Inverse(409, new int[] { 87 }, ToBigInteger())); + ulong[] z = Nat448.Create64(); + SecT409Field.Invert(x, z); + return new SecT409FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs index 0711ee4aa..fc84e336b 100644 --- a/crypto/src/math/ec/custom/sec/SecT571Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs @@ -59,6 +59,57 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec return z; } + public static void Invert(ulong[] x, ulong[] z) + { + if (Nat576.IsZero64(x)) + throw new InvalidOperationException(); + + // Itoh-Tsujii inversion with bases { 2, 3, 5 } + + ulong[] t0 = Nat576.Create64(); + ulong[] t1 = Nat576.Create64(); + ulong[] t2 = Nat576.Create64(); + + Square(x, t2); + + // 5 | 570 + Square(t2, t0); + Square(t0, t1); + Multiply(t0, t1, t0); + SquareN(t0, 2, t1); + Multiply(t0, t1, t0); + Multiply(t0, t2, t0); + + // 3 | 114 + SquareN(t0, 5, t1); + Multiply(t0, t1, t0); + SquareN(t1, 5, t1); + Multiply(t0, t1, t0); + + // 2 | 38 + SquareN(t0, 15, t1); + Multiply(t0, t1, t2); + + // ! {2,3,5} | 19 + SquareN(t2, 30, t0); + SquareN(t0, 30, t1); + Multiply(t0, t1, t0); + + // 3 | 9 + SquareN(t0, 60, t1); + Multiply(t0, t1, t0); + SquareN(t1, 60, t1); + Multiply(t0, t1, t0); + + // 3 | 3 + SquareN(t0, 180, t1); + Multiply(t0, t1, t0); + SquareN(t1, 180, t1); + Multiply(t0, t1, t0); + + Multiply(t0, t2, z); + } + public static void Multiply(ulong[] x, ulong[] y, ulong[] z) { ulong[] tt = Nat576.CreateExt64(); @@ -199,7 +250,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMulwAcc(ulong[] xs, ulong y, ulong[] z, int zOff) { ulong[] u = new ulong[32]; - // u[0] = 0; + //u[0] = 0; u[1] = y; for (int i = 2; i < 32; i += 2) { diff --git a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs index a26e1e336..5d5458412 100644 --- a/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs +++ b/crypto/src/math/ec/custom/sec/SecT571FieldElement.cs @@ -152,8 +152,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public override ECFieldElement Invert() { - return new SecT571FieldElement( - AbstractF2mCurve.Inverse(571, new int[] { 2, 5, 10 }, ToBigInteger())); + ulong[] z = Nat576.Create64(); + SecT571Field.Invert(x, z); + return new SecT571FieldElement(z); } public override ECFieldElement Sqrt() diff --git a/crypto/src/math/raw/Interleave.cs b/crypto/src/math/raw/Interleave.cs index 9755c9d6f..a45ee1e08 100644 --- a/crypto/src/math/raw/Interleave.cs +++ b/crypto/src/math/raw/Interleave.cs @@ -4,67 +4,92 @@ namespace Org.BouncyCastle.Math.Raw { internal abstract class Interleave { + private const ulong M32 = 0x55555555UL; + private const ulong M64 = 0x5555555555555555UL; + /* * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits. * In a binary field, this operation is the same as squaring an 8 bit number. */ - private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[] - { - 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, - 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, - 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, - 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, - 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, - 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, - 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, - 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, - 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, - 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, - 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, - 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, - 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, - 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, - 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, - 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, - 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, - 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, - 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, - 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, - 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, - 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, - 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, - 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, - 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, - 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, - 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, - 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, - 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, - 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, - 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, - 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 - }; + //private static readonly ushort[] INTERLEAVE2_TABLE = new ushort[] + //{ + // 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, + // 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, + // 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, + // 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + // 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, + // 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, + // 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, + // 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + // 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, + // 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, + // 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, + // 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + // 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, + // 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, + // 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, + // 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + // 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, + // 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, + // 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, + // 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + // 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, + // 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, + // 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, + // 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + // 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, + // 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, + // 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, + // 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + // 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, + // 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, + // 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, + // 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 + //}; internal static uint Expand8to16(uint x) { - return INTERLEAVE2_TABLE[x & 0xFF]; + x &= 0xFFU; + x = (x | (x << 4)) & 0x0F0FU; + x = (x | (x << 2)) & 0x3333U; + x = (x | (x << 1)) & 0x5555U; + return x; } internal static uint Expand16to32(uint x) { - return (uint)(INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >> 8) & 0xFF] << 16); + x &= 0xFFFFU; + x = (x | (x << 8)) & 0x00FF00FFU; + x = (x | (x << 4)) & 0x0F0F0F0FU; + x = (x | (x << 2)) & 0x33333333U; + x = (x | (x << 1)) & 0x55555555U; + return x; } internal static ulong Expand32to64(uint x) { - uint r00 = (uint)(INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[(x >> 8) & 0xFF] << 16); - uint r32 = (uint)(INTERLEAVE2_TABLE[(x >> 16) & 0xFF] | INTERLEAVE2_TABLE[x >> 24] << 16); - return (ulong)r32 << 32 | (ulong)r00; + // "shuffle" low half to even bits and high half to odd bits + uint t; + t = (x ^ (x >> 8)) & 0x0000FF00U; x ^= (t ^ (t << 8)); + t = (x ^ (x >> 4)) & 0x00F000F0U; x ^= (t ^ (t << 4)); + t = (x ^ (x >> 2)) & 0x0C0C0C0CU; x ^= (t ^ (t << 2)); + t = (x ^ (x >> 1)) & 0x22222222U; x ^= (t ^ (t << 1)); + + return ((x >> 1) & M32) << 32 | (x & M32); } internal static void Expand64To128(ulong x, ulong[] z, int zOff) { - z[zOff ] = Expand32to64((uint)x); - z[zOff + 1] = Expand32to64((uint)(x >> 32)); + // "shuffle" low half to even bits and high half to odd bits + ulong t; + t = (x ^ (x >> 16)) & 0x00000000FFFF0000UL; x ^= (t ^ (t << 16)); + t = (x ^ (x >> 8)) & 0x0000FF000000FF00UL; x ^= (t ^ (t << 8)); + t = (x ^ (x >> 4)) & 0x00F000F000F000F0UL; x ^= (t ^ (t << 4)); + t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CUL; x ^= (t ^ (t << 2)); + t = (x ^ (x >> 1)) & 0x2222222222222222UL; x ^= (t ^ (t << 1)); + + z[zOff ] = (x ) & M64; + z[zOff + 1] = (x >> 1) & M64; } } } diff --git a/crypto/src/pkix/PkixCertPathChecker.cs b/crypto/src/pkix/PkixCertPathChecker.cs index f22738d89..da7e82b46 100644 --- a/crypto/src/pkix/PkixCertPathChecker.cs +++ b/crypto/src/pkix/PkixCertPathChecker.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections; using Org.BouncyCastle.Utilities.Collections; using Org.BouncyCastle.X509; @@ -82,7 +80,7 @@ namespace Org.BouncyCastle.Pkix * @exception CertPathValidatorException * if the specified certificate does not pass the check */ - public abstract void Check(X509Certificate cert, ICollection unresolvedCritExts); + public abstract void Check(X509Certificate cert, ISet unresolvedCritExts); //throws CertPathValidatorException; /** diff --git a/crypto/test/src/test/CertPathValidatorTest.cs b/crypto/test/src/test/CertPathValidatorTest.cs index a92bb9b31..f83ac850a 100644 --- a/crypto/test/src/test/CertPathValidatorTest.cs +++ b/crypto/test/src/test/CertPathValidatorTest.cs @@ -290,7 +290,7 @@ namespace Org.BouncyCastle.Tests return null; } - public override void Check(X509Certificate cert, ICollection unresolvedCritExts) + public override void Check(X509Certificate cert, ISet unresolvedCritExts) { count++; } |