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