1package org.bouncycastle.math.ec.custom.sec;
2
3import java.math.BigInteger;
4
5import org.bouncycastle.math.raw.Nat;
6import org.bouncycastle.math.raw.Nat192;
7
8public class SecP192K1Field
9{
10    // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
11    static final int[] P = new int[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
12    static final int[] PExt = new int[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000,
13        0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
14    private static final int[] PExtInv = new int[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
15        0xFFFFFFFF, 0x00002391, 0x00000002 };
16    private static final int P5 = 0xFFFFFFFF;
17    private static final int PExt11 = 0xFFFFFFFF;
18    private static final int PInv33 = 0x11C9;
19
20    public static void add(int[] x, int[] y, int[] z)
21    {
22        int c = Nat192.add(x, y, z);
23        if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
24        {
25            Nat.add33To(6, PInv33, z);
26        }
27    }
28
29    public static void addExt(int[] xx, int[] yy, int[] zz)
30    {
31        int c = Nat.add(12, xx, yy, zz);
32        if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
33        {
34            if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
35            {
36                Nat.incAt(12, zz, PExtInv.length);
37            }
38        }
39    }
40
41    public static void addOne(int[] x, int[] z)
42    {
43        int c = Nat.inc(6, x, z);
44        if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
45        {
46            Nat.add33To(6, PInv33, z);
47        }
48    }
49
50    public static int[] fromBigInteger(BigInteger x)
51    {
52        int[] z = Nat192.fromBigInteger(x);
53        if (z[5] == P5 && Nat192.gte(z, P))
54        {
55            Nat192.subFrom(P, z);
56        }
57        return z;
58    }
59
60    public static void half(int[] x, int[] z)
61    {
62        if ((x[0] & 1) == 0)
63        {
64            Nat.shiftDownBit(6, x, 0, z);
65        }
66        else
67        {
68            int c = Nat192.add(x, P, z);
69            Nat.shiftDownBit(6, z, c);
70        }
71    }
72
73    public static void multiply(int[] x, int[] y, int[] z)
74    {
75        int[] tt = Nat192.createExt();
76        Nat192.mul(x, y, tt);
77        reduce(tt, z);
78    }
79
80    public static void multiplyAddToExt(int[] x, int[] y, int[] zz)
81    {
82        int c = Nat192.mulAddTo(x, y, zz);
83        if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt)))
84        {
85            if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0)
86            {
87                Nat.incAt(12, zz, PExtInv.length);
88            }
89        }
90    }
91
92    public static void negate(int[] x, int[] z)
93    {
94        if (Nat192.isZero(x))
95        {
96            Nat192.zero(z);
97        }
98        else
99        {
100            Nat192.sub(P, x, z);
101        }
102    }
103
104    public static void reduce(int[] xx, int[] z)
105    {
106        long cc = Nat192.mul33Add(PInv33, xx, 6, xx, 0, z, 0);
107        int c = Nat192.mul33DWordAdd(PInv33, cc, z, 0);
108
109        // assert c == 0L || c == 1L;
110
111        if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
112        {
113            Nat.add33To(6, PInv33, z);
114        }
115    }
116
117    public static void reduce32(int x, int[] z)
118    {
119        if ((x != 0 && Nat192.mul33WordAdd(PInv33, x, z, 0) != 0)
120            || (z[5] == P5 && Nat192.gte(z, P)))
121        {
122            Nat.add33To(6, PInv33, z);
123        }
124    }
125
126    public static void square(int[] x, int[] z)
127    {
128        int[] tt = Nat192.createExt();
129        Nat192.square(x, tt);
130        reduce(tt, z);
131    }
132
133    public static void squareN(int[] x, int n, int[] z)
134    {
135//        assert n > 0;
136
137        int[] tt = Nat192.createExt();
138        Nat192.square(x, tt);
139        reduce(tt, z);
140
141        while (--n > 0)
142        {
143            Nat192.square(z, tt);
144            reduce(tt, z);
145        }
146    }
147
148    public static void subtract(int[] x, int[] y, int[] z)
149    {
150        int c = Nat192.sub(x, y, z);
151        if (c != 0)
152        {
153            Nat.sub33From(6, PInv33, z);
154        }
155    }
156
157    public static void subtractExt(int[] xx, int[] yy, int[] zz)
158    {
159        int c = Nat.sub(12, xx, yy, zz);
160        if (c != 0)
161        {
162            if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0)
163            {
164                Nat.decAt(12, zz, PExtInv.length);
165            }
166        }
167    }
168
169    public static void twice(int[] x, int[] z)
170    {
171        int c = Nat.shiftUpBit(6, x, 0, z);
172        if (c != 0 || (z[5] == P5 && Nat192.gte(z, P)))
173        {
174            Nat.add33To(6, PInv33, z);
175        }
176    }
177}
178