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 SecP224R1Field 9{ 10 private static final long M = 0xFFFFFFFFL; 11 12 // 2^224 - 2^96 + 1 13 static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 14 static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 15 0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 16 private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000, 17 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 }; 18 private static final int P6 = 0xFFFFFFFF; 19 private static final int PExt13 = 0xFFFFFFFF; 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 addPInvTo(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 addPInvTo(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 Nat224.subFrom(P, 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 xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M; 108 109 final long n = 1; 110 111 long t0 = (xx[7] & M) + xx11 - n; 112 long t1 = (xx[8] & M) + xx12; 113 long t2 = (xx[9] & M) + xx13; 114 115 long cc = 0; 116 cc += (xx[0] & M) - t0; 117 long z0 = cc & M; 118 cc >>= 32; 119 cc += (xx[1] & M) - t1; 120 z[1] = (int)cc; 121 cc >>= 32; 122 cc += (xx[2] & M) - t2; 123 z[2] = (int)cc; 124 cc >>= 32; 125 cc += (xx[3] & M) + t0 - xx10; 126 long z3 = cc & M; 127 cc >>= 32; 128 cc += (xx[4] & M) + t1 - xx11; 129 z[4] = (int)cc; 130 cc >>= 32; 131 cc += (xx[5] & M) + t2 - xx12; 132 z[5] = (int)cc; 133 cc >>= 32; 134 cc += (xx[6] & M) + xx10 - xx13; 135 z[6] = (int)cc; 136 cc >>= 32; 137 cc += n; 138 139// assert cc >= 0; 140 141 z3 += cc; 142 143 z0 -= cc; 144 z[0] = (int)z0; 145 cc = z0 >> 32; 146 if (cc != 0) 147 { 148 cc += (z[1] & M); 149 z[1] = (int)cc; 150 cc >>= 32; 151 cc += (z[2] & M); 152 z[2] = (int)cc; 153 z3 += cc >> 32; 154 } 155 z[3] = (int)z3; 156 cc = z3 >> 32; 157 158// assert cc == 0 || cc == 1; 159 160 if ((cc != 0 && Nat.incAt(7, z, 4) != 0) 161 || (z[6] == P6 && Nat224.gte(z, P))) 162 { 163 addPInvTo(z); 164 } 165 } 166 167 public static void reduce32(int x, int[] z) 168 { 169 long cc = 0; 170 171 if (x != 0) 172 { 173 long xx07 = x & M; 174 175 cc += (z[0] & M) - xx07; 176 z[0] = (int)cc; 177 cc >>= 32; 178 if (cc != 0) 179 { 180 cc += (z[1] & M); 181 z[1] = (int)cc; 182 cc >>= 32; 183 cc += (z[2] & M); 184 z[2] = (int)cc; 185 cc >>= 32; 186 } 187 cc += (z[3] & M) + xx07; 188 z[3] = (int)cc; 189 cc >>= 32; 190 191// assert cc == 0 || cc == 1; 192 } 193 194 if ((cc != 0 && Nat.incAt(7, z, 4) != 0) 195 || (z[6] == P6 && Nat224.gte(z, P))) 196 { 197 addPInvTo(z); 198 } 199 } 200 201 public static void square(int[] x, int[] z) 202 { 203 int[] tt = Nat224.createExt(); 204 Nat224.square(x, tt); 205 reduce(tt, z); 206 } 207 208 public static void squareN(int[] x, int n, int[] z) 209 { 210// assert n > 0; 211 212 int[] tt = Nat224.createExt(); 213 Nat224.square(x, tt); 214 reduce(tt, z); 215 216 while (--n > 0) 217 { 218 Nat224.square(z, tt); 219 reduce(tt, z); 220 } 221 } 222 223 public static void subtract(int[] x, int[] y, int[] z) 224 { 225 int c = Nat224.sub(x, y, z); 226 if (c != 0) 227 { 228 subPInvFrom(z); 229 } 230 } 231 232 public static void subtractExt(int[] xx, int[] yy, int[] zz) 233 { 234 int c = Nat.sub(14, xx, yy, zz); 235 if (c != 0) 236 { 237 if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) 238 { 239 Nat.decAt(14, zz, PExtInv.length); 240 } 241 } 242 } 243 244 public static void twice(int[] x, int[] z) 245 { 246 int c = Nat.shiftUpBit(7, x, 0, z); 247 if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) 248 { 249 addPInvTo(z); 250 } 251 } 252 253 private static void addPInvTo(int[] z) 254 { 255 long c = (z[0] & M) - 1; 256 z[0] = (int)c; 257 c >>= 32; 258 if (c != 0) 259 { 260 c += (z[1] & M); 261 z[1] = (int)c; 262 c >>= 32; 263 c += (z[2] & M); 264 z[2] = (int)c; 265 c >>= 32; 266 } 267 c += (z[3] & M) + 1; 268 z[3] = (int)c; 269 c >>= 32; 270 if (c != 0) 271 { 272 Nat.incAt(7, z, 4); 273 } 274 } 275 276 private static void subPInvFrom(int[] z) 277 { 278 long c = (z[0] & M) + 1; 279 z[0] = (int)c; 280 c >>= 32; 281 if (c != 0) 282 { 283 c += (z[1] & M); 284 z[1] = (int)c; 285 c >>= 32; 286 c += (z[2] & M); 287 z[2] = (int)c; 288 c >>= 32; 289 } 290 c += (z[3] & M) - 1; 291 z[3] = (int)c; 292 c >>= 32; 293 if (c != 0) 294 { 295 Nat.decAt(7, z, 4); 296 } 297 } 298} 299