1 package org.bouncycastle.math.ec.custom.sec; 2 3 import java.math.BigInteger; 4 import java.security.SecureRandom; 5 6 import org.bouncycastle.math.raw.Mod; 7 import org.bouncycastle.math.raw.Nat; 8 import org.bouncycastle.math.raw.Nat512; 9 import org.bouncycastle.util.Pack; 10 11 public class SecP521R1Field 12 { 13 // 2^521 - 1 14 static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 15 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF }; 16 private static final int P16 = 0x1FF; 17 add(int[] x, int[] y, int[] z)18 public static void add(int[] x, int[] y, int[] z) 19 { 20 int c = Nat.add(16, x, y, z) + x[16] + y[16]; 21 if (c > P16 || (c == P16 && Nat.eq(16, z, P))) 22 { 23 c += Nat.inc(16, z); 24 c &= P16; 25 } 26 z[16] = c; 27 } 28 addOne(int[] x, int[] z)29 public static void addOne(int[] x, int[] z) 30 { 31 int c = Nat.inc(16, x, z) + x[16]; 32 if (c > P16 || (c == P16 && Nat.eq(16, z, P))) 33 { 34 c += Nat.inc(16, z); 35 c &= P16; 36 } 37 z[16] = c; 38 } 39 fromBigInteger(BigInteger x)40 public static int[] fromBigInteger(BigInteger x) 41 { 42 int[] z = Nat.fromBigInteger(521, x); 43 if (Nat.eq(17, z, P)) 44 { 45 Nat.zero(17, z); 46 } 47 return z; 48 } 49 half(int[] x, int[] z)50 public static void half(int[] x, int[] z) 51 { 52 int x16 = x[16]; 53 int c = Nat.shiftDownBit(16, x, x16, z); 54 z[16] = (x16 >>> 1) | (c >>> 23); 55 } 56 inv(int[] x, int[] z)57 public static void inv(int[] x, int[] z) 58 { 59 Mod.checkedModOddInverse(P, x, z); 60 } 61 isZero(int[] x)62 public static int isZero(int[] x) 63 { 64 int d = 0; 65 for (int i = 0; i < 17; ++i) 66 { 67 d |= x[i]; 68 } 69 d = (d >>> 1) | (d & 1); 70 return (d - 1) >> 31; 71 } 72 multiply(int[] x, int[] y, int[] z)73 public static void multiply(int[] x, int[] y, int[] z) 74 { 75 int[] tt = Nat.create(33); 76 implMultiply(x, y, tt); 77 reduce(tt, z); 78 } 79 negate(int[] x, int[] z)80 public static void negate(int[] x, int[] z) 81 { 82 if (0 != isZero(x)) 83 { 84 Nat.sub(17, P, P, z); 85 } 86 else 87 { 88 Nat.sub(17, P, x, z); 89 } 90 } 91 random(SecureRandom r, int[] z)92 public static void random(SecureRandom r, int[] z) 93 { 94 byte[] bb = new byte[17 * 4]; 95 do 96 { 97 r.nextBytes(bb); 98 Pack.littleEndianToInt(bb, 0, z, 0, 17); 99 z[16] &= P16; 100 } 101 while (0 == Nat.lessThan(17, z, P)); 102 } 103 randomMult(SecureRandom r, int[] z)104 public static void randomMult(SecureRandom r, int[] z) 105 { 106 do 107 { 108 random(r, z); 109 } 110 while (0 != isZero(z)); 111 } 112 reduce(int[] xx, int[] z)113 public static void reduce(int[] xx, int[] z) 114 { 115 // assert xx[32] >>> 18 == 0; 116 117 int xx32 = xx[32]; 118 int c = Nat.shiftDownBits(16, xx, 16, 9, xx32, z, 0) >>> 23; 119 c += xx32 >>> 9; 120 c += Nat.addTo(16, xx, z); 121 if (c > P16 || (c == P16 && Nat.eq(16, z, P))) 122 { 123 c += Nat.inc(16, z); 124 c &= P16; 125 } 126 z[16] = c; 127 } 128 reduce23(int[] z)129 public static void reduce23(int[] z) 130 { 131 int z16 = z[16]; 132 int c = Nat.addWordTo(16, z16 >>> 9, z) + (z16 & P16); 133 if (c > P16 || (c == P16 && Nat.eq(16, z, P))) 134 { 135 c += Nat.inc(16, z); 136 c &= P16; 137 } 138 z[16] = c; 139 } 140 square(int[] x, int[] z)141 public static void square(int[] x, int[] z) 142 { 143 int[] tt = Nat.create(33); 144 implSquare(x, tt); 145 reduce(tt, z); 146 } 147 squareN(int[] x, int n, int[] z)148 public static void squareN(int[] x, int n, int[] z) 149 { 150 // assert n > 0; 151 152 int[] tt = Nat.create(33); 153 implSquare(x, tt); 154 reduce(tt, z); 155 156 while (--n > 0) 157 { 158 implSquare(z, tt); 159 reduce(tt, z); 160 } 161 } 162 subtract(int[] x, int[] y, int[] z)163 public static void subtract(int[] x, int[] y, int[] z) 164 { 165 int c = Nat.sub(16, x, y, z) + x[16] - y[16]; 166 if (c < 0) 167 { 168 c += Nat.dec(16, z); 169 c &= P16; 170 } 171 z[16] = c; 172 } 173 twice(int[] x, int[] z)174 public static void twice(int[] x, int[] z) 175 { 176 int x16 = x[16]; 177 int c = Nat.shiftUpBit(16, x, x16 << 23, z) | (x16 << 1); 178 z[16] = c & P16; 179 } 180 implMultiply(int[] x, int[] y, int[] zz)181 protected static void implMultiply(int[] x, int[] y, int[] zz) 182 { 183 Nat512.mul(x, y, zz); 184 185 int x16 = x[16], y16 = y[16]; 186 zz[32] = Nat.mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16); 187 } 188 implSquare(int[] x, int[] zz)189 protected static void implSquare(int[] x, int[] zz) 190 { 191 Nat512.square(x, zz); 192 193 int x16 = x[16]; 194 zz[32] = Nat.mulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16); 195 } 196 } 197