1d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootpackage org.bouncycastle.math.ec.custom.sec;
2d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
3d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport java.math.BigInteger;
4d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
5d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.ec.ECFieldElement;
6d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.raw.Mod;
7d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.raw.Nat;
8d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.math.raw.Nat224;
9d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootimport org.bouncycastle.util.Arrays;
10d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
11d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Rootpublic class SecP224R1FieldElement extends ECFieldElement
12d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root{
13d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public static final BigInteger Q = SecP224R1Curve.q;
14d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
15d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    protected int[] x;
16d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
17d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public SecP224R1FieldElement(BigInteger x)
18d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
19d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0)
20d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
21d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            throw new IllegalArgumentException("x value invalid for SecP224R1FieldElement");
22d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
23d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
24d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        this.x = SecP224R1Field.fromBigInteger(x);
25d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
26d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
27d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public SecP224R1FieldElement()
28d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
29d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        this.x = Nat224.create();
30d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
31d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
32d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    protected SecP224R1FieldElement(int[] x)
33d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
34d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        this.x = x;
35d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
36d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
37d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public boolean isZero()
38d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
39d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.isZero(x);
40d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
41d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
42d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public boolean isOne()
43d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
44d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.isOne(x);
45d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
46d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
47d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public boolean testBitZero()
48d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
49d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.getBit(x, 0) == 1;
50d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
51d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
52d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public BigInteger toBigInteger()
53d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
54d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.toBigInteger(x);
55d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
56d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
57d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public String getFieldName()
58d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
59d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return "SecP224R1Field";
60d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
61d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
62d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public int getFieldSize()
63d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
64d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Q.bitLength();
65d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
66d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
67d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement add(ECFieldElement b)
68d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
69d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
70d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.add(x, ((SecP224R1FieldElement)b).x, z);
71d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
72d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
73d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
74d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement addOne()
75d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
76d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
77d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.addOne(x, z);
78d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
79d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
80d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
81d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement subtract(ECFieldElement b)
82d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
83d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
84d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.subtract(x, ((SecP224R1FieldElement)b).x, z);
85d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
86d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
87d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
88d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement multiply(ECFieldElement b)
89d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
90d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
91d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(x, ((SecP224R1FieldElement)b).x, z);
92d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
93d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
94d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
95d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement divide(ECFieldElement b)
96d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
97d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root//        return multiply(b.invert());
98d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
99d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Mod.invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z);
100d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(z, x, z);
101d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
102d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
103d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
104d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement negate()
105d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
106d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
107d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.negate(x, z);
108d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
109d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
110d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
111d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement square()
112d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
113d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
114d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.square(x, z);
115d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
116d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
117d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
118d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement invert()
119d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
120d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root//        return new SecP224R1FieldElement(toBigInteger().modInverse(Q));
121d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] z = Nat224.create();
122d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Mod.invert(SecP224R1Field.P, x, z);
123d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return new SecP224R1FieldElement(z);
124d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
125d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
126d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    /**
127d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * return a sqrt root - the routine verifies that the calculation returns the right value - if
128d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     * none exists it returns null.
129d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root     */
130d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public ECFieldElement sqrt()
131d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
132d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] c = this.x;
133d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (Nat224.isZero(c) || Nat224.isOne(c))
134d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
135d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return this;
136d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
137d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
138d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] nc = Nat224.create();
139d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.negate(c, nc);
140d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
141d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] r = Mod.random(SecP224R1Field.P);
142d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] t = Nat224.create();
143d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
144d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (!isSquare(c))
145d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
146d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return null;
147d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
148d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
149d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        while (!trySqrt(nc, r, t))
150d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
151d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            SecP224R1Field.addOne(r, r);
152d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
153d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
154d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.square(t, r);
155d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
156d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null;
157d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
158d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
159d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public boolean equals(Object other)
160d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
161d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (other == this)
162d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
163d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return true;
164d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
165d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
166d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (!(other instanceof SecP224R1FieldElement))
167d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
168d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            return false;
169d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
170d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
171d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1FieldElement o = (SecP224R1FieldElement)other;
172d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.eq(x, o.x);
173d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
174d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
175d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    public int hashCode()
176d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
177d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Q.hashCode() ^ Arrays.hashCode(x, 0, 7);
178d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
179d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
180d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static boolean isSquare(int[] x)
181d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
182d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] t1 = Nat224.create();
183d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] t2 = Nat224.create();
184d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Nat224.copy(x, t1);
185d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
186d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        for (int i = 0; i < 7; ++i)
187d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
188d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Nat224.copy(t1, t2);
189d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            SecP224R1Field.squareN(t1, 1 << i, t1);
190d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            SecP224R1Field.multiply(t1, t2, t1);
191d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
192d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
193d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.squareN(t1, 95, t1);
194d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return Nat224.isOne(t1);
195d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
196d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
197d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static void RM(int[] nc, int[] d0, int[] e0, int[] d1, int[] e1, int[] f1, int[] t)
198d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
199d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(e1, e0, t);
200d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(t, nc, t);
201d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(d1, d0, f1);
202d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.add(f1, t, f1);
203d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(d1, e0, t);
204d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Nat224.copy(f1, d1);
205d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(e1, d0, e1);
206d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.add(e1, t, e1);
207d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.square(e1, f1);
208d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(f1, nc, f1);
209d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
210d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
211d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t)
212d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
213d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Nat224.copy(nc, f1);
214d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
215d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] d0 = Nat224.create();
216d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] e0 = Nat224.create();
217d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
218d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        for (int i = 0; i < 7; ++i)
219d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
220d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Nat224.copy(d1, d0);
221d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Nat224.copy(e1, e0);
222d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
223d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            int j = 1 << i;
224d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            while (--j >= 0)
225d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
226d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                RS(d1, e1, f1, t);
227d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
228d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
229d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            RM(nc, d0, e0, d1, e1, f1, t);
230d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
231d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
232d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
233d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static void RS(int[] d, int[] e, int[] f, int[] t)
234d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
235d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(e, d, e);
236d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.twice(e, e);
237d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.square(d, t);
238d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.add(f, t, d);
239d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.multiply(f, t, f);
240d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int c = Nat.shiftUpBits(7, f, 2, 0);
241d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        SecP224R1Field.reduce32(c, f);
242d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
243d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
244d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    private static boolean trySqrt(int[] nc, int[] r, int[] t)
245d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    {
246d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] d1 = Nat224.create();
247d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        Nat224.copy(r, d1);
248d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] e1 = Nat224.create();
249d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        e1[0] = 1;
250d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] f1 = Nat224.create();
251d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        RP(nc, d1, e1, f1, t);
252d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
253d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] d0 = Nat224.create();
254d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        int[] e0 = Nat224.create();
255d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
256d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        for (int k = 1; k < 96; ++k)
257d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        {
258d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Nat224.copy(d1, d0);
259d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            Nat224.copy(e1, e0);
260d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
261d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            RS(d1, e1, f1, t);
262d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
263d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            if (Nat224.isZero(d1))
264d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            {
265d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                Mod.invert(SecP224R1Field.P, e0, t);
266d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                SecP224R1Field.multiply(t, d0, t);
267d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root                return true;
268d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root            }
269d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        }
270d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root
271d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        return false;
272d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root    }
273d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root}
274