Path: blob/master/test/jdk/sun/security/ec/ECDSAJavaVerify.java
41149 views
/*1* Copyright (c) 2020, 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*/2223import com.sun.jdi.Bootstrap;24import com.sun.jdi.VMDisconnectedException;25import com.sun.jdi.VirtualMachine;26import com.sun.jdi.connect.Connector;27import com.sun.jdi.connect.LaunchingConnector;28import com.sun.jdi.event.Event;29import com.sun.jdi.event.EventSet;30import com.sun.jdi.event.MethodEntryEvent;31import com.sun.jdi.request.MethodEntryRequest;3233import java.security.AlgorithmParameters;34import java.security.KeyPair;35import java.security.KeyPairGenerator;36import java.security.SecureRandom;37import java.security.Signature;38import java.security.SignatureException;39import java.security.interfaces.ECPrivateKey;40import java.security.interfaces.ECPublicKey;41import java.security.spec.ECGenParameterSpec;42import java.security.spec.ECParameterSpec;43import java.util.Arrays;44import java.util.List;45import java.util.Map;46import java.util.Random;4748/*49* @test50* @bug 8237218 823992851* @modules jdk.crypto.ec52* jdk.jdi53* @requires os.family != "windows"54* @run main ECDSAJavaVerify debug55* @summary Support NIST Curves verification in java implementation.56* This test does not run stable on Windows. VMDisconnectedException57* might not be thrown at all.58*/5960// ATTENTION: This test depends on method names inside the non-exported61// class sun.security.ec.ECDSASignature.62public class ECDSAJavaVerify {6364static final String[] ALL_ALGS = new String[] {65"SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA"};6667static final String[] ALL_CURVES = new String[] {68"secp256r1", "secp384r1", "secp521r1"};6970public static void main(String[] args) throws Exception {71if (args.length == 1) {72// Debugging a new process with no arg73debug();74} else if (args.length == 3) {75// If one test case fail, re-run it with first 3 columns76new Test().run(Integer.parseInt(args[0]), args[1], args[2]);77} else {78// Run all test cases79Test t = new Test();80Random r = new Random();8182for (String sigAlg : ALL_ALGS) {83for (String curve : ALL_CURVES) {84t.run(r.nextInt(1000000), sigAlg, curve);85}86}87}88}8990static void debug() throws Exception {9192LaunchingConnector launchingConnector = Bootstrap93.virtualMachineManager().defaultConnector();9495Map<String, Connector.Argument> arguments96= launchingConnector.defaultArguments();97arguments.get("main").setValue(ECDSAJavaVerify.class.getName());98arguments.get("options").setValue(99"-cp " + System.getProperty("test.classes"));100VirtualMachine vm = launchingConnector.launch(arguments);101102MethodEntryRequest req = vm.eventRequestManager()103.createMethodEntryRequest();104req.addClassFilter("sun.security.ec.ECDSASignature");105req.enable();106107int numberOfTests = ALL_ALGS.length * ALL_CURVES.length * 2;108109// Expected methods to call. 'J' for java impl, 'N' for native impl110char[] expected = new char[numberOfTests];111112int pos = 0;113for (String dummy : ALL_ALGS) {114for (String curve : ALL_CURVES) {115char caller = 'J';116// For each case, Signature::verify is called twice117expected[pos++] = caller;118expected[pos++] = caller;119}120}121122// Test result123// '.': not run yet124// '-': enter engineVerify125// 'v': expected impl called126// 'x': unexpected impl called127// Note: some error cases fail before any impl called. Ex: if there128// is a DER encoding error.129char[] result = new char[numberOfTests];130Arrays.fill(result, '.');131132String stdout, stderr;133134try {135EventSet eventSet;136pos = -1; // will become 0 when entering 'engineVerify'137while ((eventSet = vm.eventQueue().remove()) != null) {138for (Event event : eventSet) {139if (event instanceof MethodEntryEvent) {140MethodEntryEvent e = (MethodEntryEvent)event;141switch (e.method().name()) {142case "engineVerify":143result[++pos] = '-';144break;145case "verifySignedDigestImpl": // the java impl146result[pos] = expected[pos] != 'J' ? 'x' : 'v';147break;148}149}150vm.resume();151}152}153} catch (VMDisconnectedException e) {154System.out.println("Virtual Machine is disconnected.");155} finally {156stderr = new String(vm.process().getErrorStream().readAllBytes());157stdout = new String(vm.process().getInputStream().readAllBytes());158}159160int exitCode = vm.process().waitFor();161System.out.println(" exit: " + exitCode);162System.out.println("stderr:\n" + stderr);163System.out.println("stdout:\n" + stdout);164165String sResult = new String(result);166167System.out.println(" Cases: " + new String(expected));168System.out.println("Result: " + sResult);169170if (pos != numberOfTests - 1 || sResult.contains("x")171|| sResult.contains(".")) {172throw new Exception("Unexpected result");173}174175if (stdout.contains("fail") || exitCode != 0) {176throw new Exception("Test failed");177}178}179180static class Test {181182public boolean run(int seed, String sigAlg, String curve)183throws Exception {184185// A determined SecureRandom based on seed. If there is anything186// wrong, we can reproduce the problem using the seed.187Random r = new Random(seed);188SecureRandom rand = new SecureRandom() {189@Override190public void nextBytes(byte[] bytes) {191r.nextBytes(bytes);192}193};194195AlgorithmParameters ap = AlgorithmParameters.getInstance("EC", "SunEC");196ap.init(new ECGenParameterSpec(curve));197ECParameterSpec spec = ap.getParameterSpec(ECParameterSpec.class);198199KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "SunEC");200kpg.initialize(spec, rand);201KeyPair kp = kpg.generateKeyPair();202ECPrivateKey ecPrivateKey = (ECPrivateKey) kp.getPrivate();203ECPublicKey ecPublicKey = (ECPublicKey) kp.getPublic();204205Signature s1 = Signature.getInstance(sigAlg, "SunEC");206s1.initSign(ecPrivateKey, rand);207byte[] msg = new byte[1234];208rand.nextBytes(msg);209s1.update(msg);210byte[] sig = s1.sign();211212Signature s2 = Signature.getInstance(sigAlg, "SunEC");213s2.initVerify(ecPublicKey);214s2.update(msg);215216boolean result1 = s2.verify(sig);217218s2.initVerify(ecPublicKey);219// modify the signature in some random manner220if (rand.nextInt(10) < 8) {221sig[rand.nextInt(10000) % sig.length]222= (byte) rand.nextInt(10000);223} else {224int newLength = rand.nextInt(100);225if (newLength == sig.length) {226newLength += 1 + rand.nextInt(2);227}228sig = Arrays.copyOf(sig, newLength);229}230231boolean result2;232try {233result2 = s2.verify(sig);234} catch (SignatureException se) {235result2 = false;236}237238boolean finalResult = result1 && !result2;239System.out.printf("%10d %20s %20s -- %5s %5s -- %s\n",240seed, sigAlg, curve, result1, result2,241finalResult ? "succeed" : "fail");242243return finalResult;244}245}246}247248249