mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8273236: keytool does not accurately warn about algorithms that are disabled but have additional constraints
Reviewed-by: mullan
This commit is contained in:
parent
16e0ad0ad0
commit
c2ee1b33c3
3 changed files with 433 additions and 56 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, 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
|
||||
|
@ -31,10 +31,14 @@ import java.nio.file.Path;
|
|||
import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertPathValidatorException.BasicReason;
|
||||
import java.security.cert.CertStoreException;
|
||||
import java.security.cert.CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.security.cert.TrustAnchor;
|
||||
import java.security.cert.URICertStoreParameters;
|
||||
|
||||
|
||||
|
@ -43,6 +47,8 @@ import java.security.interfaces.EdECKey;
|
|||
import java.security.spec.ECParameterSpec;
|
||||
import java.text.Collator;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.jar.JarEntry;
|
||||
|
@ -60,6 +66,7 @@ import javax.security.auth.x500.X500Principal;
|
|||
import java.util.Base64;
|
||||
|
||||
import sun.security.pkcs12.PKCS12KeyStore;
|
||||
import sun.security.provider.certpath.CertPathConstraintsParameters;
|
||||
import sun.security.util.ECKeySizeParameterSpec;
|
||||
import sun.security.util.KeyUtil;
|
||||
import sun.security.util.NamedCurve;
|
||||
|
@ -83,6 +90,7 @@ import sun.security.tools.KeyStoreUtil;
|
|||
import sun.security.tools.PathList;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.util.Pem;
|
||||
import sun.security.validator.Validator;
|
||||
import sun.security.x509.*;
|
||||
|
||||
import static java.security.KeyStore.*;
|
||||
|
@ -178,6 +186,8 @@ public final class Main {
|
|||
// Warnings on weak algorithms etc
|
||||
private List<String> weakWarnings = new ArrayList<>();
|
||||
|
||||
private Set<X509Certificate> trustedCerts = new HashSet<>();
|
||||
|
||||
private static final DisabledAlgorithmConstraints DISABLED_CHECK =
|
||||
new DisabledAlgorithmConstraints(
|
||||
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
|
||||
|
@ -1118,6 +1128,7 @@ public final class Main {
|
|||
}
|
||||
}
|
||||
|
||||
KeyStore cakstore = buildTrustedCerts();
|
||||
// -trustcacerts can be specified on -importcert, -printcert or -printcrl.
|
||||
// Reset it so that warnings on CA cert will remain for other command.
|
||||
if (command != IMPORTCERT && command != PRINTCERT
|
||||
|
@ -1126,7 +1137,13 @@ public final class Main {
|
|||
}
|
||||
|
||||
if (trustcacerts) {
|
||||
caks = KeyStoreUtil.getCacertsKeyStore();
|
||||
if (cakstore != null) {
|
||||
caks = cakstore;
|
||||
} else {
|
||||
// try to load cacerts again, and let exception propagate
|
||||
// if it cannot be loaded
|
||||
caks = KeyStoreUtil.getCacertsKeyStore();
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the specified command
|
||||
|
@ -1485,7 +1502,9 @@ public final class Main {
|
|||
byte[] rawReq = Pem.decode(new String(sb));
|
||||
PKCS10 req = new PKCS10(rawReq);
|
||||
|
||||
checkWeak(rb.getString("the.certificate.request"), req);
|
||||
CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters(
|
||||
req.getSubjectPublicKeyInfo(), null, null, null);
|
||||
checkWeakConstraint(rb.getString("the.certificate.request"), req, cpcp);
|
||||
|
||||
info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo()));
|
||||
info.set(X509CertInfo.SUBJECT,
|
||||
|
@ -1542,8 +1561,11 @@ public final class Main {
|
|||
}
|
||||
}
|
||||
|
||||
checkWeak(rb.getString("the.issuer"), keyStore.getCertificateChain(alias));
|
||||
checkWeak(rb.getString("the.generated.certificate"), cert);
|
||||
checkWeakConstraint(rb.getString("the.issuer"),
|
||||
keyStore.getCertificateChain(alias));
|
||||
cpcp = buildCertPathConstraint(cert, null);
|
||||
checkWeakConstraint(rb.getString("the.generated.certificate"),
|
||||
cert, cpcp);
|
||||
}
|
||||
|
||||
private void doGenCRL(PrintStream out)
|
||||
|
@ -1592,7 +1614,10 @@ public final class Main {
|
|||
} else {
|
||||
out.write(crl.getEncodedInternal());
|
||||
}
|
||||
checkWeak(rb.getString("the.generated.crl"), crl, privateKey);
|
||||
CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters(
|
||||
privateKey, null, null, null);
|
||||
checkWeakConstraint(rb.getString("the.generated.crl"), crl, privateKey,
|
||||
cpcp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1638,7 +1663,10 @@ public final class Main {
|
|||
request.encodeAndSign(subject, privKey, sigAlgName);
|
||||
request.print(out);
|
||||
|
||||
checkWeak(rb.getString("the.generated.certificate.request"), request);
|
||||
CertPathConstraintsParameters cpcp = new CertPathConstraintsParameters(
|
||||
request.getSubjectPublicKeyInfo(), null, null, null);
|
||||
checkWeakConstraint(rb.getString("the.generated.certificate.request"),
|
||||
request, cpcp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1683,7 +1711,9 @@ public final class Main {
|
|||
throw new Exception(form.format(source));
|
||||
}
|
||||
dumpCert(cert, out);
|
||||
checkWeak(rb.getString("the.certificate"), cert);
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint(cert, null);
|
||||
checkWeakConstraint(rb.getString("the.certificate"), cert, cpcp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2021,7 +2051,8 @@ public final class Main {
|
|||
} else {
|
||||
finalChain = new Certificate[] { newCert };
|
||||
}
|
||||
checkWeak(rb.getString("the.generated.certificate"), finalChain);
|
||||
checkWeakConstraint(rb.getString("the.generated.certificate"),
|
||||
finalChain);
|
||||
keyStore.setKeyEntry(alias, privKey, keyPass, finalChain);
|
||||
}
|
||||
|
||||
|
@ -2114,6 +2145,7 @@ public final class Main {
|
|||
private void doPrintEntry(String label, String alias, PrintStream out)
|
||||
throws Exception
|
||||
{
|
||||
CertPathConstraintsParameters cpcp;
|
||||
if (keyStore.containsAlias(alias) == false) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(rb.getString("Alias.alias.does.not.exist"));
|
||||
|
@ -2170,6 +2202,10 @@ public final class Main {
|
|||
if (verbose || rfc || debug) {
|
||||
out.println(rb.getString
|
||||
("Certificate.chain.length.") + chain.length);
|
||||
|
||||
X509Certificate[] xcerts = convertCerts(chain);
|
||||
List<X509Certificate> certs = Arrays.asList(xcerts);
|
||||
TrustAnchor anchor = findTrustAnchor(certs);
|
||||
for (int i = 0; i < chain.length; i ++) {
|
||||
MessageFormat form = new MessageFormat
|
||||
(rb.getString("Certificate.i.1."));
|
||||
|
@ -2182,14 +2218,26 @@ public final class Main {
|
|||
} else {
|
||||
dumpCert(chain[i], out);
|
||||
}
|
||||
checkWeak(label, chain[i]);
|
||||
|
||||
if (i == 0 &&
|
||||
((X509Certificate)chain[0]).
|
||||
getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint((X509Certificate) chain[i], anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(
|
||||
(X509Certificate)chain[i], null, anchor,
|
||||
null);
|
||||
}
|
||||
|
||||
checkWeakConstraint(label, chain[i], cpcp);
|
||||
}
|
||||
} else {
|
||||
// Print the digest of the user cert only
|
||||
out.println
|
||||
(rb.getString("Certificate.fingerprint.SHA.256.") +
|
||||
getCertFingerPrint("SHA-256", chain[0]));
|
||||
checkWeak(label, chain);
|
||||
checkWeakConstraint(label, chain);
|
||||
}
|
||||
} else {
|
||||
out.println(rb.getString
|
||||
|
@ -2215,7 +2263,8 @@ public final class Main {
|
|||
out.println(rb.getString("Certificate.fingerprint.SHA.256.")
|
||||
+ getCertFingerPrint("SHA-256", cert));
|
||||
}
|
||||
checkWeak(label, cert);
|
||||
cpcp = buildCertPathConstraint((X509Certificate)cert, null);
|
||||
checkWeakConstraint(label, cert, cpcp);
|
||||
} else {
|
||||
out.println(rb.getString("Unknown.Entry.Type"));
|
||||
}
|
||||
|
@ -2442,7 +2491,9 @@ public final class Main {
|
|||
try {
|
||||
Certificate c = srckeystore.getCertificate(alias);
|
||||
if (c != null) {
|
||||
checkWeak("<" + newAlias + ">", c);
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint((X509Certificate)c, null);
|
||||
checkWeakConstraint("<" + newAlias + ">", c, cpcp);
|
||||
}
|
||||
keyStore.setEntry(newAlias, entry, pp);
|
||||
// Place the check so that only successful imports are blocked.
|
||||
|
@ -2639,11 +2690,14 @@ public final class Main {
|
|||
issuer = verifyCRL(caks, crl);
|
||||
if (issuer != null) {
|
||||
signer = caks.getCertificate(issuer);
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint((X509Certificate)signer,
|
||||
null);
|
||||
out.printf(rb.getString(
|
||||
"verified.by.s.in.s.weak"),
|
||||
issuer,
|
||||
"cacerts",
|
||||
withWeak(signer.getPublicKey()));
|
||||
withWeakConstraint(signer.getPublicKey(), cpcp));
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
@ -2651,11 +2705,14 @@ public final class Main {
|
|||
issuer = verifyCRL(keyStore, crl);
|
||||
if (issuer != null) {
|
||||
signer = keyStore.getCertificate(issuer);
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint((X509Certificate)signer,
|
||||
null);
|
||||
out.printf(rb.getString(
|
||||
"verified.by.s.in.s.weak"),
|
||||
issuer,
|
||||
"keystore",
|
||||
withWeak(signer.getPublicKey()));
|
||||
withWeakConstraint(signer.getPublicKey(), cpcp));
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
@ -2672,7 +2729,15 @@ public final class Main {
|
|||
out.println(rb.getString
|
||||
("STARNN"));
|
||||
}
|
||||
checkWeak(rb.getString("the.crl"), crl, signer == null ? null : signer.getPublicKey());
|
||||
|
||||
if (signer != null) {
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint((X509Certificate)signer, null);
|
||||
checkWeakConstraint(rb.getString("the.crl"), crl,
|
||||
signer.getPublicKey(), cpcp);
|
||||
} else {
|
||||
checkWeak(rb.getString("the.crl"), crl, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2718,10 +2783,12 @@ public final class Main {
|
|||
PKCS10 req = new PKCS10(Pem.decode(new String(sb)));
|
||||
|
||||
PublicKey pkey = req.getSubjectPublicKeyInfo();
|
||||
CertPathConstraintsParameters cpcp =
|
||||
new CertPathConstraintsParameters(pkey, null, null, null);
|
||||
out.printf(rb.getString("PKCS.10.with.weak"),
|
||||
req.getSubjectName(),
|
||||
pkey.getFormat(),
|
||||
withWeak(pkey),
|
||||
withWeakConstraint(pkey, cpcp),
|
||||
withWeak(req.getSigAlg()));
|
||||
for (PKCS10Attribute attr: req.getAttributes().getAttributes()) {
|
||||
ObjectIdentifier oid = attr.getAttributeId();
|
||||
|
@ -2745,7 +2812,12 @@ public final class Main {
|
|||
if (debug) {
|
||||
out.println(req); // Just to see more, say, public key length...
|
||||
}
|
||||
checkWeak(rb.getString("the.certificate.request"), req);
|
||||
|
||||
CertPathConstraintsParameters cpcp1 =
|
||||
new CertPathConstraintsParameters(
|
||||
req.getSubjectPublicKeyInfo(), null, null, null);
|
||||
checkWeakConstraint(rb.getString("the.certificate.request"), req,
|
||||
cpcp1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2765,6 +2837,9 @@ public final class Main {
|
|||
throw new Exception(rb.getString("Empty.input"));
|
||||
}
|
||||
Certificate[] certs = c.toArray(new Certificate[c.size()]);
|
||||
X509Certificate[] xcerts = convertCerts(certs);
|
||||
List<X509Certificate> chain = Arrays.asList(xcerts);
|
||||
TrustAnchor anchor = findTrustAnchor(chain);
|
||||
for (int i=0; i<certs.length; i++) {
|
||||
X509Certificate x509Cert = null;
|
||||
try {
|
||||
|
@ -2785,7 +2860,17 @@ public final class Main {
|
|||
if (i < (certs.length-1)) {
|
||||
out.println();
|
||||
}
|
||||
checkWeak(oneInMany(rb.getString("the.certificate"), i, certs.length), x509Cert);
|
||||
CertPathConstraintsParameters cpcp;
|
||||
if (i == 0 &&
|
||||
x509Cert.getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint(x509Cert, anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(x509Cert,
|
||||
null, anchor, null);
|
||||
}
|
||||
checkWeakConstraint(oneInMany(rb.getString("the.certificate"),
|
||||
i, certs.length), x509Cert, cpcp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2901,6 +2986,11 @@ public final class Main {
|
|||
|
||||
List<? extends Certificate> certs
|
||||
= signer.getSignerCertPath().getCertificates();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> chain =
|
||||
(List<X509Certificate>)certs;
|
||||
TrustAnchor anchor = findTrustAnchor(chain);
|
||||
CertPathConstraintsParameters cpcp;
|
||||
int cc = 0;
|
||||
for (Certificate cert: certs) {
|
||||
out.printf(rb.getString("Certificate.d."), ++cc);
|
||||
|
@ -2913,16 +3003,27 @@ public final class Main {
|
|||
printX509Cert(x, out);
|
||||
}
|
||||
out.println();
|
||||
checkWeak(oneInManys(rb.getString(
|
||||
if (cc == 0 && x.getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint(x, anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(
|
||||
x, null, anchor, null);
|
||||
}
|
||||
checkWeakConstraint(oneInManys(rb.getString(
|
||||
"the.certificate"), cc,
|
||||
certs.size(), pos,
|
||||
ss.size()), x);
|
||||
ss.size()), x, cpcp);
|
||||
}
|
||||
Timestamp ts = signer.getTimestamp();
|
||||
if (ts != null) {
|
||||
out.println(rb.getString("Timestamp."));
|
||||
out.println();
|
||||
certs = ts.getSignerCertPath().getCertificates();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> tschain =
|
||||
(List<X509Certificate>)certs;
|
||||
anchor = findTrustAnchor(tschain);
|
||||
cc = 0;
|
||||
for (Certificate cert: certs) {
|
||||
out.printf(rb.getString("Certificate.d."), ++cc);
|
||||
|
@ -2935,10 +3036,18 @@ public final class Main {
|
|||
printX509Cert(x, out);
|
||||
}
|
||||
out.println();
|
||||
checkWeak(oneInManys(rb.getString(
|
||||
if (cc == 0 &&
|
||||
x.getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint(x, anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(
|
||||
x, null, anchor, null);
|
||||
}
|
||||
checkWeakConstraint(oneInManys(rb.getString(
|
||||
"the.tsa.certificate"), cc,
|
||||
certs.size(), pos,
|
||||
ss.size()), x);
|
||||
ss.size()), x, cpcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2968,6 +3077,9 @@ public final class Main {
|
|||
}
|
||||
|
||||
int i = 0;
|
||||
@SuppressWarnings("unchecked")
|
||||
List<X509Certificate> xcerts = (List<X509Certificate>)chain;
|
||||
TrustAnchor anchor = findTrustAnchor(xcerts);
|
||||
for (Certificate cert : chain) {
|
||||
try {
|
||||
if (rfc) {
|
||||
|
@ -2978,7 +3090,17 @@ public final class Main {
|
|||
printX509Cert((X509Certificate)cert, out);
|
||||
out.println();
|
||||
}
|
||||
checkWeak(oneInMany(rb.getString("the.certificate"), i++, chain.size()), cert);
|
||||
X509Certificate x = (X509Certificate)cert;
|
||||
CertPathConstraintsParameters cpcp;
|
||||
if (i == 0 && x.getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint(x, anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(
|
||||
x, null, anchor, null);
|
||||
}
|
||||
checkWeakConstraint(oneInMany(rb.getString(
|
||||
"the.certificate"), i++, chain.size()), x, cpcp);
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
e.printStackTrace();
|
||||
|
@ -3202,8 +3324,11 @@ public final class Main {
|
|||
throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
|
||||
}
|
||||
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint(cert, null);
|
||||
|
||||
if (noprompt) {
|
||||
checkWeak(rb.getString("the.input"), cert);
|
||||
checkWeakConstraint(rb.getString("the.input"), cert, cpcp);
|
||||
keyStore.setCertificateEntry(alias, cert);
|
||||
return true;
|
||||
}
|
||||
|
@ -3223,7 +3348,7 @@ public final class Main {
|
|||
("Certificate.already.exists.in.keystore.under.alias.trustalias."));
|
||||
Object[] source = {trustalias};
|
||||
System.err.println(form.format(source));
|
||||
checkWeak(rb.getString("the.input"), cert);
|
||||
checkWeakConstraint(rb.getString("the.input"), cert, cpcp);
|
||||
printWeakWarnings(true);
|
||||
reply = getYesNoReply
|
||||
(rb.getString("Do.you.still.want.to.add.it.no."));
|
||||
|
@ -3234,7 +3359,7 @@ public final class Main {
|
|||
("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
|
||||
Object[] source = {trustalias};
|
||||
System.err.println(form.format(source));
|
||||
checkWeak(rb.getString("the.input"), cert);
|
||||
checkWeakConstraint(rb.getString("the.input"), cert, cpcp);
|
||||
printWeakWarnings(true);
|
||||
reply = getYesNoReply
|
||||
(rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no."));
|
||||
|
@ -3243,7 +3368,7 @@ public final class Main {
|
|||
// Print the cert and ask user if they really want to add
|
||||
// it to their keystore
|
||||
printX509Cert(cert, System.out);
|
||||
checkWeak(rb.getString("the.input"), cert);
|
||||
checkWeakConstraint(rb.getString("the.input"), cert, cpcp);
|
||||
printWeakWarnings(true);
|
||||
reply = getYesNoReply
|
||||
(rb.getString("Trust.this.certificate.no."));
|
||||
|
@ -3270,7 +3395,7 @@ public final class Main {
|
|||
// Print the cert and ask user if they really want to add it to
|
||||
// their keystore
|
||||
printX509Cert(cert, System.out);
|
||||
checkWeak(rb.getString("the.input"), cert);
|
||||
checkWeakConstraint(rb.getString("the.input"), cert, cpcp);
|
||||
printWeakWarnings(true);
|
||||
reply = getYesNoReply
|
||||
(rb.getString("Trust.this.certificate.no."));
|
||||
|
@ -3410,6 +3535,21 @@ public final class Main {
|
|||
return keyPass;
|
||||
}
|
||||
|
||||
private String withWeakConstraint(String alg,
|
||||
CertPathConstraintsParameters cpcp) {
|
||||
try {
|
||||
DISABLED_CHECK.permits(alg, cpcp, false);
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("with.disabled"), alg);
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(alg, cpcp, false);
|
||||
return alg;
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("with.weak"), alg);
|
||||
}
|
||||
}
|
||||
|
||||
private String withWeak(String alg) {
|
||||
if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
|
||||
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
|
||||
|
@ -3436,22 +3576,25 @@ public final class Main {
|
|||
return result;
|
||||
}
|
||||
|
||||
private String withWeak(Key key) {
|
||||
private String withWeakConstraint(Key key,
|
||||
CertPathConstraintsParameters cpcp) {
|
||||
int kLen = KeyUtil.getKeySize(key);
|
||||
String displayAlg = fullDisplayAlgName(key);
|
||||
if (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, displayAlg);
|
||||
} else {
|
||||
return String.format(rb.getString("unknown.size.1"), displayAlg);
|
||||
}
|
||||
} else {
|
||||
return String.format(rb.getString("key.bit.weak"), kLen, displayAlg);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true);
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("key.bit.disabled"), kLen, displayAlg);
|
||||
}
|
||||
try {
|
||||
LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true);
|
||||
if (kLen >= 0) {
|
||||
return String.format(rb.getString("key.bit"), kLen, displayAlg);
|
||||
} else {
|
||||
return String.format(rb.getString("unknown.size.1"), displayAlg);
|
||||
}
|
||||
} catch (CertPathValidatorException e) {
|
||||
return String.format(rb.getString("key.bit.weak"), kLen, displayAlg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3465,9 +3608,11 @@ public final class Main {
|
|||
(rb.getString(".PATTERN.printX509Cert.with.weak"));
|
||||
PublicKey pkey = cert.getPublicKey();
|
||||
String sigName = cert.getSigAlgName();
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint(cert, null);
|
||||
// No need to warn about sigalg of a trust anchor
|
||||
if (!isTrustedCert(cert)) {
|
||||
sigName = withWeak(sigName);
|
||||
sigName = withWeakConstraint(sigName, cpcp);
|
||||
}
|
||||
Object[] source = {cert.getSubjectX500Principal().toString(),
|
||||
cert.getIssuerX500Principal().toString(),
|
||||
|
@ -3477,7 +3622,7 @@ public final class Main {
|
|||
getCertFingerPrint("SHA-1", cert),
|
||||
getCertFingerPrint("SHA-256", cert),
|
||||
sigName,
|
||||
withWeak(pkey),
|
||||
withWeakConstraint(pkey, cpcp),
|
||||
cert.getVersion()
|
||||
};
|
||||
out.println(form.format(source));
|
||||
|
@ -3801,7 +3946,7 @@ public final class Main {
|
|||
throws Exception
|
||||
{
|
||||
|
||||
checkWeak(rb.getString("reply"), replyCerts);
|
||||
checkWeakConstraint(rb.getString("reply"), replyCerts);
|
||||
|
||||
// order the certs in the reply (bottom-up).
|
||||
// we know that all certs in the reply are of type X.509, because
|
||||
|
@ -3883,11 +4028,14 @@ public final class Main {
|
|||
replyCerts.length);
|
||||
tmpCerts[tmpCerts.length-1] = root.snd;
|
||||
replyCerts = tmpCerts;
|
||||
checkWeak(String.format(fromKeyStore
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint((X509Certificate)root.snd,
|
||||
null);
|
||||
checkWeakConstraint(String.format(fromKeyStore
|
||||
? rb.getString("alias.in.keystore")
|
||||
: rb.getString("alias.in.cacerts"),
|
||||
root.fst),
|
||||
root.snd);
|
||||
root.snd, cpcp);
|
||||
}
|
||||
}
|
||||
return replyCerts;
|
||||
|
@ -3952,7 +4100,9 @@ public final class Main {
|
|||
(X509Certificate) certToVerify),
|
||||
chain, certs)) {
|
||||
for (Pair<String,X509Certificate> p : chain) {
|
||||
checkWeak(p.fst, p.snd);
|
||||
CertPathConstraintsParameters cpcp =
|
||||
buildCertPathConstraint(p.snd, null);
|
||||
checkWeakConstraint(p.fst, p.snd, cpcp);
|
||||
}
|
||||
Certificate[] newChain =
|
||||
new Certificate[chain.size()];
|
||||
|
@ -4748,6 +4898,78 @@ public final class Main {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkWeakConstraint(String label, String sigAlg, Key key,
|
||||
CertPathConstraintsParameters cpcp) throws Exception {
|
||||
if (sigAlg != null) {
|
||||
try {
|
||||
DISABLED_CHECK.permits(sigAlg, cpcp, false);
|
||||
try {
|
||||
LEGACY_CHECK.permits(sigAlg, cpcp, false);
|
||||
} catch (CertPathValidatorException e) {
|
||||
weakWarnings.add(String.format(
|
||||
rb.getString("whose.sigalg.weak"), label, sigAlg));
|
||||
}
|
||||
} catch (CertPathValidatorException e) {
|
||||
String eMessage = e.getMessage();
|
||||
if (eMessage.contains("denyAfter constraint check failed") &&
|
||||
e.getReason() == BasicReason.ALGORITHM_CONSTRAINED) {
|
||||
String startSeparator = "Constraint date: ";
|
||||
int startSepPos = eMessage.indexOf(startSeparator);
|
||||
String endSeparator = "; params date";
|
||||
int endSepPos = eMessage.indexOf(endSeparator);
|
||||
String denyAfterDate = null;
|
||||
try {
|
||||
denyAfterDate = eMessage.substring(startSepPos + startSeparator.length(),
|
||||
endSepPos);
|
||||
} catch (IndexOutOfBoundsException e1) {
|
||||
throw new Exception(rb.getString(
|
||||
"Unable.to.parse.denyAfter.string.in.exception.message"));
|
||||
}
|
||||
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
|
||||
Date dateObj = null;
|
||||
try {
|
||||
dateObj = formatter.parse(denyAfterDate);
|
||||
} catch (ParseException e2) {
|
||||
throw new Exception(rb.getString(
|
||||
"Unable.to.parse.denyAfter.string.in.exception.message"));
|
||||
}
|
||||
formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
denyAfterDate = formatter.format(dateObj);
|
||||
|
||||
weakWarnings.add(String.format(
|
||||
rb.getString("whose.sigalg.usagesignedjar"), label, sigAlg,
|
||||
denyAfterDate));
|
||||
} else {
|
||||
weakWarnings.add(String.format(
|
||||
rb.getString("whose.sigalg.disabled"), label, sigAlg));
|
||||
}
|
||||
if (debug) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key != null) {
|
||||
try {
|
||||
DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true);
|
||||
try {
|
||||
LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true);
|
||||
} catch (CertPathValidatorException e) {
|
||||
weakWarnings.add(String.format(
|
||||
rb.getString("whose.key.weak"), label,
|
||||
String.format(rb.getString("key.bit"),
|
||||
KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
|
||||
}
|
||||
} catch (CertPathValidatorException e) {
|
||||
weakWarnings.add(String.format(
|
||||
rb.getString("whose.key.disabled"), label,
|
||||
String.format(rb.getString("key.bit"),
|
||||
KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeak(String label, String sigAlg, Key key) {
|
||||
if (sigAlg != null) {
|
||||
if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) {
|
||||
|
@ -4774,8 +4996,11 @@ public final class Main {
|
|||
}
|
||||
}
|
||||
|
||||
private void checkWeak(String label, Certificate[] certs)
|
||||
throws KeyStoreException {
|
||||
private void checkWeakConstraint(String label, Certificate[] certs)
|
||||
throws KeyStoreException, Exception {
|
||||
X509Certificate[] xcerts = convertCerts(certs);
|
||||
List<X509Certificate> chain = Arrays.asList(xcerts);
|
||||
TrustAnchor anchor = findTrustAnchor(chain);
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
Certificate cert = certs[i];
|
||||
if (cert instanceof X509Certificate) {
|
||||
|
@ -4784,23 +5009,43 @@ public final class Main {
|
|||
if (certs.length > 1) {
|
||||
fullLabel = oneInMany(label, i, certs.length);
|
||||
}
|
||||
checkWeak(fullLabel, xc);
|
||||
|
||||
CertPathConstraintsParameters cpcp = null;
|
||||
if (i == 0 && xc.getBasicConstraints() == -1) {
|
||||
// this is an EE
|
||||
cpcp = buildCertPathConstraint(xc, anchor);
|
||||
} else {
|
||||
cpcp = new CertPathConstraintsParameters(
|
||||
xc, null, anchor, null);
|
||||
}
|
||||
checkWeakConstraint(fullLabel, xc, cpcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeak(String label, Certificate cert)
|
||||
throws KeyStoreException {
|
||||
private void checkWeakConstraint(String label, Certificate cert,
|
||||
CertPathConstraintsParameters cpcp)
|
||||
throws KeyStoreException, Exception {
|
||||
if (cert instanceof X509Certificate) {
|
||||
X509Certificate xc = (X509Certificate)cert;
|
||||
// No need to check the sigalg of a trust anchor
|
||||
String sigAlg = isTrustedCert(cert) ? null : xc.getSigAlgName();
|
||||
checkWeak(label, sigAlg, xc.getPublicKey());
|
||||
checkWeakConstraint(label, sigAlg, xc.getPublicKey(), cpcp);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeak(String label, PKCS10 p10) {
|
||||
checkWeak(label, p10.getSigAlg(), p10.getSubjectPublicKeyInfo());
|
||||
private void checkWeakConstraint(String label, PKCS10 p10,
|
||||
CertPathConstraintsParameters cpcp) throws Exception {
|
||||
checkWeakConstraint(label, p10.getSigAlg(),
|
||||
p10.getSubjectPublicKeyInfo(), cpcp);
|
||||
}
|
||||
|
||||
private void checkWeakConstraint(String label, CRL crl, Key key,
|
||||
CertPathConstraintsParameters cpcp) throws Exception {
|
||||
if (crl instanceof X509CRLImpl) {
|
||||
X509CRLImpl impl = (X509CRLImpl)crl;
|
||||
checkWeakConstraint(label, impl.getSigAlgName(), key, cpcp);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWeak(String label, CRL crl, Key key) {
|
||||
|
@ -4810,6 +5055,76 @@ public final class Main {
|
|||
}
|
||||
}
|
||||
|
||||
private KeyStore buildTrustedCerts() {
|
||||
KeyStore caks = null;
|
||||
try {
|
||||
caks = KeyStoreUtil.getCacertsKeyStore();
|
||||
if (caks != null) {
|
||||
Enumeration<String> aliases = caks.aliases();
|
||||
while (aliases.hasMoreElements()) {
|
||||
String a = aliases.nextElement();
|
||||
try {
|
||||
trustedCerts.add((X509Certificate)caks.getCertificate(a));
|
||||
} catch (Exception e2) {
|
||||
// ignore, if the keystore has not been loaded/initialized properly
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore, if cacerts cannot be loaded
|
||||
}
|
||||
return caks;
|
||||
}
|
||||
|
||||
private TrustAnchor findTrustAnchor(List<X509Certificate> chain) {
|
||||
if (chain.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private X509Certificate[] convertCerts(Certificate[] certs) {
|
||||
X509Certificate[] xcerts = new X509Certificate[certs.length];
|
||||
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
if (certs[i] instanceof X509Certificate) {
|
||||
xcerts[i] = (X509Certificate) certs[i];
|
||||
}
|
||||
}
|
||||
return xcerts;
|
||||
}
|
||||
|
||||
private CertPathConstraintsParameters buildCertPathConstraint(
|
||||
X509Certificate xcert, TrustAnchor anchor) throws Exception{
|
||||
List<String> eku = xcert.getExtendedKeyUsage();
|
||||
if (eku == null) {
|
||||
return new CertPathConstraintsParameters(xcert, null,
|
||||
anchor, null);
|
||||
}
|
||||
|
||||
if (eku.contains(KnownOIDs.codeSigning.value())) {
|
||||
return new CertPathConstraintsParameters(xcert,
|
||||
Validator.VAR_CODE_SIGNING, anchor, null);
|
||||
} else if (eku.contains(KnownOIDs.clientAuth.value())) {
|
||||
return new CertPathConstraintsParameters(xcert,
|
||||
Validator.VAR_TLS_CLIENT, anchor, null);
|
||||
} else if (eku.contains(KnownOIDs.serverAuth.value())) {
|
||||
return new CertPathConstraintsParameters(xcert,
|
||||
Validator.VAR_TLS_SERVER, anchor, null);
|
||||
} else if (eku.contains(KnownOIDs.KP_TimeStamping.value())) {
|
||||
return new CertPathConstraintsParameters(xcert,
|
||||
Validator.VAR_TSA_SERVER, anchor, null);
|
||||
}
|
||||
return new CertPathConstraintsParameters(xcert, Validator.VAR_GENERIC,
|
||||
anchor, null);
|
||||
}
|
||||
|
||||
private void printWeakWarnings(boolean newLine) {
|
||||
if (!weakWarnings.isEmpty() && !nowarn) {
|
||||
System.err.println("\nWarning:");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue