8269039: Disable SHA-1 Signed JARs

Reviewed-by: weijun
This commit is contained in:
Sean Mullan 2021-09-21 13:45:47 +00:00
parent 42d5d2abaa
commit 6d91a3eb7b
27 changed files with 457 additions and 357 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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 {

View File

@ -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));

View File

@ -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()) {

View File

@ -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);
}
}

View File

@ -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: ")

View File

@ -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

View File

@ -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) {

View File

@ -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 $?

View 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");
}
}

View File

@ -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 $?

View File

@ -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");
}
}

View File

@ -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; }
}

View File

@ -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)")

View File

@ -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 "

View File

@ -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);
}
}

View 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

View File

@ -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);

View File

@ -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");

View File

@ -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);
}