Skip to content

Commit 6bc6980

Browse files
committed
8275887: jarsigner prints invalid digest/signature algorithm warnings if keysize is weak/disabled
Reviewed-by: mdoerr Backport-of: 03f8c0fb9363dc1bb07bed1ae0359c029caa0130
1 parent 6f2bbc4 commit 6bc6980

File tree

9 files changed

+90
-87
lines changed

9 files changed

+90
-87
lines changed

src/java.base/share/classes/sun/security/pkcs/SignerInfo.java

+17-11
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ public class SignerInfo implements DerEncoder {
7676
/**
7777
* A map containing the algorithms in this SignerInfo. This is used to
7878
* avoid checking algorithms to see if they are disabled more than once.
79-
* The key is the AlgorithmId of the algorithm, and the value is the name of
80-
* the field or attribute.
79+
* The key is the AlgorithmId of the algorithm, and the value is a record
80+
* containing the name of the field or attribute and whether the key
81+
* should also be checked (ex: if it is a signature algorithm).
8182
*/
82-
private Map<AlgorithmId, String> algorithms = new HashMap<>();
83+
private record AlgorithmInfo(String field, boolean checkKey) {}
84+
private Map<AlgorithmId, AlgorithmInfo> algorithms = new HashMap<>();
8385

8486
public SignerInfo(X500Name issuerName,
8587
BigInteger serial,
@@ -350,7 +352,8 @@ SignerInfo verify(PKCS7 block, byte[] data)
350352
}
351353

352354
String digestAlgName = digestAlgorithmId.getName();
353-
algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
355+
algorithms.put(digestAlgorithmId,
356+
new AlgorithmInfo("SignerInfo digestAlgorithm field", false));
354357

355358
byte[] dataSigned;
356359

@@ -428,7 +431,8 @@ SignerInfo verify(PKCS7 block, byte[] data)
428431
new AlgorithmId(ObjectIdentifier.of(oid),
429432
digestEncryptionAlgorithmId.getParameters());
430433
algorithms.put(sigAlgId,
431-
"SignerInfo digestEncryptionAlgorithm field");
434+
new AlgorithmInfo(
435+
"SignerInfo digestEncryptionAlgorithm field", true));
432436
}
433437

434438
X509Certificate cert = getCertificate(block);
@@ -685,7 +689,8 @@ private void verifyTimestamp(TimestampToken token)
685689
throws NoSuchAlgorithmException, SignatureException {
686690

687691
AlgorithmId digestAlgId = token.getHashAlgorithm();
688-
algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
692+
algorithms.put(digestAlgId,
693+
new AlgorithmInfo("TimestampToken digestAlgorithm field", false));
689694

690695
MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
691696

@@ -742,18 +747,19 @@ public String toString() {
742747
*/
743748
public static Set<String> verifyAlgorithms(SignerInfo[] infos,
744749
JarConstraintsParameters params, String name) throws SignatureException {
745-
Map<AlgorithmId, String> algorithms = new HashMap<>();
750+
Map<AlgorithmId, AlgorithmInfo> algorithms = new HashMap<>();
746751
for (SignerInfo info : infos) {
747752
algorithms.putAll(info.algorithms);
748753
}
749754

750755
Set<String> enabledAlgorithms = new HashSet<>();
751756
try {
752-
for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
753-
params.setExtendedExceptionMsg(name, algorithm.getValue());
754-
AlgorithmId algId = algorithm.getKey();
757+
for (var algEntry : algorithms.entrySet()) {
758+
AlgorithmInfo info = algEntry.getValue();
759+
params.setExtendedExceptionMsg(name, info.field());
760+
AlgorithmId algId = algEntry.getKey();
755761
JAR_DISABLED_CHECK.permits(algId.getName(),
756-
algId.getParameters(), params);
762+
algId.getParameters(), params, info.checkKey());
757763
enabledAlgorithms.add(algId.getName());
758764
}
759765
} catch (CertPathValidatorException e) {

src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java

+3-28
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.security.AlgorithmParameters;
3939
import java.security.GeneralSecurityException;
4040
import java.security.cert.Certificate;
41-
import java.security.cert.X509CRL;
4241
import java.security.cert.X509Certificate;
4342
import java.security.cert.PKIXCertPathChecker;
4443
import java.security.cert.TrustAnchor;
@@ -57,7 +56,6 @@
5756
import sun.security.validator.Validator;
5857
import sun.security.x509.AlgorithmId;
5958
import sun.security.x509.X509CertImpl;
60-
import sun.security.x509.X509CRLImpl;
6159

6260
/**
6361
* A {@code PKIXCertPathChecker} implementation to check whether a
@@ -285,13 +283,13 @@ public void check(Certificate cert,
285283
// Check against local constraints if it is DisabledAlgorithmConstraints
286284
if (constraints instanceof DisabledAlgorithmConstraints) {
287285
((DisabledAlgorithmConstraints)constraints).permits(currSigAlg,
288-
currSigAlgParams, cp);
286+
currSigAlgParams, cp, true);
289287
// DisabledAlgorithmsConstraints does not check primitives, so key
290288
// additional key check.
291289

292290
} else {
293291
// Perform the default constraints checking anyway.
294-
certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp);
292+
certPathDefaultConstraints.permits(currSigAlg, currSigAlgParams, cp, true);
295293
// Call locally set constraints to check key with primitives.
296294
if (!constraints.permits(primitives, currPubKey)) {
297295
throw new CertPathValidatorException(
@@ -377,29 +375,6 @@ void trySetTrustAnchor(TrustAnchor anchor) {
377375
}
378376
}
379377

380-
/**
381-
* Check the signature algorithm with the specified public key.
382-
*
383-
* @param key the public key to verify the CRL signature
384-
* @param crl the target CRL
385-
* @param variant the Validator variant of the operation. A null value
386-
* passed will set it to Validator.GENERIC.
387-
* @param anchor the trust anchor selected to validate the CRL issuer
388-
*/
389-
static void check(PublicKey key, X509CRL crl, String variant,
390-
TrustAnchor anchor) throws CertPathValidatorException {
391-
392-
X509CRLImpl x509CRLImpl = null;
393-
try {
394-
x509CRLImpl = X509CRLImpl.toImpl(crl);
395-
} catch (CRLException ce) {
396-
throw new CertPathValidatorException(ce);
397-
}
398-
399-
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
400-
check(key, algorithmId, variant, anchor);
401-
}
402-
403378
/**
404379
* Check the signature algorithm with the specified public key.
405380
*
@@ -414,7 +389,7 @@ static void check(PublicKey key, AlgorithmId algorithmId, String variant,
414389

415390
certPathDefaultConstraints.permits(algorithmId.getName(),
416391
algorithmId.getParameters(),
417-
new CertPathConstraintsParameters(key, variant, anchor));
392+
new CertPathConstraintsParameters(key, variant, anchor), true);
418393
}
419394
}
420395

src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,8 @@ static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
691691

692692
// check the crl signature algorithm
693693
try {
694-
AlgorithmChecker.check(prevKey, crl, variant, anchor);
694+
AlgorithmChecker.check(prevKey, crlImpl.getSigAlgId(),
695+
variant, anchor);
695696
} catch (CertPathValidatorException cpve) {
696697
if (debug != null) {
697698
debug.println("CRL signature algorithm check failed: " + cpve);

src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java

+25-18
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,16 @@ public final boolean permits(Set<CryptoPrimitive> primitives,
199199
}
200200

201201
public final void permits(String algorithm, AlgorithmParameters ap,
202-
ConstraintsParameters cp) throws CertPathValidatorException {
203-
204-
permits(algorithm, cp);
202+
ConstraintsParameters cp, boolean checkKey)
203+
throws CertPathValidatorException {
204+
permits(algorithm, cp, checkKey);
205205
if (ap != null) {
206206
permits(ap, cp);
207207
}
208208
}
209209

210210
private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
211-
throws CertPathValidatorException {
211+
throws CertPathValidatorException {
212212

213213
switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
214214
case "RSASSA-PSS":
@@ -226,36 +226,38 @@ private void permitsPSSParams(AlgorithmParameters ap,
226226
PSSParameterSpec pssParams =
227227
ap.getParameterSpec(PSSParameterSpec.class);
228228
String digestAlg = pssParams.getDigestAlgorithm();
229-
permits(digestAlg, cp);
229+
permits(digestAlg, cp, false);
230230
AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters();
231231
if (mgfParams instanceof MGF1ParameterSpec) {
232232
String mgfDigestAlg =
233233
((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
234234
if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) {
235-
permits(mgfDigestAlg, cp);
235+
permits(mgfDigestAlg, cp, false);
236236
}
237237
}
238238
} catch (InvalidParameterSpecException ipse) {
239239
// ignore
240240
}
241241
}
242242

243-
public final void permits(String algorithm, ConstraintsParameters cp)
244-
throws CertPathValidatorException {
243+
public final void permits(String algorithm, ConstraintsParameters cp,
244+
boolean checkKey) throws CertPathValidatorException {
245245

246-
// Check if named curves in the key are disabled.
247-
for (Key key : cp.getKeys()) {
248-
for (String curve : getNamedCurveFromKey(key)) {
249-
if (!cachedCheckAlgorithm(curve)) {
250-
throw new CertPathValidatorException(
246+
if (checkKey) {
247+
// Check if named curves in the key are disabled.
248+
for (Key key : cp.getKeys()) {
249+
for (String curve : getNamedCurveFromKey(key)) {
250+
if (!cachedCheckAlgorithm(curve)) {
251+
throw new CertPathValidatorException(
251252
"Algorithm constraints check failed on disabled " +
252253
"algorithm: " + curve,
253254
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
255+
}
254256
}
255257
}
256258
}
257259

258-
algorithmConstraints.permits(algorithm, cp);
260+
algorithmConstraints.permits(algorithm, cp, checkKey);
259261
}
260262

261263
private static List<String> getNamedCurveFromKey(Key key) {
@@ -493,8 +495,8 @@ public boolean permits(String algorithm, AlgorithmParameters aps) {
493495
return true;
494496
}
495497

496-
public void permits(String algorithm, ConstraintsParameters cp)
497-
throws CertPathValidatorException {
498+
public void permits(String algorithm, ConstraintsParameters cp,
499+
boolean checkKey) throws CertPathValidatorException {
498500

499501
if (debug != null) {
500502
debug.println("Constraints.permits(): " + algorithm + ", "
@@ -508,8 +510,10 @@ public void permits(String algorithm, ConstraintsParameters cp)
508510
algorithms.add(algorithm);
509511
}
510512

511-
for (Key key : cp.getKeys()) {
512-
algorithms.add(key.getAlgorithm());
513+
if (checkKey) {
514+
for (Key key : cp.getKeys()) {
515+
algorithms.add(key.getAlgorithm());
516+
}
513517
}
514518

515519
// Check all applicable constraints
@@ -519,6 +523,9 @@ public void permits(String algorithm, ConstraintsParameters cp)
519523
continue;
520524
}
521525
for (Constraint constraint : list) {
526+
if (!checkKey && constraint instanceof KeySizeConstraint) {
527+
continue;
528+
}
522529
constraint.permits(cp);
523530
}
524531
}

src/java.base/share/classes/sun/security/util/JarConstraintsParameters.java

+3-8
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,11 @@ public JarConstraintsParameters(CodeSigner[] signers) {
9898
this.timestamp = latestTimestamp;
9999
}
100100

101-
public JarConstraintsParameters(List<X509Certificate> chain, Timestamp timestamp) {
101+
public JarConstraintsParameters(List<X509Certificate> chain, Date timestamp) {
102102
this.keys = new HashSet<>();
103103
this.certsIssuedByAnchor = new HashSet<>();
104104
addToCertsAndKeys(chain);
105-
if (timestamp != null) {
106-
addToCertsAndKeys(timestamp.getSignerCertPath());
107-
this.timestamp = timestamp.getTimestamp();
108-
} else {
109-
this.timestamp = null;
110-
}
105+
this.timestamp = timestamp;
111106
}
112107

113108
// extract last certificate and signer's public key from chain
@@ -178,7 +173,7 @@ public void setExtendedExceptionMsg(String file, String target) {
178173

179174
@Override
180175
public String extendedExceptionMsg() {
181-
return message;
176+
return message == null ? "." : message;
182177
}
183178

184179
@Override

src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ private boolean checkConstraints(String algorithm,
295295
params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME,
296296
name + " entry");
297297
DisabledAlgorithmConstraints.jarConstraints()
298-
.permits(algorithm, params);
298+
.permits(algorithm, params, false);
299299
return true;
300300
} catch (GeneralSecurityException e) {
301301
if (debug != null) {

src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ private boolean permittedCheck(String key, String algorithm) {
383383
try {
384384
params.setExtendedExceptionMsg(name + ".SF", key + " attribute");
385385
DisabledAlgorithmConstraints
386-
.jarConstraints().permits(algorithm, params);
386+
.jarConstraints().permits(algorithm, params, false);
387387
} catch (GeneralSecurityException e) {
388388
permittedAlgs.put(algorithm, Boolean.FALSE);
389389
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);

0 commit comments

Comments
 (0)