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

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