8269039: Disable SHA-1 Signed JARs
Reviewed-by: weijun
This commit is contained in:
parent
42d5d2abaa
commit
6d91a3eb7b
@ -318,7 +318,8 @@ module java.base {
|
||||
jdk.crypto.ec,
|
||||
jdk.security.auth;
|
||||
exports sun.security.provider.certpath to
|
||||
java.naming;
|
||||
java.naming,
|
||||
jdk.jartool;
|
||||
exports sun.security.rsa to
|
||||
jdk.crypto.cryptoki;
|
||||
exports sun.security.timestamp to
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 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
|
||||
@ -131,7 +131,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||
* certificate
|
||||
* @param constraints the algorithm constraints (or null)
|
||||
* @param date the date specified by the PKIXParameters date, or the
|
||||
* JAR timestamp if jar files are being validated and the
|
||||
* timestamp if JAR files are being validated and the
|
||||
* JAR is timestamped. May be null if no timestamp or
|
||||
* PKIXParameter date is set.
|
||||
* @param variant the Validator variant of the operation. A null value
|
||||
@ -160,17 +160,19 @@ public final class AlgorithmChecker extends PKIXCertPathChecker {
|
||||
|
||||
/**
|
||||
* Create a new {@code AlgorithmChecker} with the given {@code TrustAnchor},
|
||||
* {@code PKIXParameter} date, and {@code varient}
|
||||
* {@code PKIXParameter} date, and {@code variant}.
|
||||
*
|
||||
* @param anchor the trust anchor selected to validate the target
|
||||
* certificate
|
||||
* @param pkixdate Date the constraints are checked against. The value is
|
||||
* either the PKIXParameters date or null for the current date.
|
||||
* @param date the date specified by the PKIXParameters date, or the
|
||||
* timestamp if JAR files are being validated and the
|
||||
* JAR is timestamped. May be null if no timestamp or
|
||||
* PKIXParameter date is set.
|
||||
* @param variant the Validator variant of the operation. A null value
|
||||
* passed will set it to Validator.GENERIC.
|
||||
*/
|
||||
public AlgorithmChecker(TrustAnchor anchor, Date pkixdate, String variant) {
|
||||
this(anchor, certPathDefaultConstraints, pkixdate, variant);
|
||||
public AlgorithmChecker(TrustAnchor anchor, Date date, String variant) {
|
||||
this(anchor, certPathDefaultConstraints, date, variant);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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
|
||||
@ -39,7 +39,7 @@ import sun.security.validator.Validator;
|
||||
* constraints specified in the jdk.certpath.disabledAlgorithms security
|
||||
* property.
|
||||
*/
|
||||
class CertPathConstraintsParameters implements ConstraintsParameters {
|
||||
public class CertPathConstraintsParameters implements ConstraintsParameters {
|
||||
// The public key of the certificate
|
||||
private final Key key;
|
||||
// The certificate's trust anchor which will be checked against the
|
||||
@ -103,7 +103,7 @@ class CertPathConstraintsParameters implements ConstraintsParameters {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("[\n");
|
||||
sb.append("\n Variant: ").append(variant);
|
||||
sb.append(" Variant: ").append(variant);
|
||||
if (anchor != null) {
|
||||
sb.append("\n Anchor: ").append(anchor);
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class PKIX {
|
||||
private Set<TrustAnchor> anchors;
|
||||
private List<X509Certificate> certs;
|
||||
private Timestamp timestamp;
|
||||
private Date timestampDate;
|
||||
private String variant = Validator.VAR_GENERIC;
|
||||
|
||||
ValidatorParams(CertPath cp, PKIXParameters params)
|
||||
@ -154,10 +155,20 @@ class PKIX {
|
||||
stores = params.getCertStores();
|
||||
return stores;
|
||||
}
|
||||
// The date() param is used when enforcing the validity period
|
||||
// of certificates and when checking the time period of revocation data.
|
||||
// The main difference between the date() and timestamp() method is
|
||||
// that the date() method only uses the timestamp (if specified)
|
||||
// for certificates in a code signer's chain.
|
||||
Date date() {
|
||||
if (!gotDate) {
|
||||
// use timestamp if checking signed code that is
|
||||
// timestamped, otherwise use date parameter
|
||||
// Use timestamp if checking signed code that is
|
||||
// timestamped, otherwise use date parameter.
|
||||
// Note that TSA server certificates do not use the
|
||||
// timestamp, which means that an expired TSA certificate
|
||||
// is considered a validation failure. This policy means
|
||||
// that signed and timestamped code is valid until the TSA
|
||||
// certificate expires (assuming all other checks are valid).
|
||||
if (timestamp != null &&
|
||||
variant.equals(Validator.VAR_CODE_SIGNING)) {
|
||||
date = timestamp.getTimestamp();
|
||||
@ -209,6 +220,17 @@ class PKIX {
|
||||
String variant() {
|
||||
return variant;
|
||||
}
|
||||
// The timestamp() param is passed as the date param when creating an
|
||||
// AlgorithmChecker. An AlgorithmChecker always uses the timestamp
|
||||
// if specified in order to enforce the denyAfter constraint.
|
||||
Date timestamp() {
|
||||
// return timestamp date if set, otherwise use date parameter
|
||||
if (timestampDate == null) {
|
||||
timestampDate = (timestamp != null)
|
||||
? timestamp.getTimestamp() : date();
|
||||
}
|
||||
return timestampDate;
|
||||
}
|
||||
}
|
||||
|
||||
static class BuilderParams extends ValidatorParams {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -176,8 +176,8 @@ public final class PKIXCertPathValidator extends CertPathValidatorSpi {
|
||||
List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
|
||||
// add standard checkers that we will be using
|
||||
certPathCheckers.add(untrustedChecker);
|
||||
certPathCheckers.add(new AlgorithmChecker(anchor, null, params.date(),
|
||||
params.variant()));
|
||||
certPathCheckers.add(new AlgorithmChecker(anchor, null,
|
||||
params.timestamp(), params.variant()));
|
||||
certPathCheckers.add(new KeyChecker(certPathLen,
|
||||
params.targetCertConstraints()));
|
||||
certPathCheckers.add(new ConstraintsChecker(certPathLen));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -344,7 +344,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
|
||||
|
||||
// add the algorithm checker
|
||||
checkers.add(new AlgorithmChecker(builder.trustAnchor,
|
||||
buildParams.date(), buildParams.variant()));
|
||||
buildParams.timestamp(), buildParams.variant()));
|
||||
|
||||
BasicChecker basicChecker = null;
|
||||
if (nextState.keyParamsNeeded()) {
|
||||
|
@ -39,7 +39,6 @@ import java.security.spec.InvalidParameterSpecException;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.security.spec.NamedParameterSpec;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@ -688,8 +687,6 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||
*/
|
||||
private static class DenyAfterConstraint extends Constraint {
|
||||
private Date denyAfterDate;
|
||||
private static final SimpleDateFormat dateFormat =
|
||||
new SimpleDateFormat("EEE, MMM d HH:mm:ss z yyyy");
|
||||
|
||||
DenyAfterConstraint(String algo, int year, int month, int day) {
|
||||
Calendar c;
|
||||
@ -723,7 +720,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||
denyAfterDate = c.getTime();
|
||||
if (debug != null) {
|
||||
debug.println("DenyAfterConstraint date set to: " +
|
||||
dateFormat.format(denyAfterDate));
|
||||
denyAfterDate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,8 +751,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
|
||||
throw new CertPathValidatorException(
|
||||
"denyAfter constraint check failed: " + algorithm +
|
||||
" used with Constraint date: " +
|
||||
dateFormat.format(denyAfterDate) + "; params date: " +
|
||||
dateFormat.format(currentDate) + cp.extendedExceptionMsg(),
|
||||
denyAfterDate + "; params date: " +
|
||||
currentDate + cp.extendedExceptionMsg(),
|
||||
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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
|
||||
@ -50,9 +50,9 @@ public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
private boolean anchorIsJdkCASet;
|
||||
// The timestamp of the signed JAR file, if timestamped
|
||||
private Date timestamp;
|
||||
// The keys of the signers
|
||||
// The keys of the signers and TSA
|
||||
private final Set<Key> keys;
|
||||
// The certs in the signers' chains that are issued by the trust anchor
|
||||
// The certs in the signers and TSA chain that are issued by the trust anchor
|
||||
private final Set<X509Certificate> certsIssuedByAnchor;
|
||||
// The extended exception message
|
||||
private String message;
|
||||
@ -73,7 +73,7 @@ public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
// used for checking if the signer's certificate chains back to a
|
||||
// JDK root CA
|
||||
for (CodeSigner signer : signers) {
|
||||
init(signer.getSignerCertPath());
|
||||
addToCertsAndKeys(signer.getSignerCertPath());
|
||||
Timestamp timestamp = signer.getTimestamp();
|
||||
if (timestamp == null) {
|
||||
// this means one of the signers doesn't have a timestamp
|
||||
@ -82,7 +82,7 @@ public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
skipTimestamp = true;
|
||||
} else {
|
||||
// add the key and last cert of TSA too
|
||||
init(timestamp.getSignerCertPath());
|
||||
addToCertsAndKeys(timestamp.getSignerCertPath());
|
||||
if (!skipTimestamp) {
|
||||
Date timestampDate = timestamp.getTimestamp();
|
||||
if (latestTimestamp == null) {
|
||||
@ -98,11 +98,27 @@ public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
this.timestamp = latestTimestamp;
|
||||
}
|
||||
|
||||
// extract last certificate and key from chain
|
||||
private void init(CertPath cp) {
|
||||
public JarConstraintsParameters(List<X509Certificate> chain, Timestamp timestamp) {
|
||||
this.keys = new HashSet<>();
|
||||
this.certsIssuedByAnchor = new HashSet<>();
|
||||
addToCertsAndKeys(chain);
|
||||
if (timestamp != null) {
|
||||
addToCertsAndKeys(timestamp.getSignerCertPath());
|
||||
this.timestamp = timestamp.getTimestamp();
|
||||
} else {
|
||||
this.timestamp = null;
|
||||
}
|
||||
}
|
||||
|
||||
// extract last certificate and signer's public key from chain
|
||||
private void addToCertsAndKeys(CertPath cp) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> chain =
|
||||
(List<X509Certificate>)cp.getCertificates();
|
||||
addToCertsAndKeys(chain);
|
||||
}
|
||||
|
||||
private void addToCertsAndKeys(List<X509Certificate> chain) {
|
||||
if (!chain.isEmpty()) {
|
||||
this.certsIssuedByAnchor.add(chain.get(chain.size() - 1));
|
||||
this.keys.add(chain.get(0).getPublicKey());
|
||||
@ -168,7 +184,7 @@ public class JarConstraintsParameters implements ConstraintsParameters {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("[\n");
|
||||
sb.append("\n Variant: ").append(getVariant());
|
||||
sb.append(" Variant: ").append(getVariant());
|
||||
sb.append("\n Certs Issued by Anchor:");
|
||||
for (X509Certificate cert : certsIssuedByAnchor) {
|
||||
sb.append("\n Cert Issuer: ")
|
||||
|
@ -558,7 +558,7 @@ sun.security.krb5.maxReferrals=5
|
||||
# can be included in the disabledAlgorithms properties. These properties are
|
||||
# to help manage common actions easier across multiple disabledAlgorithm
|
||||
# properties.
|
||||
# There is one defined security property: jdk.disabled.NamedCurves
|
||||
# There is one defined security property: jdk.disabled.namedCurves
|
||||
# See the property for more specific details.
|
||||
#
|
||||
#
|
||||
@ -634,7 +634,8 @@ sun.security.krb5.maxReferrals=5
|
||||
#
|
||||
#
|
||||
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
|
||||
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
|
||||
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
|
||||
SHA1 usage SignedJAR & denyAfter 2019-01-01
|
||||
|
||||
#
|
||||
# Legacy algorithms for certification path (CertPath) processing and
|
||||
@ -698,7 +699,7 @@ jdk.security.legacyAlgorithms=SHA1, \
|
||||
# See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
|
||||
#
|
||||
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
|
||||
DSA keySize < 1024
|
||||
DSA keySize < 1024, SHA1 denyAfter 2019-01-01
|
||||
|
||||
#
|
||||
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
|
||||
|
@ -56,6 +56,7 @@ import jdk.security.jarsigner.JarSigner;
|
||||
import jdk.security.jarsigner.JarSignerException;
|
||||
import sun.security.pkcs.PKCS7;
|
||||
import sun.security.pkcs.SignerInfo;
|
||||
import sun.security.provider.certpath.CertPathConstraintsParameters;
|
||||
import sun.security.timestamp.TimestampToken;
|
||||
import sun.security.tools.KeyStoreUtil;
|
||||
import sun.security.validator.Validator;
|
||||
@ -972,7 +973,8 @@ public class Main {
|
||||
String history;
|
||||
try {
|
||||
SignerInfo si = p7.getSignerInfos()[0];
|
||||
X509Certificate signer = si.getCertificate(p7);
|
||||
ArrayList<X509Certificate> chain = si.getCertificateChain(p7);
|
||||
X509Certificate signer = chain.get(0);
|
||||
String digestAlg = digestMap.get(s);
|
||||
String sigAlg = SignerInfo.makeSigAlg(
|
||||
si.getDigestAlgorithmId(),
|
||||
@ -996,26 +998,31 @@ public class Main {
|
||||
TimeZone.getTimeZone("UTC"),
|
||||
Locale.getDefault(Locale.Category.FORMAT));
|
||||
c.setTime(tsTokenInfo.getDate());
|
||||
JarConstraintsParameters jcp =
|
||||
new JarConstraintsParameters(chain, si.getTimestamp());
|
||||
history = String.format(
|
||||
rb.getString("history.with.ts"),
|
||||
signer.getSubjectX500Principal(),
|
||||
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false),
|
||||
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false),
|
||||
verifyWithWeak(key),
|
||||
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp),
|
||||
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp),
|
||||
verifyWithWeak(key, jcp),
|
||||
c,
|
||||
tsSigner.getSubjectX500Principal(),
|
||||
verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true),
|
||||
verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true),
|
||||
verifyWithWeak(tsKey));
|
||||
verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true, jcp),
|
||||
verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true, jcp),
|
||||
verifyWithWeak(tsKey, jcp));
|
||||
} else {
|
||||
JarConstraintsParameters jcp =
|
||||
new JarConstraintsParameters(chain, null);
|
||||
history = String.format(
|
||||
rb.getString("history.without.ts"),
|
||||
signer.getSubjectX500Principal(),
|
||||
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false),
|
||||
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false),
|
||||
verifyWithWeak(key));
|
||||
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp),
|
||||
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp),
|
||||
verifyWithWeak(key, jcp));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// The only usage of sigNameMap, remember the name
|
||||
// of the block file if it's invalid.
|
||||
history = String.format(
|
||||
@ -1339,56 +1346,67 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
private String verifyWithWeak(String alg, Set<CryptoPrimitive> primitiveSet, boolean tsa) {
|
||||
if (JAR_DISABLED_CHECK.permits(primitiveSet, alg, null)) {
|
||||
if (LEGACY_CHECK.permits(primitiveSet, alg, null)) {
|
||||
return alg;
|
||||
} else {
|
||||
if (primitiveSet == SIG_PRIMITIVE_SET) {
|
||||
legacyAlg |= 2;
|
||||
legacySigAlg = alg;
|
||||
} else {
|
||||
if (tsa) {
|
||||
legacyAlg |= 4;
|
||||
legacyTsaDigestAlg = alg;
|
||||
} else {
|
||||
legacyAlg |= 1;
|
||||
legacyDigestAlg = alg;
|
||||
}
|
||||
}
|
||||
return String.format(rb.getString("with.weak"), alg);
|
||||
}
|
||||
} else {
|
||||
private String verifyWithWeak(String alg, Set<CryptoPrimitive> primitiveSet,
|
||||
boolean tsa, JarConstraintsParameters jcp) {
|
||||
|
||||
try {
|
||||
JAR_DISABLED_CHECK.permits(alg, jcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
disabledAlgFound = true;
|
||||
return String.format(rb.getString("with.disabled"), alg);
|
||||
}
|
||||
}
|
||||
|
||||
private String verifyWithWeak(PublicKey key) {
|
||||
int kLen = KeyUtil.getKeySize(key);
|
||||
if (JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
if (kLen >= 0) {
|
||||
return String.format(rb.getString("key.bit"), kLen);
|
||||
} else {
|
||||
return rb.getString("unknown.size");
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(alg, jcp);
|
||||
return alg;
|
||||
} catch (CertPathValidatorException e) {
|
||||
if (primitiveSet == SIG_PRIMITIVE_SET) {
|
||||
legacyAlg |= 2;
|
||||
legacySigAlg = alg;
|
||||
} else {
|
||||
weakPublicKey = key;
|
||||
legacyAlg |= 8;
|
||||
return String.format(rb.getString("key.bit.weak"), kLen);
|
||||
if (tsa) {
|
||||
legacyAlg |= 4;
|
||||
legacyTsaDigestAlg = alg;
|
||||
} else {
|
||||
legacyAlg |= 1;
|
||||
legacyDigestAlg = alg;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disabledAlgFound = true;
|
||||
return String.format(rb.getString("key.bit.disabled"), kLen);
|
||||
return String.format(rb.getString("with.weak"), alg);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeakSign(String alg, Set<CryptoPrimitive> primitiveSet, boolean tsa) {
|
||||
if (JAR_DISABLED_CHECK.permits(primitiveSet, alg, null)) {
|
||||
if (!LEGACY_CHECK.permits(primitiveSet, alg, null)) {
|
||||
private String verifyWithWeak(PublicKey key, JarConstraintsParameters jcp) {
|
||||
int kLen = KeyUtil.getKeySize(key);
|
||||
try {
|
||||
JAR_DISABLED_CHECK.permits(key.getAlgorithm(), jcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
disabledAlgFound = true;
|
||||
return String.format(rb.getString("key.bit.disabled"), kLen);
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(key.getAlgorithm(), jcp);
|
||||
if (kLen >= 0) {
|
||||
return String.format(rb.getString("key.bit"), kLen);
|
||||
} else {
|
||||
return rb.getString("unknown.size");
|
||||
}
|
||||
} catch (CertPathValidatorException e) {
|
||||
weakPublicKey = key;
|
||||
legacyAlg |= 8;
|
||||
return String.format(rb.getString("key.bit.weak"), kLen);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeakSign(String alg, Set<CryptoPrimitive> primitiveSet,
|
||||
boolean tsa, JarConstraintsParameters jcp) {
|
||||
|
||||
try {
|
||||
JAR_DISABLED_CHECK.permits(alg, jcp);
|
||||
try {
|
||||
LEGACY_CHECK.permits(alg, jcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
if (primitiveSet == SIG_PRIMITIVE_SET) {
|
||||
legacyAlg |= 2;
|
||||
legacyAlg |= 2;
|
||||
} else {
|
||||
if (tsa) {
|
||||
legacyAlg |= 4;
|
||||
@ -1397,7 +1415,7 @@ public class Main {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} catch (CertPathValidatorException e) {
|
||||
if (primitiveSet == SIG_PRIMITIVE_SET) {
|
||||
disabledAlg |= 2;
|
||||
} else {
|
||||
@ -1410,43 +1428,50 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeakSign(PrivateKey key) {
|
||||
if (JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
private void checkWeakSign(PrivateKey key, JarConstraintsParameters jcp) {
|
||||
try {
|
||||
JAR_DISABLED_CHECK.permits(key.getAlgorithm(), jcp);
|
||||
try {
|
||||
LEGACY_CHECK.permits(key.getAlgorithm(), jcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
legacyAlg |= 8;
|
||||
}
|
||||
} else {
|
||||
} catch (CertPathValidatorException e) {
|
||||
disabledAlg |= 8;
|
||||
}
|
||||
}
|
||||
|
||||
private static String checkWeakKey(PublicKey key) {
|
||||
private static String checkWeakKey(PublicKey key, CertPathConstraintsParameters cpcp) {
|
||||
int kLen = KeyUtil.getKeySize(key);
|
||||
if (CERTPATH_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
|
||||
if (kLen >= 0) {
|
||||
return String.format(rb.getString("key.bit"), kLen);
|
||||
} else {
|
||||
return rb.getString("unknown.size");
|
||||
}
|
||||
try {
|
||||
CERTPATH_DISABLED_CHECK.permits(key.getAlgorithm(), cpcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("key.bit.disabled"), kLen);
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(key.getAlgorithm(), cpcp);
|
||||
if (kLen >= 0) {
|
||||
return String.format(rb.getString("key.bit"), kLen);
|
||||
} else {
|
||||
return String.format(rb.getString("key.bit.weak"), kLen);
|
||||
return rb.getString("unknown.size");
|
||||
}
|
||||
} else {
|
||||
return String.format(rb.getString("key.bit.disabled"), kLen);
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("key.bit.weak"), kLen);
|
||||
}
|
||||
}
|
||||
|
||||
private static String checkWeakAlg(String alg) {
|
||||
if (CERTPATH_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
|
||||
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
|
||||
return alg;
|
||||
} else {
|
||||
return String.format(rb.getString("with.weak"), alg);
|
||||
}
|
||||
} else {
|
||||
private static String checkWeakAlg(String alg, CertPathConstraintsParameters cpcp) {
|
||||
try {
|
||||
CERTPATH_DISABLED_CHECK.permits(alg, cpcp);
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("with.disabled"), alg);
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(alg, cpcp);
|
||||
return alg;
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("with.weak"), alg);
|
||||
}
|
||||
}
|
||||
|
||||
private static MessageFormat validityTimeForm = null;
|
||||
@ -1471,7 +1496,7 @@ public class Main {
|
||||
* @param checkUsage true to check code signer keyUsage
|
||||
*/
|
||||
String printCert(boolean isTsCert, String tab, Certificate c,
|
||||
Date timestamp, boolean checkUsage) throws Exception {
|
||||
Date timestamp, boolean checkUsage, CertPathConstraintsParameters cpcp) throws Exception {
|
||||
|
||||
StringBuilder certStr = new StringBuilder();
|
||||
String space = rb.getString("SPACE");
|
||||
@ -1504,16 +1529,16 @@ public class Main {
|
||||
.append("Signature algorithm: ")
|
||||
.append(sigalg)
|
||||
.append(rb.getString("COMMA"))
|
||||
.append(checkWeakKey(key));
|
||||
.append(checkWeakKey(key, cpcp));
|
||||
|
||||
certStr.append("\n").append(tab).append("[");
|
||||
certStr.append(rb.getString("trusted.certificate"));
|
||||
} else {
|
||||
certStr.append("\n").append(tab)
|
||||
.append("Signature algorithm: ")
|
||||
.append(checkWeakAlg(sigalg))
|
||||
.append(checkWeakAlg(sigalg, cpcp))
|
||||
.append(rb.getString("COMMA"))
|
||||
.append(checkWeakKey(key));
|
||||
.append(checkWeakKey(key, cpcp));
|
||||
|
||||
certStr.append("\n").append(tab).append("[");
|
||||
|
||||
@ -1694,19 +1719,21 @@ public class Main {
|
||||
if (digestalg == null) {
|
||||
digestalg = JarSigner.Builder.getDefaultDigestAlgorithm();
|
||||
}
|
||||
checkWeakSign(digestalg, DIGEST_PRIMITIVE_SET, false);
|
||||
JarConstraintsParameters jcp =
|
||||
new JarConstraintsParameters(Arrays.asList(certChain), null);
|
||||
checkWeakSign(digestalg, DIGEST_PRIMITIVE_SET, false, jcp);
|
||||
|
||||
if (tSADigestAlg == null) {
|
||||
tSADigestAlg = JarSigner.Builder.getDefaultDigestAlgorithm();
|
||||
}
|
||||
checkWeakSign(tSADigestAlg, DIGEST_PRIMITIVE_SET, true);
|
||||
checkWeakSign(tSADigestAlg, DIGEST_PRIMITIVE_SET, true, jcp);
|
||||
|
||||
if (sigalg == null) {
|
||||
sigalg = JarSigner.Builder.getDefaultSignatureAlgorithm(privateKey);
|
||||
}
|
||||
checkWeakSign(sigalg, SIG_PRIMITIVE_SET, false);
|
||||
checkWeakSign(sigalg, SIG_PRIMITIVE_SET, false, jcp);
|
||||
|
||||
checkWeakSign(privateKey);
|
||||
checkWeakSign(privateKey, jcp);
|
||||
|
||||
boolean aliasUsed = false;
|
||||
X509Certificate tsaCert = null;
|
||||
@ -1804,8 +1831,10 @@ public class Main {
|
||||
if (tsaUrl != null) {
|
||||
System.out.println(rb.getString("TSA.location.") + tsaUrl);
|
||||
} else if (tsaCert != null) {
|
||||
CertPathConstraintsParameters cpcp =
|
||||
new CertPathConstraintsParameters(tsaCert, Validator.VAR_TSA_SERVER, null, null);
|
||||
System.out.println(rb.getString("TSA.certificate.") +
|
||||
printCert(true, "", tsaCert, null, false));
|
||||
printCert(true, "", tsaCert, null, false, cpcp));
|
||||
}
|
||||
}
|
||||
builder.tsa(tsaURI);
|
||||
@ -2015,8 +2044,13 @@ public class Main {
|
||||
boolean first = true;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(tab1).append(rb.getString("...Signer")).append('\n');
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> chain = (List<X509Certificate>)certs;
|
||||
TrustAnchor anchor = findTrustAnchor(chain);
|
||||
for (Certificate c : certs) {
|
||||
sb.append(printCert(false, tab2, c, timestamp, first));
|
||||
CertPathConstraintsParameters cpcp =
|
||||
new CertPathConstraintsParameters((X509Certificate)c, Validator.VAR_CODE_SIGNING, anchor, timestamp);
|
||||
sb.append(printCert(false, tab2, c, timestamp, first, cpcp));
|
||||
sb.append('\n');
|
||||
first = false;
|
||||
}
|
||||
@ -2029,9 +2063,15 @@ public class Main {
|
||||
.append(e.getLocalizedMessage()).append("]\n");
|
||||
}
|
||||
if (ts != null) {
|
||||
List<? extends Certificate> tscerts = ts.getSignerCertPath().getCertificates();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> tschain = (List<X509Certificate>)tscerts;
|
||||
anchor = findTrustAnchor(chain);
|
||||
sb.append(tab1).append(rb.getString("...TSA")).append('\n');
|
||||
for (Certificate c : ts.getSignerCertPath().getCertificates()) {
|
||||
sb.append(printCert(true, tab2, c, null, false));
|
||||
for (Certificate c : tschain) {
|
||||
CertPathConstraintsParameters cpcp =
|
||||
new CertPathConstraintsParameters((X509Certificate)c, Validator.VAR_TSA_SERVER, anchor, timestamp);
|
||||
sb.append(printCert(true, tab2, c, null, false, cpcp));
|
||||
sb.append('\n');
|
||||
}
|
||||
try {
|
||||
@ -2052,6 +2092,15 @@ public class Main {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private TrustAnchor findTrustAnchor(List<X509Certificate> chain) {
|
||||
X509Certificate last = chain.get(chain.size() - 1);
|
||||
Optional<X509Certificate> trusted =
|
||||
trustedCerts.stream()
|
||||
.filter(c -> c.getSubjectX500Principal().equals(last.getIssuerX500Principal()))
|
||||
.findFirst();
|
||||
return trusted.isPresent() ? new TrustAnchor(trusted.get(), null) : null;
|
||||
}
|
||||
|
||||
void loadKeyStore(String keyStoreName, boolean prompt) {
|
||||
|
||||
if (!nullStream && keyStoreName == null) {
|
||||
|
@ -1,94 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2002, 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.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 4504355
|
||||
# @summary problems if signed crypto provider is the most preferred provider
|
||||
#
|
||||
# @run shell Dyn.sh
|
||||
|
||||
# set a few environment variables so that the shell-script can run stand-alone
|
||||
# in the source directory
|
||||
if [ "${TESTSRC}" = "" ] ; then
|
||||
TESTSRC="."
|
||||
fi
|
||||
|
||||
if [ "${TESTCLASSES}" = "" ] ; then
|
||||
TESTCLASSES="."
|
||||
fi
|
||||
|
||||
if [ "${TESTJAVA}" = "" ] ; then
|
||||
echo "TESTJAVA not set. Test cannot execute."
|
||||
echo "FAILED!!!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${COMPILEJAVA}" = "" ]; then
|
||||
COMPILEJAVA="${TESTJAVA}"
|
||||
fi
|
||||
|
||||
# set platform-dependent variables
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Linux )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
Darwin )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
AIX )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
CYGWIN* )
|
||||
PATHSEP=";"
|
||||
FILESEP="/"
|
||||
;;
|
||||
Windows* )
|
||||
PATHSEP=";"
|
||||
FILESEP="\\"
|
||||
;;
|
||||
* )
|
||||
echo "Unrecognized system!"
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
# remove old class files
|
||||
cd ${TESTCLASSES}${FILESEP}
|
||||
rm DynSignedProvFirst.class
|
||||
|
||||
# compile the test program
|
||||
${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
|
||||
-classpath ${TESTSRC}${FILESEP}exp.jar \
|
||||
-d ${TESTCLASSES}${FILESEP} \
|
||||
${TESTSRC}${FILESEP}DynSignedProvFirst.java
|
||||
|
||||
# run the test
|
||||
${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \
|
||||
-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
|
||||
DynSignedProvFirst
|
||||
|
||||
exit $?
|
96
test/jdk/java/security/Security/signedfirst/DynStatic.java
Normal file
96
test/jdk/java/security/Security/signedfirst/DynStatic.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 4504355 4744260
|
||||
* @summary problems if signed crypto provider is the most preferred provider
|
||||
* @modules java.base/sun.security.tools.keytool
|
||||
* jdk.jartool/sun.security.tools.jarsigner
|
||||
* @library /test/lib
|
||||
* @run main/othervm DynStatic
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
|
||||
public class DynStatic {
|
||||
|
||||
private static final String TEST_SRC =
|
||||
Paths.get(System.getProperty("test.src")).toString();
|
||||
private static final Path TEST_CLASSES =
|
||||
Paths.get(System.getProperty("test.classes"));
|
||||
|
||||
private static final Path EXP_SRC_DIR = Paths.get(TEST_SRC, "com");
|
||||
private static final Path EXP_DEST_DIR = Paths.get("build");
|
||||
private static final Path DYN_SRC =
|
||||
Paths.get(TEST_SRC, "DynSignedProvFirst.java");
|
||||
private static final Path STATIC_SRC =
|
||||
Paths.get(TEST_SRC, "StaticSignedProvFirst.java");
|
||||
|
||||
private static final String STATIC_PROPS =
|
||||
Paths.get(TEST_SRC, "Static.props").toString();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Compile the provider
|
||||
CompilerUtils.compile(EXP_SRC_DIR, EXP_DEST_DIR);
|
||||
|
||||
// Create a jar file containing the provider
|
||||
JarUtils.createJarFile(Path.of("exp.jar"), EXP_DEST_DIR, "com");
|
||||
|
||||
// Create a keystore
|
||||
sun.security.tools.keytool.Main.main(
|
||||
("-genkeypair -dname CN=Signer -keystore exp.ks -storepass "
|
||||
+ "changeit -keypass changeit -keyalg rsa").split(" "));
|
||||
|
||||
// Sign jar
|
||||
sun.security.tools.jarsigner.Main.main(
|
||||
"-storepass changeit -keystore exp.ks exp.jar mykey"
|
||||
.split(" "));
|
||||
|
||||
// Compile the DynSignedProvFirst test program
|
||||
CompilerUtils.compile(DYN_SRC, TEST_CLASSES, "-classpath", "exp.jar");
|
||||
|
||||
// Run the DynSignedProvFirst test program
|
||||
ProcessTools.executeTestJvm("-classpath",
|
||||
TEST_CLASSES.toString() + File.pathSeparator + "exp.jar",
|
||||
"DynSignedProvFirst")
|
||||
.shouldContain("test passed");
|
||||
|
||||
// Compile the StaticSignedProvFirst test program
|
||||
CompilerUtils.compile(STATIC_SRC, TEST_CLASSES, "-classpath", "exp.jar");
|
||||
|
||||
// Run the StaticSignedProvFirst test program
|
||||
ProcessTools.executeTestJvm("-classpath",
|
||||
TEST_CLASSES.toString() + File.pathSeparator + "exp.jar",
|
||||
"-Djava.security.properties=file:" + STATIC_PROPS,
|
||||
"StaticSignedProvFirst")
|
||||
.shouldContain("test passed");
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2002, 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.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 4504355 4744260
|
||||
# @summary problems if signed crypto provider is the most preferred provider
|
||||
#
|
||||
# @run shell Static.sh
|
||||
|
||||
# set a few environment variables so that the shell-script can run stand-alone
|
||||
# in the source directory
|
||||
if [ "${TESTSRC}" = "" ] ; then
|
||||
TESTSRC="."
|
||||
fi
|
||||
|
||||
if [ "${TESTCLASSES}" = "" ] ; then
|
||||
TESTCLASSES="."
|
||||
fi
|
||||
|
||||
if [ "${TESTJAVA}" = "" ] ; then
|
||||
echo "TESTJAVA not set. Test cannot execute."
|
||||
echo "FAILED!!!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${COMPILEJAVA}" = "" ]; then
|
||||
COMPILEJAVA="${TESTJAVA}"
|
||||
fi
|
||||
|
||||
# set platform-dependent variables
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Linux )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
Darwin )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
AIX )
|
||||
PATHSEP=":"
|
||||
FILESEP="/"
|
||||
;;
|
||||
CYGWIN* )
|
||||
PATHSEP=";"
|
||||
FILESEP="/"
|
||||
;;
|
||||
Windows* )
|
||||
PATHSEP=";"
|
||||
FILESEP="\\"
|
||||
;;
|
||||
* )
|
||||
echo "Unrecognized system!"
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
# remove old class files
|
||||
cd ${TESTCLASSES}${FILESEP}
|
||||
rm StaticSignedProvFirst.class
|
||||
|
||||
# compile the test program
|
||||
${COMPILEJAVA}${FILESEP}bin${FILESEP}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
|
||||
-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
|
||||
-d ${TESTCLASSES}${FILESEP} \
|
||||
${TESTSRC}${FILESEP}StaticSignedProvFirst.java
|
||||
|
||||
# run the test
|
||||
cd ${TESTSRC}${FILESEP}
|
||||
${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \
|
||||
-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
|
||||
-Djava.security.properties=file:${TESTSRC}${FILESEP}Static.props \
|
||||
StaticSignedProvFirst
|
||||
|
||||
exit $?
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.sun.exp.provider;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
public class EXP extends Provider {
|
||||
|
||||
public EXP() {
|
||||
super("EXP", 0.0d, "Test provider");
|
||||
put("MessageDigest.SHA1", "com.sun.exp.provider.SHA");
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.sun.exp.provider;
|
||||
|
||||
import java.security.MessageDigestSpi;
|
||||
|
||||
public class SHA extends MessageDigestSpi {
|
||||
protected void engineReset() {}
|
||||
protected void engineUpdate(byte input) {}
|
||||
protected void engineUpdate(byte[] input, int offset, int len) {}
|
||||
protected byte[] engineDigest() { return null; }
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -76,7 +76,7 @@ public class CheckSignerCertChain {
|
||||
"-sigalg SHA256withRSA " +
|
||||
"-verbose" +
|
||||
" a.jar e1")
|
||||
.shouldContain("Signature algorithm: SHA1withRSA (weak), 2048-bit key")
|
||||
.shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit key")
|
||||
// For trusted cert, warning should be generated for its weak 1024-bit
|
||||
// key, but not for its SHA1withRSA algorithm.
|
||||
.shouldContain("Signature algorithm: SHA1withRSA, 1024-bit key (weak)")
|
||||
@ -87,7 +87,7 @@ public class CheckSignerCertChain {
|
||||
|
||||
SecurityTools.jarsigner("-verify -certs signeda.jar " +
|
||||
"-keystore caks -storepass changeit -verbose -debug")
|
||||
.shouldContain("Signature algorithm: SHA1withRSA (weak), 2048-bit key")
|
||||
.shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit key")
|
||||
// For trusted cert, warning should be generated for its weak 1024-bit
|
||||
// key, but not for its SHA1withRSA algorithm.
|
||||
.shouldContain("Signature algorithm: SHA1withRSA, 1024-bit key (weak)")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 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
|
||||
@ -51,7 +51,7 @@ public class DiffEnd {
|
||||
String ksArgs = "-keystore " + Path.of(System.getProperty("test.src"))
|
||||
.resolve("JarSigning.keystore") + " -storepass bbbbbb";
|
||||
|
||||
SecurityTools.jarsigner(ksArgs + " -digestalg SHA1 "
|
||||
SecurityTools.jarsigner(ksArgs + " -digestalg SHA-256 "
|
||||
+ "-signedjar diffend.signed.jar diffend.jar c")
|
||||
.shouldHaveExitValue(0);
|
||||
SecurityTools.jarsigner(" -verify " + ksArgs + " -verbose "
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 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
|
||||
@ -51,9 +51,12 @@ public class OldSig {
|
||||
|
||||
String ksArgs = "-keystore " + src.resolve("JarSigning.keystore")
|
||||
+ " -storepass bbbbbb";
|
||||
String propArgs = " -J-Djava.security.properties="
|
||||
+ src.resolve("OldSig.props");
|
||||
SecurityTools.jarsigner(ksArgs + " -digestalg SHA1 B.jar c");
|
||||
SecurityTools.jarsigner("-verify B.jar").shouldHaveExitValue(0);
|
||||
SecurityTools.jarsigner("-verify " + ksArgs + " -verbose B.jar c")
|
||||
SecurityTools.jarsigner("-verify " + ksArgs + propArgs
|
||||
+ " -verbose B.jar c")
|
||||
.stdoutShouldMatch("^smk .* B[.]class$").shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
2
test/jdk/sun/security/tools/jarsigner/OldSig.props
Normal file
2
test/jdk/sun/security/tools/jarsigner/OldSig.props
Normal file
@ -0,0 +1,2 @@
|
||||
# Re-enable SHA-1 since OldSig.java test uses it
|
||||
jdk.jar.disabledAlgorithms=MD2,MD5,RSA keySize < 1024,DSA keySize < 1024
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -25,16 +25,23 @@
|
||||
* @test
|
||||
* @bug 4431684
|
||||
* @summary jar signature certificate key usage check incorrect
|
||||
* @library /test/lib
|
||||
* @run main/othervm Test4431684
|
||||
*/
|
||||
|
||||
import java.util.jar.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import jdk.test.lib.security.SecurityUtils;
|
||||
|
||||
public class Test4431684 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Re-enable SHA1 since JavaApplication1.jar uses it
|
||||
SecurityUtils.removeFromDisabledAlgs("jdk.jar.disabledAlgorithms",
|
||||
List.of("SHA1"));
|
||||
File f = new File(System.getProperty("test.src", "."),
|
||||
"JavaApplication1.jar");
|
||||
JarFile jf = new JarFile(f);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -54,7 +54,8 @@ import sun.security.timestamp.TimestampToken;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289 8172404 8247960 8242068
|
||||
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289 8172404
|
||||
* 8247960 8242068 8269039
|
||||
* @summary checking response of timestamp
|
||||
* @modules java.base/sun.security.pkcs
|
||||
* java.base/sun.security.timestamp
|
||||
@ -134,6 +135,9 @@ public class TimestampCheck {
|
||||
Instant instant = Instant.now();
|
||||
if (path.equals("tsold")) {
|
||||
instant = instant.minus(20, ChronoUnit.DAYS);
|
||||
} else if (path.equals("tsbefore2019")) {
|
||||
// Saturday, August 18, 2018 7:04:58 PM
|
||||
instant = Instant.ofEpochSecond(1534619098l);
|
||||
}
|
||||
respParam.genTime(Date.from(instant));
|
||||
|
||||
@ -213,6 +217,17 @@ public class TimestampCheck {
|
||||
+ "However, the JAR will be valid")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// should not be disabled because timestamped before 2019
|
||||
signVerbose("tsbefore2019", "unsigned.jar", "tsbefore2019.jar", "pre2019signer",
|
||||
"-digestalg", "SHA-1")
|
||||
.shouldHaveExitValue(4);
|
||||
|
||||
verify("tsbefore2019.jar", "-verbose")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldMatch("Digest.*SHA-1.*(weak)")
|
||||
.shouldMatch("signer certificate expired on .*. "
|
||||
+ "However, the JAR will be valid");
|
||||
|
||||
// No timestamp
|
||||
signVerbose(null, "unsigned.jar", "none.jar", "signer")
|
||||
.shouldContain("is not timestamped")
|
||||
@ -286,35 +301,28 @@ public class TimestampCheck {
|
||||
.shouldHaveExitValue(0);
|
||||
checkTimestamp("sha384alg.jar", defaultPolicyId, "SHA-384");
|
||||
|
||||
// Legacy algorithms
|
||||
// Disabled algorithms
|
||||
signVerbose(null, "unsigned.jar", "sha1alg.jar", "signer",
|
||||
"-strict", "-digestalg", "SHA-1")
|
||||
.shouldHaveExitValue(0)
|
||||
"-digestalg", "SHA-1")
|
||||
.shouldHaveExitValue(4)
|
||||
.shouldContain("jar signed")
|
||||
.shouldNotContain("with signer errors")
|
||||
.shouldMatch("SHA-1.*-digestalg.*will be disabled");
|
||||
verify("sha1alg.jar", "-strict")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("jar verified")
|
||||
.shouldNotContain("with signer errors")
|
||||
.shouldContain("SHA-1 digest algorithm is considered a security risk")
|
||||
.shouldContain("This algorithm will be disabled in a future update")
|
||||
.shouldNotContain("is disabled");
|
||||
.shouldContain("with signer errors")
|
||||
.shouldMatch("SHA-1.*-digestalg.*is disabled");
|
||||
verify("sha1alg.jar", "-verbose")
|
||||
.shouldHaveExitValue(16)
|
||||
.shouldContain("treated as unsigned")
|
||||
.shouldMatch("Digest.*SHA-1.*(disabled)");
|
||||
|
||||
sign("sha1tsaalg", "-tsadigestalg", "SHA-1", "-strict")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldHaveExitValue(4)
|
||||
.shouldContain("jar signed")
|
||||
.shouldNotContain("with signer errors")
|
||||
.shouldMatch("SHA-1.*-tsadigestalg.*will be disabled")
|
||||
.shouldNotContain("is disabled");
|
||||
verify("sha1tsaalg.jar", "-strict")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("jar verified")
|
||||
.shouldNotContain("with signer errors")
|
||||
.shouldContain("SHA-1 timestamp digest algorithm is considered a security risk")
|
||||
.shouldNotContain("is disabled");
|
||||
.shouldContain("with signer errors")
|
||||
.shouldMatch("SHA-1.*-tsadigestalg.*is disabled");
|
||||
verify("sha1tsaalg.jar", "-verbose")
|
||||
.shouldHaveExitValue(16)
|
||||
.shouldContain("treated as unsigned")
|
||||
.shouldMatch("Timestamp.*digest.*SHA-1.*(disabled)");
|
||||
|
||||
// Disabled algorithms
|
||||
sign("tsdisabled", "-digestalg", "MD5",
|
||||
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
|
||||
.shouldHaveExitValue(68)
|
||||
@ -371,15 +379,21 @@ public class TimestampCheck {
|
||||
.shouldContain("Signature algorithm: Ed25519")
|
||||
.shouldContain("Signature algorithm: SHA256withDSA");
|
||||
|
||||
// Legacy algorithms
|
||||
// Disabled algorithms
|
||||
sign("tsweak", "-digestalg", "SHA1",
|
||||
"-sigalg", "SHA1withRSA", "-tsadigestalg", "SHA1")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldMatch("SHA1.*-digestalg.*will be disabled")
|
||||
.shouldMatch("SHA1.*-tsadigestalg.*will be disabled")
|
||||
.shouldMatch("SHA1withRSA.*-sigalg.*will be disabled");
|
||||
checkWeak("tsweak.jar");
|
||||
.shouldHaveExitValue(4)
|
||||
.shouldMatch("SHA1.*-digestalg.*is disabled")
|
||||
.shouldMatch("SHA1.*-tsadigestalg.*is disabled")
|
||||
.shouldMatch("SHA1withRSA.*-sigalg.*is disabled");
|
||||
verify("tsweak.jar", "-verbose")
|
||||
.shouldHaveExitValue(16)
|
||||
.shouldContain("treated as unsigned")
|
||||
.shouldMatch("Digest algorithm: .*(disabled)")
|
||||
.shouldMatch("Signature algorithm: .*(disabled)")
|
||||
.shouldMatch("Timestamp digest algorithm: .*(disabled)");
|
||||
|
||||
// Legacy algorithms (1024-bit key)
|
||||
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
@ -388,13 +402,15 @@ public class TimestampCheck {
|
||||
.shouldContain("jar verified")
|
||||
.shouldMatch("Timestamp.*1024.*(weak)");
|
||||
|
||||
// Algorithm used in signing is weak
|
||||
// Algorithm used in signing is disabled
|
||||
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
|
||||
"-digestalg", "SHA1")
|
||||
.shouldContain("-digestalg option is considered a security risk.")
|
||||
.shouldContain("This algorithm will be disabled in a future update.")
|
||||
.shouldHaveExitValue(0);
|
||||
checkHalfWeak("halfWeak.jar");
|
||||
.shouldContain("-digestalg option is considered a security risk and is disabled.")
|
||||
.shouldHaveExitValue(4);
|
||||
verify("halfWeak.jar", "-verbose")
|
||||
.shouldHaveExitValue(16)
|
||||
.shouldContain("treated as unsigned")
|
||||
.shouldMatch("Digest algorithm: .*(disabled)");
|
||||
|
||||
// sign with DSA key
|
||||
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
|
||||
@ -832,6 +848,7 @@ public class TimestampCheck {
|
||||
Files.deleteIfExists(Paths.get("ks"));
|
||||
keytool("-alias signer -genkeypair -ext bc -dname CN=signer");
|
||||
keytool("-alias oldsigner -genkeypair -dname CN=oldsigner");
|
||||
keytool("-alias pre2019signer -genkeypair -dname CN=pre2019signer");
|
||||
keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
|
||||
keytool("-alias eckey -genkeypair -keyalg EC -dname CN=eckey");
|
||||
keytool("-alias psskey -genkeypair -keyalg RSASSA-PSS -dname CN=psskey");
|
||||
@ -841,6 +858,7 @@ public class TimestampCheck {
|
||||
keytool("-alias badku -genkeypair -dname CN=badku");
|
||||
keytool("-alias ts -genkeypair -dname CN=ts");
|
||||
keytool("-alias tsold -genkeypair -dname CN=tsold");
|
||||
keytool("-alias tsbefore2019 -genkeypair -dname CN=tsbefore2019");
|
||||
keytool("-alias tsweak -genkeypair -keysize 1024 -dname CN=tsweak");
|
||||
keytool("-alias tsdisabled -genkeypair -keysize 512 -dname CN=tsdisabled");
|
||||
keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
|
||||
@ -864,6 +882,7 @@ public class TimestampCheck {
|
||||
|
||||
gencert("signer");
|
||||
gencert("oldsigner", "-startdate -30d -validity 20");
|
||||
gencert("pre2019signer", "-startdate 2018/06/01 -validity 365");
|
||||
gencert("dsakey");
|
||||
gencert("eckey");
|
||||
gencert("psskey");
|
||||
@ -900,6 +919,7 @@ public class TimestampCheck {
|
||||
}
|
||||
|
||||
gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
|
||||
gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 3000");
|
||||
|
||||
gencert("tsweak", "-ext eku:critical=ts");
|
||||
gencert("tsdisabled", "-ext eku:critical=ts");
|
||||
|
@ -61,11 +61,18 @@ public final class SecurityUtils {
|
||||
List.<String>of(protocols));
|
||||
}
|
||||
|
||||
private static void removeFromDisabledAlgs(String prop, List<String> algs) {
|
||||
/**
|
||||
* Removes constraints that contain the specified constraint from the
|
||||
* specified security property. For example, List.of("SHA1") will remove
|
||||
* any constraint containing "SHA1".
|
||||
*/
|
||||
public static void removeFromDisabledAlgs(String prop,
|
||||
List<String> constraints) {
|
||||
String value = Security.getProperty(prop);
|
||||
value = Arrays.stream(value.split(","))
|
||||
.map(s -> s.trim())
|
||||
.filter(s -> !algs.contains(s))
|
||||
.filter(s -> constraints.stream()
|
||||
.allMatch(constraint -> !s.contains(constraint)))
|
||||
.collect(Collectors.joining(","));
|
||||
Security.setProperty(prop, value);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user