Skip to content

Commit 03f8c0f

Browse files
committed
8275887: jarsigner prints invalid digest/signature algorithm warnings if keysize is weak/disabled
Reviewed-by: weijun
1 parent 936f7ff commit 03f8c0f

File tree

9 files changed

+90
-89
lines changed

9 files changed

+90
-89
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

@@ -421,7 +424,8 @@ SignerInfo verify(PKCS7 block, byte[] data)
421424
new AlgorithmId(ObjectIdentifier.of(oid),
422425
digestEncryptionAlgorithmId.getParameters());
423426
algorithms.put(sigAlgId,
424-
"SignerInfo digestEncryptionAlgorithm field");
427+
new AlgorithmInfo(
428+
"SignerInfo digestEncryptionAlgorithm field", true));
425429
}
426430

427431
X509Certificate cert = getCertificate(block);
@@ -677,7 +681,8 @@ private void verifyTimestamp(TimestampToken token)
677681
throws NoSuchAlgorithmException, SignatureException {
678682

679683
AlgorithmId digestAlgId = token.getHashAlgorithm();
680-
algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
684+
algorithms.put(digestAlgId,
685+
new AlgorithmInfo("TimestampToken digestAlgorithm field", false));
681686

682687
MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
683688

@@ -734,18 +739,19 @@ public String toString() {
734739
*/
735740
public static Set<String> verifyAlgorithms(SignerInfo[] infos,
736741
JarConstraintsParameters params, String name) throws SignatureException {
737-
Map<AlgorithmId, String> algorithms = new HashMap<>();
742+
Map<AlgorithmId, AlgorithmInfo> algorithms = new HashMap<>();
738743
for (SignerInfo info : infos) {
739744
algorithms.putAll(info.algorithms);
740745
}
741746

742747
Set<String> enabledAlgorithms = new HashSet<>();
743748
try {
744-
for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
745-
params.setExtendedExceptionMsg(name, algorithm.getValue());
746-
AlgorithmId algId = algorithm.getKey();
749+
for (var algEntry : algorithms.entrySet()) {
750+
AlgorithmInfo info = algEntry.getValue();
751+
params.setExtendedExceptionMsg(name, info.field());
752+
AlgorithmId algId = algEntry.getKey();
747753
JAR_DISABLED_CHECK.permits(algId.getName(),
748-
algId.getParameters(), params);
754+
algId.getParameters(), params, info.checkKey());
749755
enabledAlgorithms.add(algId.getName());
750756
}
751757
} 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
@@ -226,13 +224,13 @@ public void check(Certificate cert,
226224
CertPathConstraintsParameters cp =
227225
new CertPathConstraintsParameters(trustedPubKey, variant,
228226
anchor, date);
229-
dac.permits(trustedPubKey.getAlgorithm(), cp);
227+
dac.permits(trustedPubKey.getAlgorithm(), cp, true);
230228
}
231229
// Check the signature algorithm and parameters against constraints
232230
CertPathConstraintsParameters cp =
233231
new CertPathConstraintsParameters(x509Cert, variant,
234232
anchor, date);
235-
dac.permits(currSigAlg, currSigAlgParams, cp);
233+
dac.permits(currSigAlg, currSigAlgParams, cp, true);
236234
} else {
237235
if (prevPubKey != null) {
238236
if (!constraints.permits(SIGNATURE_PRIMITIVE_SET,
@@ -362,29 +360,6 @@ void trySetTrustAnchor(TrustAnchor anchor) {
362360
}
363361
}
364362

365-
/**
366-
* Check the signature algorithm with the specified public key.
367-
*
368-
* @param key the public key to verify the CRL signature
369-
* @param crl the target CRL
370-
* @param variant the Validator variant of the operation. A null value
371-
* passed will set it to Validator.GENERIC.
372-
* @param anchor the trust anchor selected to validate the CRL issuer
373-
*/
374-
static void check(PublicKey key, X509CRL crl, String variant,
375-
TrustAnchor anchor) throws CertPathValidatorException {
376-
377-
X509CRLImpl x509CRLImpl = null;
378-
try {
379-
x509CRLImpl = X509CRLImpl.toImpl(crl);
380-
} catch (CRLException ce) {
381-
throw new CertPathValidatorException(ce);
382-
}
383-
384-
AlgorithmId algorithmId = x509CRLImpl.getSigAlgId();
385-
check(key, algorithmId, variant, anchor);
386-
}
387-
388363
/**
389364
* Check the signature algorithm with the specified public key.
390365
*
@@ -399,7 +374,7 @@ static void check(PublicKey key, AlgorithmId algorithmId, String variant,
399374

400375
DisabledAlgorithmConstraints.certPathConstraints().permits(
401376
algorithmId.getName(), algorithmId.getParameters(),
402-
new CertPathConstraintsParameters(key, variant, anchor, null));
377+
new CertPathConstraintsParameters(key, variant, anchor, null), true);
403378
}
404379
}
405380

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

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

654654
// check the crl signature algorithm
655655
try {
656-
AlgorithmChecker.check(prevKey, crl, variant, anchor);
656+
AlgorithmChecker.check(prevKey, crlImpl.getSigAlgId(),
657+
variant, anchor);
657658
} catch (CertPathValidatorException cpve) {
658659
if (debug != null) {
659660
debug.println("CRL signature algorithm check failed: " + cpve);

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

+24-19
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ public final boolean permits(Set<CryptoPrimitive> primitives,
192192
}
193193

194194
public final void permits(String algorithm, AlgorithmParameters ap,
195-
ConstraintsParameters cp) throws CertPathValidatorException {
196-
197-
permits(algorithm, cp);
195+
ConstraintsParameters cp, boolean checkKey)
196+
throws CertPathValidatorException {
197+
permits(algorithm, cp, checkKey);
198198
if (ap != null) {
199199
permits(ap, cp);
200200
}
@@ -219,36 +219,36 @@ private void permitsPSSParams(AlgorithmParameters ap,
219219
PSSParameterSpec pssParams =
220220
ap.getParameterSpec(PSSParameterSpec.class);
221221
String digestAlg = pssParams.getDigestAlgorithm();
222-
permits(digestAlg, cp);
222+
permits(digestAlg, cp, false);
223223
AlgorithmParameterSpec mgfParams = pssParams.getMGFParameters();
224224
if (mgfParams instanceof MGF1ParameterSpec) {
225225
String mgfDigestAlg =
226226
((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
227227
if (!mgfDigestAlg.equalsIgnoreCase(digestAlg)) {
228-
permits(mgfDigestAlg, cp);
228+
permits(mgfDigestAlg, cp, false);
229229
}
230230
}
231231
} catch (InvalidParameterSpecException ipse) {
232232
// ignore
233233
}
234234
}
235235

236-
public final void permits(String algorithm, ConstraintsParameters cp)
237-
throws CertPathValidatorException {
238-
239-
// Check if named curves in the key are disabled.
240-
for (Key key : cp.getKeys()) {
241-
for (String curve : getNamedCurveFromKey(key)) {
242-
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
243-
throw new CertPathValidatorException(
236+
public final void permits(String algorithm, ConstraintsParameters cp,
237+
boolean checkKey) throws CertPathValidatorException {
238+
if (checkKey) {
239+
// Check if named curves in the key are disabled.
240+
for (Key key : cp.getKeys()) {
241+
for (String curve : getNamedCurveFromKey(key)) {
242+
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
243+
throw new CertPathValidatorException(
244244
"Algorithm constraints check failed on disabled " +
245245
"algorithm: " + curve,
246246
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
247+
}
247248
}
248249
}
249250
}
250-
251-
algorithmConstraints.permits(algorithm, cp);
251+
algorithmConstraints.permits(algorithm, cp, checkKey);
252252
}
253253

254254
private static List<String> getNamedCurveFromKey(Key key) {
@@ -481,8 +481,8 @@ public boolean permits(String algorithm, AlgorithmParameters aps) {
481481
return true;
482482
}
483483

484-
public void permits(String algorithm, ConstraintsParameters cp)
485-
throws CertPathValidatorException {
484+
public void permits(String algorithm, ConstraintsParameters cp,
485+
boolean checkKey) throws CertPathValidatorException {
486486

487487
if (debug != null) {
488488
debug.println("Constraints.permits(): " + algorithm + ", "
@@ -496,8 +496,10 @@ public void permits(String algorithm, ConstraintsParameters cp)
496496
algorithms.add(algorithm);
497497
}
498498

499-
for (Key key : cp.getKeys()) {
500-
algorithms.add(key.getAlgorithm());
499+
if (checkKey) {
500+
for (Key key : cp.getKeys()) {
501+
algorithms.add(key.getAlgorithm());
502+
}
501503
}
502504

503505
// Check all applicable constraints
@@ -507,6 +509,9 @@ public void permits(String algorithm, ConstraintsParameters cp)
507509
continue;
508510
}
509511
for (Constraint constraint : list) {
512+
if (!checkKey && constraint instanceof KeySizeConstraint) {
513+
continue;
514+
}
510515
constraint.permits(cp);
511516
}
512517
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -217,7 +217,7 @@ public CodeSigner[] verify(Hashtable<String, CodeSigner[]> verifiedSigners,
217217
params.setExtendedExceptionMsg(JarFile.MANIFEST_NAME,
218218
name + " entry");
219219
DisabledAlgorithmConstraints.jarConstraints()
220-
.permits(digest.getAlgorithm(), params);
220+
.permits(digest.getAlgorithm(), params, false);
221221
} catch (GeneralSecurityException e) {
222222
if (debug != null) {
223223
debug.println("Digest algorithm is restricted: " + e);

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)