diff --git a/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index 3ed82afaab840..4a79c3a3f51e7 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -74,10 +74,10 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { private static final Debug debug = Debug.getInstance("certpath"); private final AlgorithmConstraints constraints; - private final PublicKey trustedPubKey; private final Date date; - private PublicKey prevPubKey; private final String variant; + private PublicKey trustedPubKey; + private PublicKey prevPubKey; private TrustAnchor anchor; private static final Set SIGNATURE_PRIMITIVE_SET = @@ -90,10 +90,6 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { CryptoPrimitive.PUBLIC_KEY_ENCRYPTION, CryptoPrimitive.KEY_AGREEMENT)); - private static final DisabledAlgorithmConstraints - certPathDefaultConstraints = - DisabledAlgorithmConstraints.certPathConstraints(); - /** * Create a new {@code AlgorithmChecker} with the given * {@code TrustAnchor} and {@code String} variant. @@ -104,7 +100,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { * passed will set it to Validator.GENERIC. */ public AlgorithmChecker(TrustAnchor anchor, String variant) { - this(anchor, certPathDefaultConstraints, null, variant); + this(anchor, null, null, variant); } /** @@ -141,19 +137,11 @@ public AlgorithmChecker(TrustAnchor anchor, AlgorithmConstraints constraints, Date date, String variant) { if (anchor != null) { - if (anchor.getTrustedCert() != null) { - this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); - } else { - this.trustedPubKey = anchor.getCAPublicKey(); - } - this.anchor = anchor; - } else { - this.trustedPubKey = null; + setTrustAnchorAndKeys(anchor); } - this.prevPubKey = this.trustedPubKey; - this.constraints = (constraints == null ? certPathDefaultConstraints : - constraints); + this.constraints = constraints == null ? + DisabledAlgorithmConstraints.certPathConstraints() : constraints; this.date = date; this.variant = (variant == null ? Validator.VAR_GENERIC : variant); } @@ -172,18 +160,14 @@ public AlgorithmChecker(TrustAnchor anchor, * passed will set it to Validator.GENERIC. */ public AlgorithmChecker(TrustAnchor anchor, Date date, String variant) { - this(anchor, certPathDefaultConstraints, date, variant); + this(anchor, null, date, variant); } @Override public void init(boolean forward) throws CertPathValidatorException { // Note that this class does not support forward mode. if (!forward) { - if (trustedPubKey != null) { - prevPubKey = trustedPubKey; - } else { - prevPubKey = null; - } + prevPubKey = trustedPubKey; } else { throw new CertPathValidatorException("forward checking not supported"); @@ -207,8 +191,8 @@ public void check(Certificate cert, Collection unresolvedCritExts) throws CertPathValidatorException { - if (!(cert instanceof X509Certificate) || constraints == null) { - // ignore the check for non-x.509 certificate or null constraints + if (!(cert instanceof X509Certificate)) { + // ignore the check for non-x.509 certificate return; } @@ -233,115 +217,114 @@ public void check(Certificate cert, PublicKey currPubKey = cert.getPublicKey(); String currSigAlg = x509Cert.getSigAlgName(); - // Check the signature algorithm and parameters against constraints. - if (!constraints.permits(SIGNATURE_PRIMITIVE_SET, currSigAlg, - currSigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on signature " + - "algorithm: " + currSigAlg, null, null, -1, - BasicReason.ALGORITHM_CONSTRAINED); - } - - // Assume all key usage bits are set if key usage is not present - Set primitives = KU_PRIMITIVE_SET; - - if (keyUsage != null) { - primitives = EnumSet.noneOf(CryptoPrimitive.class); - - if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) { - // keyUsage[0]: KeyUsage.digitalSignature - // keyUsage[1]: KeyUsage.nonRepudiation - // keyUsage[5]: KeyUsage.keyCertSign - // keyUsage[6]: KeyUsage.cRLSign - primitives.add(CryptoPrimitive.SIGNATURE); - } - - if (keyUsage[2]) { // KeyUsage.keyEncipherment - primitives.add(CryptoPrimitive.KEY_ENCAPSULATION); - } - - if (keyUsage[3]) { // KeyUsage.dataEncipherment - primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION); - } - - if (keyUsage[4]) { // KeyUsage.keyAgreement - primitives.add(CryptoPrimitive.KEY_AGREEMENT); - } - - // KeyUsage.encipherOnly and KeyUsage.decipherOnly are - // undefined in the absence of the keyAgreement bit. - - if (primitives.isEmpty()) { - throw new CertPathValidatorException( - "incorrect KeyUsage extension bits", - null, null, -1, PKIXReason.INVALID_KEY_USAGE); + if (constraints instanceof DisabledAlgorithmConstraints) { + DisabledAlgorithmConstraints dac = + (DisabledAlgorithmConstraints)constraints; + if (prevPubKey != null && prevPubKey == trustedPubKey) { + // check constraints of trusted public key (make sure + // algorithm and size is not restricted) + CertPathConstraintsParameters cp = + new CertPathConstraintsParameters(trustedPubKey, variant, + anchor, date); + dac.permits(trustedPubKey.getAlgorithm(), cp); } - } - - ConstraintsParameters cp = - new CertPathConstraintsParameters(x509Cert, variant, + // Check the signature algorithm and parameters against constraints + CertPathConstraintsParameters cp = + new CertPathConstraintsParameters(x509Cert, variant, anchor, date); - - // Check against local constraints if it is DisabledAlgorithmConstraints - if (constraints instanceof DisabledAlgorithmConstraints) { - ((DisabledAlgorithmConstraints)constraints).permits(currSigAlg, - currSigAlgParams, cp); - // DisabledAlgorithmsConstraints does not check primitives, so key - // additional key check. - + dac.permits(currSigAlg, currSigAlgParams, cp); } else { - // Perform the default constraints checking anyway. - certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp); - // Call locally set constraints to check key with primitives. - if (!constraints.permits(primitives, currPubKey)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on key " + - currPubKey.getAlgorithm() + " with size of " + - sun.security.util.KeyUtil.getKeySize(currPubKey) + - "bits", + if (prevPubKey != null) { + if (!constraints.permits(SIGNATURE_PRIMITIVE_SET, + currSigAlg, prevPubKey, currSigAlgParams)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on " + + currSigAlg + "signature and " + + currPubKey.getAlgorithm() + " key with size of " + + sun.security.util.KeyUtil.getKeySize(currPubKey) + + "bits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + } else { + if (!constraints.permits(SIGNATURE_PRIMITIVE_SET, + currSigAlg, currSigAlgParams)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on " + + "signature algorithm: " + currSigAlg, null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } } - } - - // If there is no previous key, set one and exit - if (prevPubKey == null) { - prevPubKey = currPubKey; - return; - } + // Assume all key usage bits are set if key usage is not present + Set primitives = KU_PRIMITIVE_SET; - // Check with previous cert for signature algorithm and public key - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, prevPubKey, currSigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed on " + - "signature algorithm: " + currSigAlg, - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } + if (keyUsage != null) { + primitives = EnumSet.noneOf(CryptoPrimitive.class); - // Inherit key parameters from previous key - if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { - // Inherit DSA parameters from previous key - if (!(prevPubKey instanceof DSAPublicKey)) { - throw new CertPathValidatorException("Input key is not " + - "of a appropriate type for inheriting parameters"); + if (keyUsage[0] || keyUsage[1] || keyUsage[5] || keyUsage[6]) { + // keyUsage[0]: KeyUsage.digitalSignature + // keyUsage[1]: KeyUsage.nonRepudiation + // keyUsage[5]: KeyUsage.keyCertSign + // keyUsage[6]: KeyUsage.cRLSign + primitives.add(CryptoPrimitive.SIGNATURE); + } + + if (keyUsage[2]) { // KeyUsage.keyEncipherment + primitives.add(CryptoPrimitive.KEY_ENCAPSULATION); + } + + if (keyUsage[3]) { // KeyUsage.dataEncipherment + primitives.add(CryptoPrimitive.PUBLIC_KEY_ENCRYPTION); + } + + if (keyUsage[4]) { // KeyUsage.keyAgreement + primitives.add(CryptoPrimitive.KEY_AGREEMENT); + } + + // KeyUsage.encipherOnly and KeyUsage.decipherOnly are + // undefined in the absence of the keyAgreement bit. + + if (primitives.isEmpty()) { + throw new CertPathValidatorException( + "incorrect KeyUsage extension bits", + null, null, -1, PKIXReason.INVALID_KEY_USAGE); + } } - - DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); - if (params == null) { + if (!constraints.permits(primitives, currPubKey)) { throw new CertPathValidatorException( - "Key parameters missing from public key."); + "Algorithm constraints check failed on " + + currPubKey.getAlgorithm() + " key with size of " + + sun.security.util.KeyUtil.getKeySize(currPubKey) + + "bits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } + } - try { - BigInteger y = ((DSAPublicKey)currPubKey).getY(); - KeyFactory kf = KeyFactory.getInstance("DSA"); - DSAPublicKeySpec ks = new DSAPublicKeySpec(y, params.getP(), - params.getQ(), params.getG()); - currPubKey = kf.generatePublic(ks); - } catch (GeneralSecurityException e) { - throw new CertPathValidatorException("Unable to generate " + - "key with inherited parameters: " + e.getMessage(), e); + if (prevPubKey != null) { + // Inherit key parameters from previous key + if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { + // Inherit DSA parameters from previous key + if (!(prevPubKey instanceof DSAPublicKey)) { + throw new CertPathValidatorException("Input key is not " + + "of a appropriate type for inheriting parameters"); + } + + DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); + if (params == null) { + throw new CertPathValidatorException( + "Key parameters missing from public key."); + } + + try { + BigInteger y = ((DSAPublicKey)currPubKey).getY(); + KeyFactory kf = KeyFactory.getInstance("DSA"); + DSAPublicKeySpec ks = new DSAPublicKeySpec(y, params.getP(), + params.getQ(), params.getG()); + currPubKey = kf.generatePublic(ks); + } catch (GeneralSecurityException e) { + throw new CertPathValidatorException("Unable to generate " + + "key with inherited parameters: " + + e.getMessage(), e); + } } } @@ -349,6 +332,20 @@ public void check(Certificate cert, prevPubKey = currPubKey; } + /** + * Sets the anchor, trustedPubKey and prevPubKey fields based on the + * specified trust anchor. + */ + private void setTrustAnchorAndKeys(TrustAnchor anchor) { + if (anchor.getTrustedCert() != null) { + this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); + } else { + this.trustedPubKey = anchor.getCAPublicKey(); + } + this.anchor = anchor; + this.prevPubKey = this.trustedPubKey; + } + /** * Try to set the trust anchor of the checker. *

@@ -359,21 +356,9 @@ public void check(Certificate cert, * certificate */ void trySetTrustAnchor(TrustAnchor anchor) { - // Don't bother if the check has started or trust anchor has already - // specified. - if (prevPubKey == null) { - if (anchor == null) { - throw new IllegalArgumentException( - "The trust anchor cannot be null"); - } - - // Don't bother to change the trustedPubKey. - if (anchor.getTrustedCert() != null) { - prevPubKey = anchor.getTrustedCert().getPublicKey(); - } else { - prevPubKey = anchor.getCAPublicKey(); - } - this.anchor = anchor; + // Only set if trust anchor has not already been set. + if (this.trustedPubKey == null) { + setTrustAnchorAndKeys(anchor); } } @@ -412,9 +397,9 @@ static void check(PublicKey key, X509CRL crl, String variant, static void check(PublicKey key, AlgorithmId algorithmId, String variant, TrustAnchor anchor) throws CertPathValidatorException { - certPathDefaultConstraints.permits(algorithmId.getName(), - algorithmId.getParameters(), - new CertPathConstraintsParameters(key, variant, anchor)); + DisabledAlgorithmConstraints.certPathConstraints().permits( + algorithmId.getName(), algorithmId.getParameters(), + new CertPathConstraintsParameters(key, variant, anchor, null)); } } diff --git a/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java b/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java index dacbd12737a62..679e865745147 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/CertPathConstraintsParameters.java @@ -50,8 +50,8 @@ public class CertPathConstraintsParameters implements ConstraintsParameters { private final Date date; // The variant or usage of this certificate private final String variant; - // The certificate being checked (may be null if a CRL or OCSPResponse is - // being checked) + // The certificate being checked (may be null if a raw public key, a CRL + // or an OCSPResponse is being checked) private final X509Certificate cert; public CertPathConstraintsParameters(X509Certificate cert, @@ -60,8 +60,8 @@ public CertPathConstraintsParameters(X509Certificate cert, } public CertPathConstraintsParameters(Key key, String variant, - TrustAnchor anchor) { - this(key, variant, anchor, null, null); + TrustAnchor anchor, Date date) { + this(key, variant, anchor, date, null); } private CertPathConstraintsParameters(Key key, String variant, diff --git a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index de3923bb3bc1f..0454d84ac4658 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java @@ -176,8 +176,8 @@ private static PKIXCertPathValidatorResult validate(TrustAnchor anchor, List certPathCheckers = new ArrayList<>(); // add standard checkers that we will be using certPathCheckers.add(untrustedChecker); - certPathCheckers.add(new AlgorithmChecker(anchor, null, - params.timestamp(), params.variant())); + certPathCheckers.add(new AlgorithmChecker(anchor, params.timestamp(), + params.variant())); certPathCheckers.add(new KeyChecker(certPathLen, params.targetCertConstraints())); certPathCheckers.add(new ConstraintsChecker(certPathLen)); diff --git a/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java b/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java index ee97d461ac127..69eaa22aafb04 100644 --- a/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java +++ b/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -26,6 +26,8 @@ package sun.security.util; import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.Arrays; import java.util.Collection; @@ -40,6 +42,14 @@ public class AlgorithmDecomposer { private static final Pattern PATTERN = Pattern.compile("with|and|(? DECOMPOSED_DIGEST_NAMES = + Map.of("SHA-1", "SHA1", "SHA-224", "SHA224", "SHA-256", "SHA256", + "SHA-384", "SHA384", "SHA-512", "SHA512", "SHA-512/224", + "SHA512/224", "SHA-512/256", "SHA512/256"); + private static Set decomposeImpl(String algorithm) { Set elements = new HashSet<>(); @@ -93,44 +103,19 @@ public Set decompose(String algorithm) { // signature algorithm "SHA256withRSA". So we need to check both // "SHA-256" and "SHA256" to make the right constraint checking. - // handle special name: SHA-1 and SHA1 - if (elements.contains("SHA1") && !elements.contains("SHA-1")) { - elements.add("SHA-1"); - } - if (elements.contains("SHA-1") && !elements.contains("SHA1")) { - elements.add("SHA1"); + // no need to check further if algorithm doesn't contain "SHA" + if (!algorithm.contains("SHA")) { + return elements; } - // handle special name: SHA-224 and SHA224 - if (elements.contains("SHA224") && !elements.contains("SHA-224")) { - elements.add("SHA-224"); - } - if (elements.contains("SHA-224") && !elements.contains("SHA224")) { - elements.add("SHA224"); - } - - // handle special name: SHA-256 and SHA256 - if (elements.contains("SHA256") && !elements.contains("SHA-256")) { - elements.add("SHA-256"); - } - if (elements.contains("SHA-256") && !elements.contains("SHA256")) { - elements.add("SHA256"); - } - - // handle special name: SHA-384 and SHA384 - if (elements.contains("SHA384") && !elements.contains("SHA-384")) { - elements.add("SHA-384"); - } - if (elements.contains("SHA-384") && !elements.contains("SHA384")) { - elements.add("SHA384"); - } - - // handle special name: SHA-512 and SHA512 - if (elements.contains("SHA512") && !elements.contains("SHA-512")) { - elements.add("SHA-512"); - } - if (elements.contains("SHA-512") && !elements.contains("SHA512")) { - elements.add("SHA512"); + for (Map.Entry e : DECOMPOSED_DIGEST_NAMES.entrySet()) { + if (elements.contains(e.getValue()) && + !elements.contains(e.getKey())) { + elements.add(e.getKey()); + } else if (elements.contains(e.getKey()) && + !elements.contains(e.getValue())) { + elements.add(e.getValue()); + } } return elements; @@ -153,40 +138,44 @@ public static Collection getAliases(String algorithm) { return Arrays.asList(aliases); } - private static void hasLoop(Set elements, String find, String replace) { - if (elements.contains(find)) { - if (!elements.contains(replace)) { - elements.add(replace); - } - elements.remove(find); - } - } - - /* - * This decomposes a standard name into sub-elements with a consistent - * message digest algorithm name to avoid overly complicated checking. + /** + * Decomposes a standard algorithm name into sub-elements and uses a + * consistent message digest algorithm name to avoid overly complicated + * checking. */ - public static Set decomposeOneHash(String algorithm) { + static Set decomposeName(String algorithm) { if (algorithm == null || algorithm.isEmpty()) { return new HashSet<>(); } Set elements = decomposeImpl(algorithm); - hasLoop(elements, "SHA-1", "SHA1"); - hasLoop(elements, "SHA-224", "SHA224"); - hasLoop(elements, "SHA-256", "SHA256"); - hasLoop(elements, "SHA-384", "SHA384"); - hasLoop(elements, "SHA-512", "SHA512"); + // no need to check further if algorithm doesn't contain "SHA" + if (!algorithm.contains("SHA")) { + return elements; + } + + for (Map.Entry e : DECOMPOSED_DIGEST_NAMES.entrySet()) { + if (elements.contains(e.getKey())) { + if (!elements.contains(e.getValue())) { + elements.add(e.getValue()); + } + elements.remove(e.getKey()); + } + } return elements; } - /* - * The provided message digest algorithm name will return a consistent - * naming scheme. + /** + * Decomposes a standard message digest algorithm name into a consistent + * name for matching purposes. + * + * @param algorithm the name to be decomposed + * @return the decomposed name, or the passed in algorithm name if + * it is not a digest algorithm or does not need to be decomposed */ - public static String hashName(String algorithm) { - return algorithm.replace("-", ""); + static String decomposeDigestName(String algorithm) { + return DECOMPOSED_DIGEST_NAMES.getOrDefault(algorithm, algorithm); } } diff --git a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index c56f9b60b7501..2bf39bfae6f46 100644 --- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -304,10 +304,6 @@ private boolean checkConstraints(Set primitives, /** * Key and Certificate Constraints * - * The complete disabling of an algorithm is not handled by Constraints or - * Constraint classes. That is addressed with - * permit(Set, String, AlgorithmParameters) - * * When passing a Key to permit(), the boolean return values follow the * same as the interface class AlgorithmConstraints.permit(). This is to * maintain compatibility: @@ -318,7 +314,6 @@ private boolean checkConstraints(Set primitives, * will be thrown on a failure to better identify why the operation was * disallowed. */ - private static class Constraints { private Map> constraintsMap = new HashMap<>(); @@ -341,9 +336,9 @@ public Constraints(String propertyName, Set constraintSet) { // Check if constraint is a complete disabling of an // algorithm or has conditions. int space = constraintEntry.indexOf(' '); - String algorithm = AlgorithmDecomposer.hashName( - ((space > 0 ? constraintEntry.substring(0, space) : - constraintEntry))); + String algorithm = AlgorithmDecomposer.decomposeDigestName( + space > 0 ? constraintEntry.substring(0, space) : + constraintEntry); List constraintList = constraintsMap.getOrDefault( algorithm.toUpperCase(Locale.ENGLISH), @@ -497,7 +492,7 @@ public void permits(String algorithm, ConstraintsParameters cp) // Get all signature algorithms to check for constraints Set algorithms = new HashSet<>(); if (algorithm != null) { - algorithms.addAll(AlgorithmDecomposer.decomposeOneHash(algorithm)); + algorithms.addAll(AlgorithmDecomposer.decomposeName(algorithm)); algorithms.add(algorithm); } diff --git a/test/jdk/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java b/test/jdk/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java index 6d705000e862c..463dd2878831a 100644 --- a/test/jdk/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java +++ b/test/jdk/sun/security/ssl/SSLContextImpl/TrustTrustedCert.java @@ -159,9 +159,9 @@ protected void runClientApplication(SSLSocket socket) throws Exception { if (expectFail) { // focus on the CertPathValidatorException Throwable t = e.getCause().getCause(); - if (t == null || !t.toString().contains("MD5withRSA")) { + if (t == null || !t.toString().contains("MD5")) { throw new RuntimeException( - "Expected to see MD5withRSA in exception output", t); + "Expected to see MD5 in exception output", t); } } else { throw e; diff --git a/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java b/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java index 65c3ee6f2ad12..8465f36261ba6 100644 --- a/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java +++ b/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java @@ -129,7 +129,7 @@ public static void main(String[] args) throws Exception { " a.jar ee") .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit key") .shouldContain("Signature algorithm: SHA256withRSA, 2048-bit key") - .shouldContain("Invalid certificate chain: Algorithm constraints check failed on signature algorithm: MD5withRSA") + .shouldContain("Invalid certificate chain: Algorithm constraints check failed on disabled algorithm: MD5 used with certificate: CN=EE") .shouldHaveExitValue(0); kt("-exportcert -alias cacert -rfc -file cacert", "ks"); @@ -139,7 +139,7 @@ public static void main(String[] args) throws Exception { "-keystore caks1 -storepass changeit -verbose -debug") .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit key") .shouldContain("Signature algorithm: SHA256withRSA, 2048-bit key") - .shouldContain("Invalid certificate chain: Algorithm constraints check failed on signature algorithm: MD5withRSA") + .shouldContain("Invalid certificate chain: Algorithm constraints check failed on disabled algorithm: MD5 used with certificate: CN=EE") .shouldHaveExitValue(0); } } diff --git a/test/jdk/sun/security/tools/jarsigner/Warning.java b/test/jdk/sun/security/tools/jarsigner/Warning.java index 47e36999077a8..e7ed287e6eca9 100644 --- a/test/jdk/sun/security/tools/jarsigner/Warning.java +++ b/test/jdk/sun/security/tools/jarsigner/Warning.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -32,7 +32,7 @@ /** * @test - * @bug 8024302 8026037 8130132 + * @bug 8024302 8026037 8130132 8243585 * @summary warnings, errors and -strict * @library /lib/testlibrary /test/lib * @build jdk.test.lib.util.JarUtils @@ -83,7 +83,7 @@ public static void main(String[] args) throws Throwable { issueCert("b", "-sigalg MD5withRSA"); run("jarsigner", "a.jar b") - .shouldMatch("chain is invalid. Reason:.*MD5withRSA"); + .shouldMatch("chain is invalid. Reason:.*MD5.*"); recreateJar(); @@ -175,6 +175,18 @@ public static void main(String[] args) throws Throwable { .shouldHaveExitValue(4) .shouldContain("with signer errors") .shouldMatch("(?s).*Error:.*has expired.*Warning:.*"); + + // Sign jar with Trust Anchor that has a 512 bit key. Make sure + // the error message indicates the key size is restricted. + recreateJar(); + run("keytool", "-delete -alias ca"); + newCert("ca", "-keysize 512", "-validity 365000", "-ext bc:c"); + newCert("d"); + issueCert("d"); + run("jarsigner", "a.jar d") + .shouldContain("chain is invalid. " + + "Reason: Algorithm constraints check failed on " + + "keysize limits: RSA 512 bit key."); } // Creates a new jar without signature