| /* |
| * 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", "SHA-256", true); |
| |
| System.out.println("\nTesting sigalg MD5\n"); |
| test("RSA", "MD5withRSA", "SigAlgMD5", "SHA-256", 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", "SHA-256", true, |
| "-keysize", "512"); |
| |
| System.out.println("\nTesting DSA Keysize: DSA keySize < 1024\n"); |
| test("DSA", "SHA256withDSA", "KeySizeDSA", "SHA-256", true, |
| "-keysize", "512"); |
| |
| System.out.println("\nTesting Native Curve:" |
| + " include jdk.disabled.namedCurves\n"); |
| test("EC", "SHA256withECDSA", "curve", "SHA-256", true, |
| "-groupname", "secp112r1"); |
| } |
| |
| 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<String> cmd = prepareCommand( |
| "-genkeypair", |
| "-keystore", KEYSTORE, |
| "-storepass", PASSWORD, |
| "-dname", "CN=Test", |
| "-ext", "bc:c", |
| "-keyalg", keyAlg, |
| "-sigalg", sigAlg, |
| "-alias", alias, |
| "-J-Djdk.sunec.disableNative=false"); |
| 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<String> cmd = prepareCommand( |
| "-keystore", KEYSTORE, |
| "-storepass", PASSWORD, |
| "-sigalg", sigAlg, |
| "-digestalg", digestAlg, |
| "-signedjar", SIGNED_JARFILE, |
| UNSIGNED_JARFILE, |
| alias, |
| "-J-Djdk.sunec.disableNative=false"); |
| |
| OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd) |
| .shouldHaveExitValue(0); |
| |
| verifyAnalyzer(analyzer); |
| } |
| |
| private static void testJarSignerVerification() |
| throws Exception { |
| |
| System.out.println("\nTesting JarSigner Verification\n"); |
| List<String> cmd = prepareCommand( |
| "-verify", |
| SIGNED_JARFILE, |
| "-J-Djdk.sunec.disableNative=false"); |
| |
| 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<String> prepareCommand(String... options) { |
| List<String> 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; |
| } |
| } |