| /* | |
| * Copyright (c) 2024, Intel Corporation. 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. | |
| * | |
| * 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. | |
| */ | |
| import java.util.Random; | |
| import java.util.List; | |
| import java.util.LinkedList; | |
| import java.math.BigInteger; | |
| import java.lang.reflect.Field; | |
| import java.security.spec.ECParameterSpec; | |
| import sun.security.ec.ECOperations; | |
| import sun.security.util.ECUtil; | |
| import sun.security.util.NamedCurve; | |
| import sun.security.util.CurveDB; | |
| import sun.security.ec.point.*; | |
| import java.security.spec.ECPoint; | |
| import sun.security.util.KnownOIDs; | |
| import sun.security.util.math.IntegerMontgomeryFieldModuloP; | |
| import sun.security.util.math.intpoly.*; | |
| /* | |
| * @test | |
| * @modules java.base/sun.security.ec java.base/sun.security.ec.point | |
| * java.base/sun.security.util java.base/sun.security.util.math | |
| * java.base/sun.security.util.math.intpoly | |
| * @run main/othervm --add-opens java.base/sun.security.ec=ALL-UNNAMED | |
| * ECOperationsKATTest | |
| * @summary Unit test ECOperationsKATTest. | |
| */ | |
| /* | |
| * @test | |
| * @modules java.base/sun.security.ec java.base/sun.security.ec.point | |
| * java.base/sun.security.util java.base/sun.security.util.math | |
| * java.base/sun.security.util.math.intpoly | |
| * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xcomp | |
| * -XX:-TieredCompilation --add-opens java.base/sun.security.ec=ALL-UNNAMED | |
| * -XX:+UnlockDiagnosticVMOptions ECOperationsKATTest | |
| * @summary Unit test ECOperationsKATTest. | |
| */ | |
| public class ECOperationsKATTest { | |
| final private static java.util.HexFormat hex = java.util.HexFormat.of(); | |
| public static void main(String args[]) throws Exception { | |
| int testsPassed = 0; | |
| int testNumber = 0; | |
| for (TestData test : testList) { | |
| System.out.println("*** Test " + ++testNumber + ": " + test.testName); | |
| if (runSingleTest(test)) { | |
| testsPassed++; | |
| } | |
| } | |
| System.out.println(); | |
| if (testsPassed != testNumber) { | |
| throw new RuntimeException( | |
| "One or more tests failed. Check output for details"); | |
| } | |
| } | |
| private static boolean check(MutablePoint testValue, ECPoint reference) { | |
| AffinePoint affine = testValue.asAffine(); | |
| BigInteger x = affine.getX().asBigInteger(); | |
| BigInteger y = affine.getY().asBigInteger(); | |
| BigInteger refX = reference.getAffineX(); | |
| BigInteger refY = reference.getAffineY(); | |
| if (!refX.equals(x) || !refY.equals(y)) { | |
| System.out.println("ERROR - Output Mismatch!"); | |
| System.out.println("Expected: X: " + refX.toString(16) + " Y: " | |
| + refY.toString(16)); | |
| System.out.println( | |
| "Result: X: " + x.toString(16) + " Y: " + y.toString(16)); | |
| return false; | |
| } | |
| return true; | |
| } | |
| private static class TestData { | |
| public TestData(String name, String keyStr, String xStr1, String yStr1, | |
| String xStr2, String yStr2) { | |
| testName = name; | |
| // multiplier = (new BigInteger(keyStr, 16)).toByteArray(); | |
| multiplier = hex.parseHex(keyStr); | |
| sun.security.util.ArrayUtil.reverse(multiplier); | |
| reference1 = new ECPoint(new BigInteger(xStr1, 16), | |
| new BigInteger(yStr1, 16)); | |
| reference2 = new ECPoint(new BigInteger(xStr2, 16), | |
| new BigInteger(yStr2, 16)); | |
| } | |
| String testName; | |
| byte[] multiplier; | |
| ECPoint reference1; // For generator multiplier test | |
| ECPoint reference2; // For non-generator multiplier test | |
| } | |
| public static final List<TestData> testList = new LinkedList<TestData>() {{ | |
| // (x1,y1) = mult*generator | |
| // (x2,y2) = mult*mult*generator | |
| add(new TestData("Test Vector #1", | |
| "0000000000000000000000000000000000000000000000000000000000000012", // mult | |
| "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", // x1 | |
| "F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2", // y1 | |
| "4954047A366A91E3FD94E574DB6F2B04F3A8465883DBC55A816EA563BF54A324", // x2 | |
| "B5A54786FD9EA48C9FC38A0557B0C4D54F285908A7291B630D06BEE970F530D3") // y2 | |
| ); | |
| add(new TestData("Test Vector #2", | |
| "1200000000000000000000000000000000000000000000000000000000000000", // mult | |
| "DF684E6D0D57AF8B89DA11E8F7436C3D360F531D62BDCE42C5A8B72D73D5C717", // x | |
| "9D3576BD03C09B8F416EE9C27D70AD4A425119271ACF549312CA48758F4E1FEC", // y | |
| "57C8257EEAABF5446DCFACB99DEE104367B6C9950C76797C372EB177D5FA23B3", // x | |
| "1CD3E8A34521C1C8E574EB4B99343CAA57E00725D8618F0231C7C79AA6837725") // y | |
| ); | |
| add(new TestData("Test Vector #3", | |
| "0000000000000000000000000000000120000000000000000000000000000012", // mult | |
| "A69DFD47B24485E5F523BDA5FBACF03F5A7C3D22E0C2BC6705594B7B051A06D0", // x | |
| "ECF19629416BE5C9AF1E30988F3AA8B803809CF4D12944EB49C5E9892723798A", // y | |
| "1E28559F5B681C308632EE11A007B9891B3FD592C982C4926153795794295E58", // x | |
| "3C373046C27BB34609A43C91DF6D4B9AB9EB08F3B69A8F8FAE944211D8297F30") // y | |
| ); | |
| add(new TestData("Test Vector #4", | |
| "0000000000000000000000000000000000000000000000000000000000000001", // mult | |
| "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", // x | |
| "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", // y | |
| "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", // x | |
| "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5") // y | |
| ); | |
| add(new TestData("Test Vector #5", | |
| "EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // mult | |
| "66B71D0BD47344197CCFB0C9578EAF0ADB609E05BB4E8F87D56BD34F24EE7C47", // x | |
| "14A0ECB7F708C02B2BAE238D2C4607BB9D04FCE64E10A428C911D6FA25B2F0FD", // y | |
| "D25AAFD0FCC5B5E95C84C0702C138BC4D7FEB4E5F9C2DFB4301E313507EFDF44", // x | |
| "F3F04EBC7D308511B0392BB7171CF92688D6484A95A8100EDFC933613A359133") // y | |
| ); | |
| add(new TestData("Test Vector #6", | |
| "1111111111111111111111111111111111111111111111111111111111111111", // mult | |
| "0217E617F0B6443928278F96999E69A23A4F2C152BDF6D6CDF66E5B80282D4ED", // x | |
| "194A7DEBCB97712D2DDA3CA85AA8765A56F45FC758599652F2897C65306E5794", // y | |
| "A83A07D6AE918359DEBCC385DA1E416EB83417435079CA8DB06005E107C309A0", // x | |
| "5AACDF816850C33EB3E54F3D0DD759B97B5E7065B2060016F73735E4A6AADE23") // y | |
| ); | |
| }}; | |
| private static boolean runSingleTest(TestData testData) { | |
| int keySize = 256; | |
| ECParameterSpec params = ECUtil.getECParameterSpec(keySize); | |
| NamedCurve curve = CurveDB.lookup(KnownOIDs.secp256r1.value()); | |
| ECPoint generator = curve.getGenerator(); | |
| BigInteger b = curve.getCurve().getB(); | |
| if (params == null || generator == null) { | |
| throw new RuntimeException( | |
| "No EC parameters available for key size " + keySize + " bits"); | |
| } | |
| ECOperations ops = ECOperations.forParameters(params).get(); | |
| ECOperations opsReference = new ECOperations( | |
| IntegerPolynomialP256.ONE.getElement(b), P256OrderField.ONE); | |
| boolean instanceTest1 = ops | |
| .getField() instanceof IntegerMontgomeryFieldModuloP; | |
| boolean instanceTest2 = opsReference | |
| .getField() instanceof IntegerMontgomeryFieldModuloP; | |
| if (instanceTest1 == false || instanceTest2 == true) { | |
| throw new RuntimeException("Bad Initialization: [" + instanceTest1 + "," | |
| + instanceTest2 + "]"); | |
| } | |
| MutablePoint nextPoint = ops.multiply(generator, testData.multiplier); | |
| MutablePoint nextReferencePoint = opsReference.multiply(generator, | |
| testData.multiplier); | |
| if (!check(nextReferencePoint, testData.reference1) | |
| || !check(nextPoint, testData.reference1)) { | |
| return false; | |
| } | |
| nextPoint = ops.multiply(nextPoint.asAffine(), testData.multiplier); | |
| nextReferencePoint = opsReference.multiply(nextReferencePoint.asAffine(), | |
| testData.multiplier); | |
| if (!check(nextReferencePoint, testData.reference2) | |
| || !check(nextPoint, testData.reference2)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| } | |
| //make test TEST="test/jdk/com/sun/security/ec/ECOperationsKATTest.java" | |
| /* | |
| * KAT generator using OpenSSL for reference vectors | |
| * g++ ecpoint.cpp -g -lcrypto -Wno-deprecated-declarations && ./a.out | |
| * (Some OpenSSL EC operations are marked internal i.e. deprecated) | |
| * | |
| #include <openssl/obj_mac.h> | |
| #include <openssl/ec.h> | |
| void check(int rc, const char* locator) { | |
| if (rc != 1) { | |
| printf("Failed at %s\n", locator); | |
| exit(55); | |
| } | |
| } | |
| int main(){ | |
| BN_CTX* ctx = BN_CTX_new(); | |
| BIGNUM* k = BN_CTX_get(ctx); | |
| BIGNUM* x1 = BN_CTX_get(ctx); | |
| BIGNUM* y1 = BN_CTX_get(ctx); | |
| BIGNUM* x2 = BN_CTX_get(ctx); | |
| BIGNUM* y2 = BN_CTX_get(ctx); | |
| EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); | |
| EC_POINT* pubkey = EC_POINT_new(ec_group); | |
| EC_POINT* pubkey2 = EC_POINT_new(ec_group); | |
| int rc; | |
| rc = BN_hex2bn(&k, "1111111111111111111111111111111111111111111111111111111111111111"); //check(rc, "set raw key"); | |
| rc = EC_POINT_mul(ec_group, pubkey, k, NULL, NULL, ctx); check(rc, "mult public key"); | |
| rc = EC_POINT_get_affine_coordinates(ec_group, pubkey, x1, y1, ctx); check(rc, "get affine coordinates"); | |
| rc = EC_POINT_mul(ec_group, pubkey2, NULL, pubkey, k, ctx); check(rc, "mult public key"); | |
| rc = EC_POINT_get_affine_coordinates(ec_group, pubkey2, x2, y2, ctx); check(rc, "get affine coordinates"); | |
| printf("k: %s\n", BN_bn2hex(k)); | |
| printf("x: %s\ny: %s\n", BN_bn2hex(x1), BN_bn2hex(y1)); | |
| printf("x: %s\ny: %s\n", BN_bn2hex(x2), BN_bn2hex(y2)); | |
| BN_CTX_free(ctx); | |
| return 0; | |
| } | |
| */ |