Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/util/math/TestIntegerModuloP.java
38853 views
/*1* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8181594 820864826* @summary Test proper operation of integer field arithmetic27* @modules java.base/sun.security.util java.base/sun.security.util.math java.base/sun.security.util.math.intpoly28* @build BigIntegerModuloP29* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 32 030* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial448 56 131* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial1305 16 232* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP256 32 533* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP384 48 634* @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP521 66 735* @run main TestIntegerModuloP sun.security.util.math.intpoly.P256OrderField 32 836* @run main TestIntegerModuloP sun.security.util.math.intpoly.P384OrderField 48 937* @run main TestIntegerModuloP sun.security.util.math.intpoly.P521OrderField 66 1038*/3940import sun.security.util.math.*;41import sun.security.util.math.intpoly.*;42import java.util.function.*;4344import java.util.*;45import java.math.*;46import java.nio.*;4748public class TestIntegerModuloP {4950static BigInteger TWO = BigInteger.valueOf(2);5152// The test has a list of functions, and it selects randomly from that list5354// The function types55interface ElemFunction extends BiFunction56<MutableIntegerModuloP, IntegerModuloP, IntegerModuloP> { }57interface ElemArrayFunction extends BiFunction58<MutableIntegerModuloP, IntegerModuloP, byte[]> { }59interface TriConsumer <T, U, V> {60void accept(T t, U u, V v);61}62interface ElemSetFunction extends TriConsumer63<MutableIntegerModuloP, IntegerModuloP, byte[]> { }6465// The lists of functions. Multiple lists are needed because the test66// respects the limitations of the arithmetic implementations.67static final List<ElemFunction> ADD_FUNCTIONS = new ArrayList<>();68static final List<ElemFunction> MULT_FUNCTIONS = new ArrayList<>();69static final List<ElemArrayFunction> ARRAY_FUNCTIONS = new ArrayList<>();70static final List<ElemSetFunction> SET_FUNCTIONS = new ArrayList<>();7172static void setUpFunctions(IntegerFieldModuloP field, int length) {7374ADD_FUNCTIONS.clear();75MULT_FUNCTIONS.clear();76SET_FUNCTIONS.clear();77ARRAY_FUNCTIONS.clear();7879byte highByte = (byte)80(field.getSize().bitLength() > length * 8 ? 1 : 0);8182// add functions are (im)mutable add/subtract83ADD_FUNCTIONS.add(IntegerModuloP::add);84ADD_FUNCTIONS.add(IntegerModuloP::subtract);85ADD_FUNCTIONS.add(MutableIntegerModuloP::setSum);86ADD_FUNCTIONS.add(MutableIntegerModuloP::setDifference);87// also include functions that return the first/second argument88ADD_FUNCTIONS.add((a, b) -> a);89ADD_FUNCTIONS.add((a, b) -> b);9091// mult functions are (im)mutable multiply and square92MULT_FUNCTIONS.add(IntegerModuloP::multiply);93MULT_FUNCTIONS.add((a, b) -> a.square());94MULT_FUNCTIONS.add((a, b) -> b.square());95MULT_FUNCTIONS.add(MutableIntegerModuloP::setProduct);96MULT_FUNCTIONS.add((a, b) -> a.setSquare());97// also test multiplication by a small value98MULT_FUNCTIONS.add((a, b) -> a.setProduct(b.getField().getSmallValue(99b.asBigInteger().mod(BigInteger.valueOf(262144)).intValue())));100101// set functions are setValue with various argument types102SET_FUNCTIONS.add((a, b, c) -> a.setValue(b));103SET_FUNCTIONS.add((a, b, c) ->104a.setValue(c, 0, c.length, (byte) 0));105SET_FUNCTIONS.add((a, b, c) ->106a.setValue(ByteBuffer.wrap(c, 0, c.length).order(ByteOrder.LITTLE_ENDIAN),107c.length, highByte));108109// array functions return the (possibly modified) value as byte array110ARRAY_FUNCTIONS.add((a, b ) -> a.asByteArray(length));111ARRAY_FUNCTIONS.add((a, b) -> a.addModPowerTwo(b, length));112}113114public static void main(String[] args) {115116String className = args[0];117final int length = Integer.parseInt(args[1]);118int seed = Integer.parseInt(args[2]);119120Class<IntegerFieldModuloP> fieldBaseClass = IntegerFieldModuloP.class;121try {122Class<? extends IntegerFieldModuloP> clazz =123Class.forName(className).asSubclass(fieldBaseClass);124IntegerFieldModuloP field =125clazz.getDeclaredConstructor().newInstance();126127setUpFunctions(field, length);128129runFieldTest(field, length, seed);130} catch (Exception ex) {131throw new RuntimeException(ex);132}133System.out.println("All tests passed");134}135136static void assertEqual(IntegerModuloP e1, IntegerModuloP e2) {137138if (!e1.asBigInteger().equals(e2.asBigInteger())) {139throw new RuntimeException("values not equal: "140+ e1.asBigInteger() + " != " + e2.asBigInteger());141}142}143144// A class that holds pairs of actual/expected values, and allows145// computation on these pairs.146static class TestPair<T extends IntegerModuloP> {147private final T test;148private final T baseline;149150public TestPair(T test, T baseline) {151this.test = test;152this.baseline = baseline;153}154155public T getTest() {156return test;157}158public T getBaseline() {159return baseline;160}161162private void assertEqual() {163TestIntegerModuloP.assertEqual(test, baseline);164}165166public TestPair<MutableIntegerModuloP> mutable() {167return new TestPair<>(test.mutable(), baseline.mutable());168}169170public171<R extends IntegerModuloP, X extends IntegerModuloP>172TestPair<X> apply(BiFunction<T, R, X> func, TestPair<R> right) {173X testResult = func.apply(test, right.test);174X baselineResult = func.apply(baseline, right.baseline);175return new TestPair(testResult, baselineResult);176}177178public179<U extends IntegerModuloP, V>180void apply(TriConsumer<T, U, V> func, TestPair<U> right, V argV) {181func.accept(test, right.test, argV);182func.accept(baseline, right.baseline, argV);183}184185public186<R extends IntegerModuloP>187void applyAndCheckArray(BiFunction<T, R, byte[]> func,188TestPair<R> right) {189byte[] testResult = func.apply(test, right.test);190byte[] baselineResult = func.apply(baseline, right.baseline);191if (!Arrays.equals(testResult, baselineResult)) {192throw new RuntimeException("Array values do not match: "193+ byteArrayToHexString(testResult) + " != "194+ byteArrayToHexString(baselineResult));195}196}197198}199200static String byteArrayToHexString(byte[] arr) {201StringBuilder result = new StringBuilder();202for (int i = 0; i < arr.length; ++i) {203byte curVal = arr[i];204result.append(Character.forDigit(curVal >> 4 & 0xF, 16));205result.append(Character.forDigit(curVal & 0xF, 16));206}207return result.toString();208}209210static TestPair<IntegerModuloP>211applyAndCheck(ElemFunction func, TestPair<MutableIntegerModuloP> left,212TestPair<IntegerModuloP> right) {213214TestPair<IntegerModuloP> result = left.apply(func, right);215result.assertEqual();216left.assertEqual();217right.assertEqual();218219return result;220}221222static void223setAndCheck(ElemSetFunction func, TestPair<MutableIntegerModuloP> left,224TestPair<IntegerModuloP> right, byte[] argV) {225226left.apply(func, right, argV);227left.assertEqual();228right.assertEqual();229}230231static TestPair<MutableIntegerModuloP>232applyAndCheckMutable(ElemFunction func,233TestPair<MutableIntegerModuloP> left,234TestPair<IntegerModuloP> right) {235236TestPair<IntegerModuloP> result = applyAndCheck(func, left, right);237238TestPair<MutableIntegerModuloP> mutableResult = result.mutable();239mutableResult.assertEqual();240result.assertEqual();241left.assertEqual();242right.assertEqual();243244return mutableResult;245}246247static void248cswapAndCheck(int swap, TestPair<MutableIntegerModuloP> left,249TestPair<MutableIntegerModuloP> right) {250251left.getTest().conditionalSwapWith(right.getTest(), swap);252left.getBaseline().conditionalSwapWith(right.getBaseline(), swap);253254left.assertEqual();255right.assertEqual();256257}258259// Request arithmetic that should overflow, and ensure that overflow is260// detected.261static void runOverflowTest(TestPair<IntegerModuloP> elem) {262263TestPair<MutableIntegerModuloP> mutableElem = elem.mutable();264265try {266for (int i = 0; i < 1000; i++) {267applyAndCheck(MutableIntegerModuloP::setSum, mutableElem, elem);268}269applyAndCheck(MutableIntegerModuloP::setProduct, mutableElem, elem);270} catch (ArithmeticException ex) {271// this is expected272}273274mutableElem = elem.mutable();275try {276for (int i = 0; i < 1000; i++) {277elem = applyAndCheck(IntegerModuloP::add,278mutableElem, elem);279}280applyAndCheck(IntegerModuloP::multiply, mutableElem, elem);281} catch (ArithmeticException ex) {282// this is expected283}284}285286// Run a large number of random operations and ensure that287// results are correct288static void runOperationsTest(Random random, int length,289TestPair<IntegerModuloP> elem,290TestPair<IntegerModuloP> right) {291292TestPair<MutableIntegerModuloP> left = elem.mutable();293294for (int i = 0; i < 10000; i++) {295296ElemFunction addFunc1 =297ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size()));298TestPair<MutableIntegerModuloP> result1 =299applyAndCheckMutable(addFunc1, left, right);300301// left could have been modified, so turn it back into a summand302applyAndCheckMutable((a, b) -> a.setSquare(), left, right);303304ElemFunction addFunc2 =305ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size()));306TestPair<IntegerModuloP> result2 =307applyAndCheck(addFunc2, left, right);308309if (elem.test.getField() instanceof IntegerPolynomial) {310IntegerPolynomial field =311(IntegerPolynomial) elem.test.getField();312int numAdds = field.getMaxAdds();313for (int j = 1; j < numAdds; j++) {314ElemFunction addFunc3 = ADD_FUNCTIONS.315get(random.nextInt(ADD_FUNCTIONS.size()));316result2 = applyAndCheck(addFunc3, left, right);317}318}319320ElemFunction multFunc2 =321MULT_FUNCTIONS.get(random.nextInt(MULT_FUNCTIONS.size()));322TestPair<MutableIntegerModuloP> multResult =323applyAndCheckMutable(multFunc2, result1, result2);324325int swap = random.nextInt(2);326cswapAndCheck(swap, left, multResult);327328ElemSetFunction setFunc =329SET_FUNCTIONS.get(random.nextInt(SET_FUNCTIONS.size()));330byte[] valueArr = new byte[length];331random.nextBytes(valueArr);332setAndCheck(setFunc, result1, result2, valueArr);333334// left could have been modified, so to turn it back into a summand335applyAndCheckMutable((a, b) -> a.setSquare(), left, right);336337ElemArrayFunction arrayFunc =338ARRAY_FUNCTIONS.get(random.nextInt(ARRAY_FUNCTIONS.size()));339left.applyAndCheckArray(arrayFunc, right);340}341}342343// Run all the tests for a given field344static void runFieldTest(IntegerFieldModuloP testField,345int length, int seed) {346System.out.println("Testing: " + testField.getClass().getSimpleName());347348Random random = new Random(seed);349350IntegerFieldModuloP baselineField =351new BigIntegerModuloP(testField.getSize());352353int numBits = testField.getSize().bitLength();354BigInteger r =355new BigInteger(numBits, random).mod(testField.getSize());356TestPair<IntegerModuloP> rand =357new TestPair(testField.getElement(r), baselineField.getElement(r));358359runOverflowTest(rand);360361// check combinations of operations for different kinds of elements362List<TestPair<IntegerModuloP>> testElements = new ArrayList<>();363testElements.add(rand);364testElements.add(new TestPair(testField.get0(), baselineField.get0()));365testElements.add(new TestPair(testField.get1(), baselineField.get1()));366byte[] testArr = {121, 37, -100, -5, 76, 33};367testElements.add(new TestPair(testField.getElement(testArr),368baselineField.getElement(testArr)));369370testArr = new byte[length];371random.nextBytes(testArr);372testElements.add(new TestPair(testField.getElement(testArr),373baselineField.getElement(testArr)));374375random.nextBytes(testArr);376byte highByte = (byte) (numBits > length * 8 ? 1 : 0);377testElements.add(378new TestPair(379testField.getElement(testArr, 0, testArr.length, highByte),380baselineField.getElement(testArr, 0, testArr.length, highByte)381)382);383384for (int i = 0; i < testElements.size(); i++) {385for (int j = 0; j < testElements.size(); j++) {386runOperationsTest(random, length, testElements.get(i),387testElements.get(j));388}389}390}391}392393394395