1package org.bouncycastle.math.ec.custom.sec; 2 3import java.math.BigInteger; 4 5import org.bouncycastle.math.raw.Nat; 6import org.bouncycastle.math.raw.Nat384; 7 8public class SecP384R1Field 9{ 10 private static final long M = 0xFFFFFFFFL; 11 12 // 2^384 - 2^128 - 2^96 + 2^32 - 1 13 static final int[] P = new int[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 14 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 15 static final int[] PExt = new int[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE, 16 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000, 17 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 18 private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001, 19 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF, 20 0x00000001, 0x00000002 }; 21 private static final int P11 = 0xFFFFFFFF; 22 private static final int PExt23 = 0xFFFFFFFF; 23 24 public static void add(int[] x, int[] y, int[] z) 25 { 26 int c = Nat.add(12, x, y, z); 27 if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) 28 { 29 addPInvTo(z); 30 } 31 } 32 33 public static void addExt(int[] xx, int[] yy, int[] zz) 34 { 35 int c = Nat.add(24, xx, yy, zz); 36 if (c != 0 || (zz[23] == PExt23 && Nat.gte(24, zz, PExt))) 37 { 38 if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) 39 { 40 Nat.incAt(24, zz, PExtInv.length); 41 } 42 } 43 } 44 45 public static void addOne(int[] x, int[] z) 46 { 47 int c = Nat.inc(12, x, z); 48 if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) 49 { 50 addPInvTo(z); 51 } 52 } 53 54 public static int[] fromBigInteger(BigInteger x) 55 { 56 int[] z = Nat.fromBigInteger(384, x); 57 if (z[11] == P11 && Nat.gte(12, z, P)) 58 { 59 Nat.subFrom(12, P, z); 60 } 61 return z; 62 } 63 64 public static void half(int[] x, int[] z) 65 { 66 if ((x[0] & 1) == 0) 67 { 68 Nat.shiftDownBit(12, x, 0, z); 69 } 70 else 71 { 72 int c = Nat.add(12, x, P, z); 73 Nat.shiftDownBit(12, z, c); 74 } 75 } 76 77 public static void multiply(int[] x, int[] y, int[] z) 78 { 79 int[] tt = Nat.create(24); 80 Nat384.mul(x, y, tt); 81 reduce(tt, z); 82 } 83 84 public static void negate(int[] x, int[] z) 85 { 86 if (Nat.isZero(12, x)) 87 { 88 Nat.zero(12, z); 89 } 90 else 91 { 92 Nat.sub(12, P, x, z); 93 } 94 } 95 96 public static void reduce(int[] xx, int[] z) 97 { 98 long xx16 = xx[16] & M, xx17 = xx[17] & M, xx18 = xx[18] & M, xx19 = xx[19] & M; 99 long xx20 = xx[20] & M, xx21 = xx[21] & M, xx22 = xx[22] & M, xx23 = xx[23] & M; 100 101 final long n = 1; 102 103 long t0 = (xx[12] & M) + xx20 - n; 104 long t1 = (xx[13] & M) + xx22; 105 long t2 = (xx[14] & M) + xx22 + xx23; 106 long t3 = (xx[15] & M) + xx23; 107 long t4 = xx17 + xx21; 108 long t5 = xx21 - xx23; 109 long t6 = xx22 - xx23; 110 111 long cc = 0; 112 cc += (xx[0] & M) + t0 + t5; 113 z[0] = (int)cc; 114 cc >>= 32; 115 cc += (xx[1] & M) + xx23 - t0 + t1; 116 z[1] = (int)cc; 117 cc >>= 32; 118 cc += (xx[2] & M) - xx21 - t1 + t2; 119 z[2] = (int)cc; 120 cc >>= 32; 121 cc += (xx[3] & M) + t0 - t2 + t3 + t5; 122 z[3] = (int)cc; 123 cc >>= 32; 124 cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5; 125 z[4] = (int)cc; 126 cc >>= 32; 127 cc += (xx[5] & M) - xx16 + t1 + t2 + t4; 128 z[5] = (int)cc; 129 cc >>= 32; 130 cc += (xx[6] & M) + xx18 - xx17 + t2 + t3; 131 z[6] = (int)cc; 132 cc >>= 32; 133 cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3; 134 z[7] = (int)cc; 135 cc >>= 32; 136 cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19; 137 z[8] = (int)cc; 138 cc >>= 32; 139 cc += (xx[9] & M) + xx18 - xx20 + t4; 140 z[9] = (int)cc; 141 cc >>= 32; 142 cc += (xx[10] & M) + xx18 + xx19 - t5 + t6; 143 z[10] = (int)cc; 144 cc >>= 32; 145 cc += (xx[11] & M) + xx19 + xx20 - t6; 146 z[11] = (int)cc; 147 cc >>= 32; 148 cc += n; 149 150// assert cc >= 0; 151 152 reduce32((int)cc, z); 153 } 154 155 public static void reduce32(int x, int[] z) 156 { 157 long cc = 0; 158 159 if (x != 0) 160 { 161 long xx12 = x & M; 162 163 cc += (z[0] & M) + xx12; 164 z[0] = (int)cc; 165 cc >>= 32; 166 cc += (z[1] & M) - xx12; 167 z[1] = (int)cc; 168 cc >>= 32; 169 if (cc != 0) 170 { 171 cc += (z[2] & M); 172 z[2] = (int)cc; 173 cc >>= 32; 174 } 175 cc += (z[3] & M) + xx12; 176 z[3] = (int)cc; 177 cc >>= 32; 178 cc += (z[4] & M) + xx12; 179 z[4] = (int)cc; 180 cc >>= 32; 181 182// assert cc == 0 || cc == 1; 183 } 184 185 if ((cc != 0 && Nat.incAt(12, z, 5) != 0) 186 || (z[11] == P11 && Nat.gte(12, z, P))) 187 { 188 addPInvTo(z); 189 } 190 } 191 192 public static void square(int[] x, int[] z) 193 { 194 int[] tt = Nat.create(24); 195 Nat384.square(x, tt); 196 reduce(tt, z); 197 } 198 199 public static void squareN(int[] x, int n, int[] z) 200 { 201// assert n > 0; 202 203 int[] tt = Nat.create(24); 204 Nat384.square(x, tt); 205 reduce(tt, z); 206 207 while (--n > 0) 208 { 209 Nat384.square(z, tt); 210 reduce(tt, z); 211 } 212 } 213 214 public static void subtract(int[] x, int[] y, int[] z) 215 { 216 int c = Nat.sub(12, x, y, z); 217 if (c != 0) 218 { 219 subPInvFrom(z); 220 } 221 } 222 223 public static void subtractExt(int[] xx, int[] yy, int[] zz) 224 { 225 int c = Nat.sub(24, xx, yy, zz); 226 if (c != 0) 227 { 228 if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) 229 { 230 Nat.decAt(24, zz, PExtInv.length); 231 } 232 } 233 } 234 235 public static void twice(int[] x, int[] z) 236 { 237 int c = Nat.shiftUpBit(12, x, 0, z); 238 if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) 239 { 240 addPInvTo(z); 241 } 242 } 243 244 private static void addPInvTo(int[] z) 245 { 246 long c = (z[0] & M) + 1; 247 z[0] = (int)c; 248 c >>= 32; 249 c += (z[1] & M) - 1; 250 z[1] = (int)c; 251 c >>= 32; 252 if (c != 0) 253 { 254 c += (z[2] & M); 255 z[2] = (int)c; 256 c >>= 32; 257 } 258 c += (z[3] & M) + 1; 259 z[3] = (int)c; 260 c >>= 32; 261 c += (z[4] & M) + 1; 262 z[4] = (int)c; 263 c >>= 32; 264 if (c != 0) 265 { 266 Nat.incAt(12, z, 5); 267 } 268 } 269 270 private static void subPInvFrom(int[] z) 271 { 272 long c = (z[0] & M) - 1; 273 z[0] = (int)c; 274 c >>= 32; 275 c += (z[1] & M) + 1; 276 z[1] = (int)c; 277 c >>= 32; 278 if (c != 0) 279 { 280 c += (z[2] & M); 281 z[2] = (int)c; 282 c >>= 32; 283 } 284 c += (z[3] & M) - 1; 285 z[3] = (int)c; 286 c >>= 32; 287 c += (z[4] & M) - 1; 288 z[4] = (int)c; 289 c >>= 32; 290 if (c != 0) 291 { 292 Nat.decAt(12, z, 5); 293 } 294 } 295} 296