summary refs log tree commit diff
path: root/crypto/src/math/ec/custom/sec/SecP384R1Field.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/math/ec/custom/sec/SecP384R1Field.cs')
-rw-r--r--crypto/src/math/ec/custom/sec/SecP384R1Field.cs105
1 files changed, 101 insertions, 4 deletions
diff --git a/crypto/src/math/ec/custom/sec/SecP384R1Field.cs b/crypto/src/math/ec/custom/sec/SecP384R1Field.cs
index 0780df3f0..f15678497 100644
--- a/crypto/src/math/ec/custom/sec/SecP384R1Field.cs
+++ b/crypto/src/math/ec/custom/sec/SecP384R1Field.cs
@@ -1,16 +1,18 @@
 using System;
 using System.Diagnostics;
 
+using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Math.Raw;
+using Org.BouncyCastle.Security;
 
 namespace Org.BouncyCastle.Math.EC.Custom.Sec
 {
     internal class SecP384R1Field
     {
             // 2^384 - 2^128 - 2^96 + 2^32 - 1
-        internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+        private static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
             0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
-        internal static readonly uint[] PExt = new uint[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
+        private static readonly uint[] PExt = new uint[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
             0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000,
             0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
         private static readonly uint[] PExtInv = new uint[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001,
@@ -72,6 +74,81 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static void Inv(uint[] x, uint[] z)
+        {
+            /*
+             * Raise this element to the exponent 2^384 - 2^128 - 2^96 + 2^32 - 3
+             *
+             * Breaking up the exponent's binary representation into "repunits", we get:
+             * { 255 1s } { 1 0s } { 32 1s } { 64 0s } { 30 1s } { 1 0s} { 1 1s}
+             *
+             * Therefore we need an addition chain containing 1, 30, 32, 255 (the lengths of the repunits)
+             * We use: [1], 2, 3, 6, 12, 24, [30], [32], 62, 124, 248, 254, [255]
+             */
+
+            if (0 != IsZero(x))
+                throw new ArgumentException("cannot be 0", "x");
+
+            uint[] x1 = x;
+            uint[] x2 = Nat.Create(12);
+            Square(x1, x2);
+            Multiply(x2, x1, x2);
+            uint[] x3 = Nat.Create(12);
+            Square(x2, x3);
+            Multiply(x3, x1, x3);
+            uint[] x6 = Nat.Create(12);
+            SquareN(x3, 3, x6);
+            Multiply(x6, x3, x6);
+            uint[] x12 = x3;
+            SquareN(x6, 6, x12);
+            Multiply(x12, x6, x12);
+            uint[] x24 = Nat.Create(12);
+            SquareN(x12, 12, x24);
+            Multiply(x24, x12, x24);
+            uint[] x30 = x12;
+            SquareN(x24, 6, x30);
+            Multiply(x30, x6, x30);
+            uint[] x32 = x24;
+            SquareN(x30, 2, x32);
+            Multiply(x32, x2, x32);
+            uint[] x62 = x2;
+            SquareN(x32, 30, x62);
+            Multiply(x62, x30, x62);
+            uint[] x124 = Nat.Create(12);
+            SquareN(x62, 62, x124);
+            Multiply(x124, x62, x124);
+            uint[] x248 = x62;
+            SquareN(x124, 124, x248);
+            Multiply(x248, x124, x248);
+            uint[] x254 = x124;
+            SquareN(x248, 6, x254);
+            Multiply(x254, x6, x254);
+            uint[] x255 = x6;
+            Square(x254, x255);
+            Multiply(x255, x1, x255);
+
+            uint[] t = x255;
+            SquareN(t, 33, t);
+            Multiply(t, x32, t);
+            SquareN(t, 94, t);
+            Multiply(t, x30, t);
+            SquareN(t, 2, t);
+
+            // NOTE that x1 and z could be the same array
+            Multiply(x1, t, z);
+        }
+
+        public static int IsZero(uint[] x)
+        {
+            uint d = 0;
+            for (int i = 0; i < 12; ++i)
+            {
+                d |= x[i];
+            }
+            d = (d >> 1) | (d & 1);
+            return ((int)d - 1) >> 31;
+        }
+
         public static void Multiply(uint[] x, uint[] y, uint[] z)
         {
             uint[] tt = Nat.Create(24);
@@ -81,9 +158,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
 
         public static void Negate(uint[] x, uint[] z)
         {
-            if (Nat.IsZero(12, x))
+            if (0 != IsZero(x))
             {
-                Nat.Zero(12, z);
+                Nat.Sub(12, P, P, z);
             }
             else
             {
@@ -91,6 +168,26 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
             }
         }
 
+        public static void Random(SecureRandom r, uint[] z)
+        {
+            byte[] bb = new byte[12 * 4];
+            do
+            {
+                r.NextBytes(bb);
+                Pack.LE_To_UInt32(bb, 0, z, 0, 12);
+            }
+            while (0 == Nat.LessThan(12, z, P));
+        }
+
+        public static void RandomMult(SecureRandom r, uint[] z)
+        {
+            do
+            {
+                Random(r, z);
+            }
+            while (0 != IsZero(z));
+        }
+
         public static void Reduce(uint[] xx, uint[] z)
         {
             long xx16 = xx[16], xx17 = xx[17], xx18 = xx[18], xx19 = xx[19];