1 package org.bouncycastle.math.ec.custom.sec; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.math.raw.Nat; 6 import org.bouncycastle.math.raw.Nat384; 7 8 public 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 add(int[] x, int[] y, int[] z)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 addExt(int[] xx, int[] yy, int[] zz)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 addOne(int[] x, int[] z)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 fromBigInteger(BigInteger x)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 half(int[] x, int[] z)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 multiply(int[] x, int[] y, int[] z)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 negate(int[] x, int[] z)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 reduce(int[] xx, int[] z)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 long t7 = t0 + t5; 111 112 long cc = 0; 113 cc += (xx[0] & M) + t7; 114 z[0] = (int)cc; 115 cc >>= 32; 116 cc += (xx[1] & M) + xx23 - t0 + t1; 117 z[1] = (int)cc; 118 cc >>= 32; 119 cc += (xx[2] & M) - xx21 - t1 + t2; 120 z[2] = (int)cc; 121 cc >>= 32; 122 cc += (xx[3] & M) - t2 + t3 + t7; 123 z[3] = (int)cc; 124 cc >>= 32; 125 cc += (xx[4] & M) + xx16 + xx21 + t1 - t3 + t7; 126 z[4] = (int)cc; 127 cc >>= 32; 128 cc += (xx[5] & M) - xx16 + t1 + t2 + t4; 129 z[5] = (int)cc; 130 cc >>= 32; 131 cc += (xx[6] & M) + xx18 - xx17 + t2 + t3; 132 z[6] = (int)cc; 133 cc >>= 32; 134 cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3; 135 z[7] = (int)cc; 136 cc >>= 32; 137 cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19; 138 z[8] = (int)cc; 139 cc >>= 32; 140 cc += (xx[9] & M) + xx18 - xx20 + t4; 141 z[9] = (int)cc; 142 cc >>= 32; 143 cc += (xx[10] & M) + xx18 + xx19 - t5 + t6; 144 z[10] = (int)cc; 145 cc >>= 32; 146 cc += (xx[11] & M) + xx19 + xx20 - t6; 147 z[11] = (int)cc; 148 cc >>= 32; 149 cc += n; 150 151 // assert cc >= 0; 152 153 reduce32((int)cc, z); 154 } 155 reduce32(int x, int[] z)156 public static void reduce32(int x, int[] z) 157 { 158 long cc = 0; 159 160 if (x != 0) 161 { 162 long xx12 = x & M; 163 164 cc += (z[0] & M) + xx12; 165 z[0] = (int)cc; 166 cc >>= 32; 167 cc += (z[1] & M) - xx12; 168 z[1] = (int)cc; 169 cc >>= 32; 170 if (cc != 0) 171 { 172 cc += (z[2] & M); 173 z[2] = (int)cc; 174 cc >>= 32; 175 } 176 cc += (z[3] & M) + xx12; 177 z[3] = (int)cc; 178 cc >>= 32; 179 cc += (z[4] & M) + xx12; 180 z[4] = (int)cc; 181 cc >>= 32; 182 183 // assert cc == 0 || cc == 1; 184 } 185 186 if ((cc != 0 && Nat.incAt(12, z, 5) != 0) 187 || (z[11] == P11 && Nat.gte(12, z, P))) 188 { 189 addPInvTo(z); 190 } 191 } 192 square(int[] x, int[] z)193 public static void square(int[] x, int[] z) 194 { 195 int[] tt = Nat.create(24); 196 Nat384.square(x, tt); 197 reduce(tt, z); 198 } 199 squareN(int[] x, int n, int[] z)200 public static void squareN(int[] x, int n, int[] z) 201 { 202 // assert n > 0; 203 204 int[] tt = Nat.create(24); 205 Nat384.square(x, tt); 206 reduce(tt, z); 207 208 while (--n > 0) 209 { 210 Nat384.square(z, tt); 211 reduce(tt, z); 212 } 213 } 214 subtract(int[] x, int[] y, int[] z)215 public static void subtract(int[] x, int[] y, int[] z) 216 { 217 int c = Nat.sub(12, x, y, z); 218 if (c != 0) 219 { 220 subPInvFrom(z); 221 } 222 } 223 subtractExt(int[] xx, int[] yy, int[] zz)224 public static void subtractExt(int[] xx, int[] yy, int[] zz) 225 { 226 int c = Nat.sub(24, xx, yy, zz); 227 if (c != 0) 228 { 229 if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) 230 { 231 Nat.decAt(24, zz, PExtInv.length); 232 } 233 } 234 } 235 twice(int[] x, int[] z)236 public static void twice(int[] x, int[] z) 237 { 238 int c = Nat.shiftUpBit(12, x, 0, z); 239 if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) 240 { 241 addPInvTo(z); 242 } 243 } 244 addPInvTo(int[] z)245 private static void addPInvTo(int[] z) 246 { 247 long c = (z[0] & M) + 1; 248 z[0] = (int)c; 249 c >>= 32; 250 c += (z[1] & M) - 1; 251 z[1] = (int)c; 252 c >>= 32; 253 if (c != 0) 254 { 255 c += (z[2] & M); 256 z[2] = (int)c; 257 c >>= 32; 258 } 259 c += (z[3] & M) + 1; 260 z[3] = (int)c; 261 c >>= 32; 262 c += (z[4] & M) + 1; 263 z[4] = (int)c; 264 c >>= 32; 265 if (c != 0) 266 { 267 Nat.incAt(12, z, 5); 268 } 269 } 270 subPInvFrom(int[] z)271 private static void subPInvFrom(int[] z) 272 { 273 long c = (z[0] & M) - 1; 274 z[0] = (int)c; 275 c >>= 32; 276 c += (z[1] & M) + 1; 277 z[1] = (int)c; 278 c >>= 32; 279 if (c != 0) 280 { 281 c += (z[2] & M); 282 z[2] = (int)c; 283 c >>= 32; 284 } 285 c += (z[3] & M) - 1; 286 z[3] = (int)c; 287 c >>= 32; 288 c += (z[4] & M) - 1; 289 z[4] = (int)c; 290 c >>= 32; 291 if (c != 0) 292 { 293 Nat.decAt(12, z, 5); 294 } 295 } 296 } 297