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