1package org.bouncycastle.math.ec.custom.sec; 2 3import org.bouncycastle.math.ec.ECCurve; 4import org.bouncycastle.math.ec.ECFieldElement; 5import org.bouncycastle.math.ec.ECPoint; 6import org.bouncycastle.math.raw.Nat; 7import org.bouncycastle.math.raw.Nat384; 8 9public class SecP384R1Point extends ECPoint.AbstractFp 10{ 11 /** 12 * Create a point which encodes with point compression. 13 * 14 * @param curve 15 * the curve to use 16 * @param x 17 * affine x co-ordinate 18 * @param y 19 * affine y co-ordinate 20 * 21 * @deprecated Use ECCurve.createPoint to construct points 22 */ 23 public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y) 24 { 25 this(curve, x, y, false); 26 } 27 28 /** 29 * Create a point that encodes with or without point compresion. 30 * 31 * @param curve 32 * the curve to use 33 * @param x 34 * affine x co-ordinate 35 * @param y 36 * affine y co-ordinate 37 * @param withCompression 38 * if true encode with point compression 39 * 40 * @deprecated per-point compression property will be removed, refer 41 * {@link #getEncoded(boolean)} 42 */ 43 public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) 44 { 45 super(curve, x, y); 46 47 if ((x == null) != (y == null)) 48 { 49 throw new IllegalArgumentException("Exactly one of the field elements is null"); 50 } 51 52 this.withCompression = withCompression; 53 } 54 55 SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) 56 { 57 super(curve, x, y, zs); 58 59 this.withCompression = withCompression; 60 } 61 62 protected ECPoint detach() 63 { 64 return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord()); 65 } 66 67 public ECPoint add(ECPoint b) 68 { 69 if (this.isInfinity()) 70 { 71 return b; 72 } 73 if (b.isInfinity()) 74 { 75 return this; 76 } 77 if (this == b) 78 { 79 return twice(); 80 } 81 82 ECCurve curve = this.getCurve(); 83 84 SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Y1 = (SecP384R1FieldElement)this.y; 85 SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.getXCoord(), Y2 = (SecP384R1FieldElement)b.getYCoord(); 86 87 SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.zs[0]; 88 SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.getZCoord(0); 89 90 int c; 91 int[] tt1 = Nat.create(24); 92 int[] tt2 = Nat.create(24); 93 int[] t3 = Nat.create(12); 94 int[] t4 = Nat.create(12); 95 96 boolean Z1IsOne = Z1.isOne(); 97 int[] U2, S2; 98 if (Z1IsOne) 99 { 100 U2 = X2.x; 101 S2 = Y2.x; 102 } 103 else 104 { 105 S2 = t3; 106 SecP384R1Field.square(Z1.x, S2); 107 108 U2 = tt2; 109 SecP384R1Field.multiply(S2, X2.x, U2); 110 111 SecP384R1Field.multiply(S2, Z1.x, S2); 112 SecP384R1Field.multiply(S2, Y2.x, S2); 113 } 114 115 boolean Z2IsOne = Z2.isOne(); 116 int[] U1, S1; 117 if (Z2IsOne) 118 { 119 U1 = X1.x; 120 S1 = Y1.x; 121 } 122 else 123 { 124 S1 = t4; 125 SecP384R1Field.square(Z2.x, S1); 126 127 U1 = tt1; 128 SecP384R1Field.multiply(S1, X1.x, U1); 129 130 SecP384R1Field.multiply(S1, Z2.x, S1); 131 SecP384R1Field.multiply(S1, Y1.x, S1); 132 } 133 134 int[] H = Nat.create(12); 135 SecP384R1Field.subtract(U1, U2, H); 136 137 int[] R = Nat.create(12); 138 SecP384R1Field.subtract(S1, S2, R); 139 140 // Check if b == this or b == -this 141 if (Nat.isZero(12, H)) 142 { 143 if (Nat.isZero(12, R)) 144 { 145 // this == b, i.e. this must be doubled 146 return this.twice(); 147 } 148 149 // this == -b, i.e. the result is the point at infinity 150 return curve.getInfinity(); 151 } 152 153 int[] HSquared = t3; 154 SecP384R1Field.square(H, HSquared); 155 156 int[] G = Nat.create(12); 157 SecP384R1Field.multiply(HSquared, H, G); 158 159 int[] V = t3; 160 SecP384R1Field.multiply(HSquared, U1, V); 161 162 SecP384R1Field.negate(G, G); 163 Nat384.mul(S1, G, tt1); 164 165 c = Nat.addBothTo(12, V, V, G); 166 SecP384R1Field.reduce32(c, G); 167 168 SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4); 169 SecP384R1Field.square(R, X3.x); 170 SecP384R1Field.subtract(X3.x, G, X3.x); 171 172 SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G); 173 SecP384R1Field.subtract(V, X3.x, Y3.x); 174 Nat384.mul(Y3.x, R, tt2); 175 SecP384R1Field.addExt(tt1, tt2, tt1); 176 SecP384R1Field.reduce(tt1, Y3.x); 177 178 SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H); 179 if (!Z1IsOne) 180 { 181 SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x); 182 } 183 if (!Z2IsOne) 184 { 185 SecP384R1Field.multiply(Z3.x, Z2.x, Z3.x); 186 } 187 188 ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; 189 190 return new SecP384R1Point(curve, X3, Y3, zs, this.withCompression); 191 } 192 193 public ECPoint twice() 194 { 195 if (this.isInfinity()) 196 { 197 return this; 198 } 199 200 ECCurve curve = this.getCurve(); 201 202 SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.y; 203 if (Y1.isZero()) 204 { 205 return curve.getInfinity(); 206 } 207 208 SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Z1 = (SecP384R1FieldElement)this.zs[0]; 209 210 int c; 211 int[] t1 = Nat.create(12); 212 int[] t2 = Nat.create(12); 213 214 int[] Y1Squared = Nat.create(12); 215 SecP384R1Field.square(Y1.x, Y1Squared); 216 217 int[] T = Nat.create(12); 218 SecP384R1Field.square(Y1Squared, T); 219 220 boolean Z1IsOne = Z1.isOne(); 221 222 int[] Z1Squared = Z1.x; 223 if (!Z1IsOne) 224 { 225 Z1Squared = t2; 226 SecP384R1Field.square(Z1.x, Z1Squared); 227 } 228 229 SecP384R1Field.subtract(X1.x, Z1Squared, t1); 230 231 int[] M = t2; 232 SecP384R1Field.add(X1.x, Z1Squared, M); 233 SecP384R1Field.multiply(M, t1, M); 234 c = Nat.addBothTo(12, M, M, M); 235 SecP384R1Field.reduce32(c, M); 236 237 int[] S = Y1Squared; 238 SecP384R1Field.multiply(Y1Squared, X1.x, S); 239 c = Nat.shiftUpBits(12, S, 2, 0); 240 SecP384R1Field.reduce32(c, S); 241 242 c = Nat.shiftUpBits(12, T, 3, 0, t1); 243 SecP384R1Field.reduce32(c, t1); 244 245 SecP384R1FieldElement X3 = new SecP384R1FieldElement(T); 246 SecP384R1Field.square(M, X3.x); 247 SecP384R1Field.subtract(X3.x, S, X3.x); 248 SecP384R1Field.subtract(X3.x, S, X3.x); 249 250 SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S); 251 SecP384R1Field.subtract(S, X3.x, Y3.x); 252 SecP384R1Field.multiply(Y3.x, M, Y3.x); 253 SecP384R1Field.subtract(Y3.x, t1, Y3.x); 254 255 SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M); 256 SecP384R1Field.twice(Y1.x, Z3.x); 257 if (!Z1IsOne) 258 { 259 SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x); 260 } 261 262 return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); 263 } 264 265 public ECPoint twicePlus(ECPoint b) 266 { 267 if (this == b) 268 { 269 return threeTimes(); 270 } 271 if (this.isInfinity()) 272 { 273 return b; 274 } 275 if (b.isInfinity()) 276 { 277 return twice(); 278 } 279 280 ECFieldElement Y1 = this.y; 281 if (Y1.isZero()) 282 { 283 return b; 284 } 285 286 return twice().add(b); 287 } 288 289 public ECPoint threeTimes() 290 { 291 if (this.isInfinity() || this.y.isZero()) 292 { 293 return this; 294 } 295 296 // NOTE: Be careful about recursions between twicePlus and threeTimes 297 return twice().add(this); 298 } 299 300 public ECPoint negate() 301 { 302 if (this.isInfinity()) 303 { 304 return this; 305 } 306 307 return new SecP384R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); 308 } 309} 310