| package org.bouncycastle.math.raw; |
| |
| public abstract class Mont256 |
| { |
| private static final long M = 0xFFFFFFFFL; |
| |
| public static int inverse32(int x) |
| { |
| // assert (x & 1) == 1; |
| int z = x; // x.z == 1 mod 2**3 |
| z *= 2 - x * z; // x.z == 1 mod 2**6 |
| z *= 2 - x * z; // x.z == 1 mod 2**12 |
| z *= 2 - x * z; // x.z == 1 mod 2**24 |
| z *= 2 - x * z; // x.z == 1 mod 2**48 |
| // assert x * z == 1; |
| return z; |
| } |
| |
| public static void multAdd(int[] x, int[] y, int[] z, int[] m, int mInv32) |
| { |
| int z_8 = 0; |
| long y_0 = y[0] & M; |
| |
| for (int i = 0; i < 8; ++i) |
| { |
| long z_0 = z[0] & M; |
| long x_i = x[i] & M; |
| |
| long prod1 = x_i * y_0; |
| long carry = (prod1 & M) + z_0; |
| |
| long t = ((int)carry * mInv32) & M; |
| |
| long prod2 = t * (m[0] & M); |
| carry += (prod2 & M); |
| // assert (int)carry == 0; |
| carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); |
| |
| for (int j = 1; j < 8; ++j) |
| { |
| prod1 = x_i * (y[j] & M); |
| prod2 = t * (m[j] & M); |
| |
| carry += (prod1 & M) + (prod2 & M) + (z[j] & M); |
| z[j - 1] = (int)carry; |
| carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); |
| } |
| |
| carry += (z_8 & M); |
| z[7] = (int)carry; |
| z_8 = (int)(carry >>> 32); |
| } |
| |
| if (z_8 != 0 || Nat256.gte(z, m)) |
| { |
| Nat256.sub(z, m, z); |
| } |
| } |
| |
| public static void multAddXF(int[] x, int[] y, int[] z, int[] m) |
| { |
| // assert m[0] == M; |
| |
| int z_8 = 0; |
| long y_0 = y[0] & M; |
| |
| for (int i = 0; i < 8; ++i) |
| { |
| long x_i = x[i] & M; |
| |
| long carry = x_i * y_0 + (z[0] & M); |
| long t = carry & M; |
| carry = (carry >>> 32) + t; |
| |
| for (int j = 1; j < 8; ++j) |
| { |
| long prod1 = x_i * (y[j] & M); |
| long prod2 = t * (m[j] & M); |
| |
| carry += (prod1 & M) + (prod2 & M) + (z[j] & M); |
| z[j - 1] = (int)carry; |
| carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); |
| } |
| |
| carry += (z_8 & M); |
| z[7] = (int)carry; |
| z_8 = (int)(carry >>> 32); |
| } |
| |
| if (z_8 != 0 || Nat256.gte(z, m)) |
| { |
| Nat256.sub(z, m, z); |
| } |
| } |
| |
| public static void reduce(int[] z, int[] m, int mInv32) |
| { |
| for (int i = 0; i < 8; ++i) |
| { |
| int z_0 = z[0]; |
| |
| long t = (z_0 * mInv32) & M; |
| |
| long carry = t * (m[0] & M) + (z_0 & M); |
| // assert (int)carry == 0; |
| carry >>>= 32; |
| |
| for (int j = 1; j < 8; ++j) |
| { |
| carry += t * (m[j] & M) + (z[j] & M); |
| z[j - 1] = (int)carry; |
| carry >>>= 32; |
| } |
| |
| z[7] = (int)carry; |
| // assert carry >>> 32 == 0; |
| } |
| |
| if (Nat256.gte(z, m)) |
| { |
| Nat256.sub(z, m, z); |
| } |
| } |
| |
| public static void reduceXF(int[] z, int[] m) |
| { |
| // assert m[0] == M; |
| |
| for (int i = 0; i < 8; ++i) |
| { |
| int z_0 = z[0]; |
| |
| long t = z_0 & M; |
| long carry = t; |
| |
| for (int j = 1; j < 8; ++j) |
| { |
| carry += t * (m[j] & M) + (z[j] & M); |
| z[j - 1] = (int)carry; |
| carry >>>= 32; |
| } |
| |
| z[7] = (int)carry; |
| // assert carry >>> 32 == 0; |
| } |
| |
| if (Nat256.gte(z, m)) |
| { |
| Nat256.sub(z, m, z); |
| } |
| } |
| } |