diff --git a/make/jdk/src/classes/build/tools/intpoly/FieldGen.java b/make/jdk/src/classes/build/tools/intpoly/FieldGen.java index fcc45db0219..c29a315f368 100644 --- a/make/jdk/src/classes/build/tools/intpoly/FieldGen.java +++ b/make/jdk/src/classes/build/tools/intpoly/FieldGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,36 +34,6 @@ import java.util.*; public class FieldGen { - static FieldParams Curve25519 = new FieldParams( - "IntegerPolynomial25519", 26, 10, 1, 255, - Arrays.asList( - new Term(0, -19) - ), - Curve25519CrSequence(), simpleSmallCrSequence(10) - ); - - private static List Curve25519CrSequence() { - List result = new ArrayList(); - - // reduce(7,2) - result.add(new Reduce(17)); - result.add(new Reduce(18)); - - // carry(8,2) - result.add(new Carry(8)); - result.add(new Carry(9)); - - // reduce(0,7) - for (int i = 10; i < 17; i++) { - result.add(new Reduce(i)); - } - - // carry(0,9) - result.addAll(fullCarry(10)); - - return result; - } - static FieldParams Curve448 = new FieldParams( "IntegerPolynomial448", 28, 16, 1, 448, Arrays.asList( @@ -224,8 +194,7 @@ public class FieldGen { } static final FieldParams[] ALL_FIELDS = { - Curve25519, Curve448, - P256, P384, P521, O256, O384, O521, O25519, O448 + Curve448, P256, P384, P521, O256, O384, O521, O25519, O448 }; public static class Term { diff --git a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java new file mode 100644 index 00000000000..c8f23da417e --- /dev/null +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; + +public final class IntegerPolynomial25519 extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 51; + private static final int NUM_LIMBS = 5; + private static final int MAX_ADDS = 1; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1L << (BITS_PER_LIMB - 1); + private static final long LIMB_MASK = -1L >>> (64 - BITS_PER_LIMB); + + public static final IntegerPolynomial25519 ONE = + new IntegerPolynomial25519(); + + private IntegerPolynomial25519() { + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + } + + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(255); + result = result.subtract(BigInteger.valueOf(19)); + + return result; + } + + /** + * Carry from a range of limb positions. + * Override for performance (unnesting). + * + * @param limbs [in|out] the limbs for carry operation. + * @param start [in] the starting position of carry. + * @param end [in] the ending position of carry. + */ + @Override + protected void carry(long[] limbs, int start, int end) { + long carry; + + for (int i = start; i < end; i++) { + carry = (limbs[i] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[i] -= (carry << BITS_PER_LIMB); + limbs[i + 1] += carry; + } + } + + /** + * Carry operation for all limb positions. + * Override for performance (unroll and unnesting). + * + * @param limbs [in|out] the limbs for carry operation. + */ + @Override + protected void carry(long[] limbs) { + long carry = (limbs[0] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[0] -= carry << BITS_PER_LIMB; + limbs[1] += carry; + + carry = (limbs[1] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[1] -= carry << BITS_PER_LIMB; + limbs[2] += carry; + + carry = (limbs[2] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[2] -= carry << BITS_PER_LIMB; + limbs[3] += carry; + + carry = (limbs[3] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[3] -= carry << BITS_PER_LIMB; + limbs[4] += carry; + } + + /** + * Multiply limbs by scalar value. + * Superclass assumes that limb primitive radix > (bits per limb * 2) + * + * @param a [in|out] the limbs to multiply a carry operation. 'a' is + * assumed to be reduced. + * @param b [in] the scalar value to be muliplied with the limbs. + */ + @Override + protected void multByInt(long[] a, long b) { + long aa0 = a[0]; + long aa1 = a[1]; + long aa2 = a[2]; + long aa3 = a[3]; + long aa4 = a[4]; + + long bb0 = b; + + final long shift1 = 64 - BITS_PER_LIMB; + final long shift2 = BITS_PER_LIMB; + + long d0; // low digit from multiplication + long dd0; // high digit from multiplication + // multiplication result digits for each column + long c0, c1, c2, c3, c4, c5; + + // Row 0 - multiply by aa0 + d0 = aa0 * bb0; + dd0 = Math.multiplyHigh(aa0, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + c0 = d0; + c1 = dd0; + + // Row 1 - multiply by aa1 + d0 = aa1 * bb0; + dd0 = Math.multiplyHigh(aa1, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + c1 += d0; + c2 = dd0; + + // Row 2 - multiply by aa2 + d0 = aa2 * bb0; + dd0 = Math.multiplyHigh(aa2, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + c2 += d0; + c3 = dd0; + + // Row 3 - multiply by aa3 + d0 = aa3 * bb0; + dd0 = Math.multiplyHigh(aa3, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + c3 += d0; + c4 = dd0; + + // Row 4 - multiply by aa4 + d0 = aa4 * bb0; + dd0 = Math.multiplyHigh(aa4, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + c4 += d0; + c5 = dd0; + + // Perform pseudo-Mersenne reduction + a[0] = c0 + (19 * c5); + + a[1] = c1; + a[2] = c2; + a[3] = c3; + a[4] = c4; + + reduce(a); + } + + /** + * Carry in all positions and reduce high order limb. + * + * @param limbs [in|out] the limbs to carry and reduce. + */ + protected void reduce(long[] limbs) { + long carry = (limbs[3] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[3] -= carry << BITS_PER_LIMB; + limbs[4] += carry; + + carry = (limbs[4] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[4] -= carry << BITS_PER_LIMB; + + limbs[0] += 19 * carry; + + carry = (limbs[0] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[0] -= carry << BITS_PER_LIMB; + limbs[1] += carry; + + carry = (limbs[1] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[1] -= carry << BITS_PER_LIMB; + limbs[2] += carry; + + carry = (limbs[2] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[2] -= carry << BITS_PER_LIMB; + limbs[3] += carry; + + carry = (limbs[3] + CARRY_ADD) >> BITS_PER_LIMB; + limbs[3] -= carry << BITS_PER_LIMB; + limbs[4] += carry; + } + + /** + * Reduces digit 'v' at limb position 'i' to a lower limb. + * + * @param limbs [in|out] the limbs to reduce in. + * @param v [in] the digit to reduce to the lower limb. + * @param i [in] the limbs to reduce from. + */ + protected void reduceIn(long[] limbs, long v, int i) { + limbs[i - NUM_LIMBS] += 19 * v; + } + + /** + * Carry from high order limb and reduce to the lower order limb. Assumed + * to be called two times to propagate the carries. + * + * @param limbs [in|out] the limbs to fully carry and reduce. + */ + protected void finalCarryReduceLast(long[] limbs) { + long carry = limbs[4] >> BITS_PER_LIMB; + + limbs[4] -= carry << BITS_PER_LIMB; + limbs[0] += 19 * carry; + } + + /** + * Multiply two limbs using a high/low digit technique that allows for + * larger limb sizes. It is assumed that both limbs have already been + * reduced. + * + * @param a [in] the limb operand to multiply. + * @param b [in] the limb operand to multiply. + * @param r [out] the product of the limbs operands that is fully reduced. + */ + protected void mult(long[] a, long[] b, long[] r) { + long aa0 = a[0]; + long aa1 = a[1]; + long aa2 = a[2]; + long aa3 = a[3]; + long aa4 = a[4]; + + long bb0 = b[0]; + long bb1 = b[1]; + long bb2 = b[2]; + long bb3 = b[3]; + long bb4 = b[4]; + + final long shift1 = 64 - BITS_PER_LIMB; + final long shift2 = BITS_PER_LIMB; + + long d0, d1, d2, d3, d4; // low digits from multiplication + long dd0, dd1, dd2, dd3, dd4; // high digits from multiplication + // multiplication result digits for each column + long c0, c1, c2, c3, c4, c5, c6, c7, c8, c9; + + // Row 0 - multiply by aa0 + d0 = aa0 * bb0; + dd0 = Math.multiplyHigh(aa0, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa0 * bb1; + dd1 = Math.multiplyHigh(aa0, bb1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa0 * bb2; + dd2 = Math.multiplyHigh(aa0, bb2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa0 * bb3; + dd3 = Math.multiplyHigh(aa0, bb3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa0 * bb4; + dd4 = Math.multiplyHigh(aa0, bb4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c0 = d0; + c1 = d1 + dd0; + c2 = d2 + dd1; + c3 = d3 + dd2; + c4 = d4 + dd3; + c5 = dd4; + + // Row 1 - multiply by aa1 + d0 = aa1 * bb0; + dd0 = Math.multiplyHigh(aa1, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa1 * bb1; + dd1 = Math.multiplyHigh(aa1, bb1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa1 * bb2; + dd2 = Math.multiplyHigh(aa1, bb2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa1 * bb3; + dd3 = Math.multiplyHigh(aa1, bb3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa1 * bb4; + dd4 = Math.multiplyHigh(aa1, bb4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c1 += d0; + c2 += d1 + dd0; + c3 += d2 + dd1; + c4 += d3 + dd2; + c5 += d4 + dd3; + c6 = dd4; + + // Row 2 - multiply by aa2 + d0 = aa2 * bb0; + dd0 = Math.multiplyHigh(aa2, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa2 * bb1; + dd1 = Math.multiplyHigh(aa2, bb1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa2 * bb2; + dd2 = Math.multiplyHigh(aa2, bb2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa2 * bb3; + dd3 = Math.multiplyHigh(aa2, bb3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa2 * bb4; + dd4 = Math.multiplyHigh(aa2, bb4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c2 += d0; + c3 += d1 + dd0; + c4 += d2 + dd1; + c5 += d3 + dd2; + c6 += d4 + dd3; + c7 = dd4; + + // Row 3 - multiply by aa3 + d0 = aa3 * bb0; + dd0 = Math.multiplyHigh(aa3, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa3 * bb1; + dd1 = Math.multiplyHigh(aa3, bb1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa3 * bb2; + dd2 = Math.multiplyHigh(aa3, bb2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa3 * bb3; + dd3 = Math.multiplyHigh(aa3, bb3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa3 * bb4; + dd4 = Math.multiplyHigh(aa3, bb4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c3 += d0; + c4 += d1 + dd0; + c5 += d2 + dd1; + c6 += d3 + dd2; + c7 += d4 + dd3; + c8 = dd4; + + // Row 4 - multiply by aa4 + d0 = aa4 * bb0; + dd0 = Math.multiplyHigh(aa4, bb0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa4 * bb1; + dd1 = Math.multiplyHigh(aa4, bb1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa4 * bb2; + dd2 = Math.multiplyHigh(aa4, bb2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa4 * bb3; + dd3 = Math.multiplyHigh(aa4, bb3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa4 * bb4; + dd4 = Math.multiplyHigh(aa4, bb4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c4 += d0; + c5 += d1 + dd0; + c6 += d2 + dd1; + c7 += d3 + dd2; + c8 += d4 + dd3; + c9 = dd4; + + // Perform pseudo-Mersenne reduction + r[0] = c0 + (19 * c5); + r[1] = c1 + (19 * c6); + r[2] = c2 + (19 * c7); + r[3] = c3 + (19 * c8); + r[4] = c4 + (19 * c9); + + reduce(r); + } + + /** + * Takes a single limb and squares it using a high/low digit technique that + * allows for larger limb sizes. It is assumed that the limb input has + * already been reduced. + * + * @param a [in] the limb operand to square. + * @param r [out] the resulting square of the limb which is fully reduced. + */ + protected void square(long[] a, long[] r) { + long aa0 = a[0]; + long aa1 = a[1]; + long aa2 = a[2]; + long aa3 = a[3]; + long aa4 = a[4]; + + final long shift1 = 64 - BITS_PER_LIMB; + final long shift2 = BITS_PER_LIMB; + + long d0, d1, d2, d3, d4; // low digits from multiplication + long dd0, dd1, dd2, dd3, dd4; // high digits from multiplication + // multiplication result digits for each column + long c0, c1, c2, c3, c4, c5, c6, c7, c8, c9; + + // Row 0 - multiply by aa0 + d0 = aa0 * aa0; + dd0 = Math.multiplyHigh(aa0, aa0) << shift1 | (d0 >>> shift2); + d0 &= LIMB_MASK; + + d1 = aa0 * aa1; + dd1 = Math.multiplyHigh(aa0, aa1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa0 * aa2; + dd2 = Math.multiplyHigh(aa0, aa2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa0 * aa3; + dd3 = Math.multiplyHigh(aa0, aa3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa0 * aa4; + dd4 = Math.multiplyHigh(aa0, aa4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c0 = d0; + c1 = (d1 << 1) + dd0; + c2 = (d2 + dd1) << 1; + c3 = (d3 + dd2) << 1; + c4 = (d4 + dd3) << 1; + c5 = dd4 << 1; + + // Row 1 - multiply by aa1 + d1 = aa1 * aa1; + dd1 = Math.multiplyHigh(aa1, aa1) << shift1 | (d1 >>> shift2); + d1 &= LIMB_MASK; + + d2 = aa1 * aa2; + dd2 = Math.multiplyHigh(aa1, aa2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa1 * aa3; + dd3 = Math.multiplyHigh(aa1, aa3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa1 * aa4; + dd4 = Math.multiplyHigh(aa1, aa4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c2 += d1; + c3 += (d2 << 1) + dd1; + c4 += (d3 + dd2) << 1; + c5 += (d4 + dd3) << 1; + c6 = dd4 << 1; + + // Row 2 - multiply by aa2 + d2 = aa2 * aa2; + dd2 = Math.multiplyHigh(aa2, aa2) << shift1 | (d2 >>> shift2); + d2 &= LIMB_MASK; + + d3 = aa2 * aa3; + dd3 = Math.multiplyHigh(aa2, aa3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa2 * aa4; + dd4 = Math.multiplyHigh(aa2, aa4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c4 += d2; + c5 += (d3 << 1) + dd2; + c6 += (d4 + dd3) << 1; + c7 = dd4 << 1; + + // Row 3 - multiply by aa3 + d3 = aa3 * aa3; + dd3 = Math.multiplyHigh(aa3, aa3) << shift1 | (d3 >>> shift2); + d3 &= LIMB_MASK; + + d4 = aa3 * aa4; + dd4 = Math.multiplyHigh(aa3, aa4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c6 += d3; + c7 += (d4 << 1) + dd3; + c8 = dd4 << 1; + + // Row 4 - multiply by aa4 + d4 = aa4 * aa4; + dd4 = Math.multiplyHigh(aa4, aa4) << shift1 | (d4 >>> shift2); + d4 &= LIMB_MASK; + + c8 += d4; + c9 = dd4; + + // Perform pseudo-Mersenne reduction + r[0] = c0 + (19 * c5); + r[1] = c1 + (19 * c6); + r[2] = c2 + (19 * c7); + r[3] = c3 + (19 * c8); + r[4] = c4 + (19 * c9); + + reduce(r); + } +} diff --git a/test/jdk/sun/security/util/math/TestIntegerModuloP.java b/test/jdk/sun/security/util/math/TestIntegerModuloP.java index e1c02365424..f2b73223efc 100644 --- a/test/jdk/sun/security/util/math/TestIntegerModuloP.java +++ b/test/jdk/sun/security/util/math/TestIntegerModuloP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary Test proper operation of integer field arithmetic * @modules java.base/sun.security.util java.base/sun.security.util.math java.base/sun.security.util.math.intpoly * @build BigIntegerModuloP - * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 32 0 + * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 31 0 */ /*