/* * Copyright (c) 2020, 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. * * 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.ArrayList; import java.util.Arrays; import java.util.List; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import jdk.test.lib.SecurityTools; import jdk.test.lib.util.JarUtils; import jdk.test.lib.process.OutputAnalyzer; /** * @test * @bug 8248745 * @summary Test key generation and jar signing with disabled algorithms and * key sizes, with and without entries in jdk.jar.disabledAlgorithms, * jdk.certpath.disabledAlgorithms * @library /test/lib * @run main/othervm RestrictedAlgo RESTRICT * @run main/othervm RestrictedAlgo NO_RESTRICT */ public class RestrictedAlgo { private static final String KEYSTORE = "keystore.jks"; private static final String PASSWORD = "password"; private static final String SIGNED_JARFILE = "signed.jar"; private static final String UNSIGNED_JARFILE = "unsigned.jar"; private static final String SECURITY_FILE = "java.security"; private static final String NO_RESTRICT = "-J-Djava.security.properties=" + SECURITY_FILE; private static final String FIRST_FILE = "first.txt"; private static final String WARNING = "Warning:"; private static final String SECURITY_WARNING = ".* is considered a security risk and is disabled."; private static String algoStatus; public static void main(String[] args) throws Exception { algoStatus = args[0]; // create a jar file that contains one file JarUtils.createJarFile(Path.of(UNSIGNED_JARFILE), Path.of("."), new File(FIRST_FILE).exists() ? Paths.get(FIRST_FILE) : Files.createFile(Paths.get(FIRST_FILE))); if (!isAlgoRestricted()) { // An alternative security properties Files.writeString(Files.createFile(Paths.get(SECURITY_FILE)), "jdk.certpath.disabledAlgorithms=\n" + "jdk.jar.disabledAlgorithms=\n" + "jdk.security.legacyAlgorithms="); } System.out.println("\nTesting sigalg MD2\n"); test("RSA", "MD2withRSA", "SigAlgMD2", "SHA256", true); System.out.println("\nTesting sigalg MD5\n"); test("RSA", "MD5withRSA", "SigAlgMD5", "SHA256", true); System.out.println("\nTesting digestalg MD2\n"); test("RSA", "SHA256withRSA", "DigestAlgMD2", "MD2", false); System.out.println("\nTesting digestalg MD5\n"); test("RSA", "SHA256withRSA", "DigestAlgMD5", "MD5", false); System.out.println("\nTesting RSA Keysize: RSA keySize < 1024\n"); test("RSA", "SHA256withRSA", "KeySizeRSA", "SHA256", true, "-keysize", "512"); System.out.println("\nTesting DSA Keysize: DSA keySize < 1024\n"); test("DSA", "SHA256withDSA", "KeySizeDSA", "SHA256", true, "-keysize", "512"); } private static void test(String keyAlg, String sigAlg, String aliasPrefix, String digestAlg, boolean isKeyToolVerify, String... addKeyToolArgs) throws Exception { String alias = aliasPrefix + "_" + algoStatus; testKeytool(keyAlg, sigAlg, alias, isKeyToolVerify, addKeyToolArgs); testJarSignerSigning(sigAlg, alias, digestAlg); testJarSignerVerification(); } private static void testKeytool(String keyAlg, String sigAlg, String alias, boolean isKeyToolVerify, String... additionalCmdArgs) throws Exception { System.out.println("Testing Keytool\n"); List cmd = prepareCommand( "-genkeypair", "-keystore", KEYSTORE, "-storepass", PASSWORD, "-dname", "CN=Test", "-ext", "bc:c", "-keyalg", keyAlg, "-sigalg", sigAlg, "-alias", alias); for (String additionalCMDArg : additionalCmdArgs) { cmd.add(additionalCMDArg); } OutputAnalyzer analyzer = SecurityTools.keytool(cmd) .shouldHaveExitValue(0); if (isKeyToolVerify) { verifyAnalyzer(analyzer); } } private static void testJarSignerSigning(String sigAlg, String alias, String digestAlg) throws Exception { System.out.println("\nTesting JarSigner Signing\n"); List cmd = prepareCommand( "-keystore", KEYSTORE, "-storepass", PASSWORD, "-sigalg", sigAlg, "-digestalg", digestAlg, "-signedjar", SIGNED_JARFILE, UNSIGNED_JARFILE, alias); OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd) .shouldHaveExitValue(0); verifyAnalyzer(analyzer); } private static void testJarSignerVerification() throws Exception { System.out.println("\nTesting JarSigner Verification\n"); List cmd = prepareCommand( "-verify", SIGNED_JARFILE); OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd) .shouldHaveExitValue(0); if (isAlgoRestricted()) { analyzer.shouldContain("The jar will be treated as unsigned," + " because it is signed with a weak algorithm that " + "is now disabled."); } else { analyzer.shouldContain("jar verified."); } } private static List prepareCommand(String... options) { List cmd = new ArrayList<>(); cmd.addAll(Arrays.asList(options)); if (!isAlgoRestricted()) { cmd.add(NO_RESTRICT); } return cmd; } private static void verifyAnalyzer(OutputAnalyzer analyzer) { if (isAlgoRestricted()) { analyzer.shouldContain(WARNING) .shouldMatch(SECURITY_WARNING); } else { analyzer.shouldNotMatch(SECURITY_WARNING); } } private static boolean isAlgoRestricted() { return ("RESTRICT".equals(algoStatus)) ? true : false; } }