Skip to content

Commit 53620b3

Browse files
author
Alexey Bakhtin
committed
8275887: jarsigner prints invalid digest/signature algorithm warnings if keysize is weak/disabled
Reviewed-by: phh, andrew Backport-of: 03f8c0fb9363dc1bb07bed1ae0359c029caa0130
1 parent 7297bdf commit 53620b3

File tree

9 files changed

+95
-83
lines changed

9 files changed

+95
-83
lines changed

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

+26-11
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,21 @@ public class SignerInfo implements DerEncoder {
8484
/**
8585
* A map containing the algorithms in this SignerInfo. This is used to
8686
* avoid checking algorithms to see if they are disabled more than once.
87-
* The key is the AlgorithmId of the algorithm, and the value is the name of
88-
* the field or attribute.
87+
* The key is the AlgorithmId of the algorithm, and the value is a record
88+
* containing the name of the field or attribute and whether the key
89+
* should also be checked (ex: if it is a signature algorithm).
8990
*/
90-
private Map<AlgorithmId, String> algorithms = new HashMap<>();
91+
private class AlgorithmInfo {
92+
String field;
93+
boolean checkKey;
94+
private AlgorithmInfo(String f, boolean cK) {
95+
field = f;
96+
checkKey = cK;
97+
}
98+
String field() { return field; }
99+
boolean checkKey() { return checkKey; }
100+
}
101+
private Map<AlgorithmId, AlgorithmInfo> algorithms = new HashMap<>();
91102

92103
public SignerInfo(X500Name issuerName,
93104
BigInteger serial,
@@ -323,7 +334,8 @@ SignerInfo verify(PKCS7 block, byte[] data)
323334
}
324335

325336
String digestAlgName = digestAlgorithmId.getName();
326-
algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
337+
algorithms.put(digestAlgorithmId,
338+
new AlgorithmInfo("SignerInfo digestAlgorithm field", false));
327339

328340
byte[] dataSigned;
329341

@@ -382,7 +394,8 @@ SignerInfo verify(PKCS7 block, byte[] data)
382394
new AlgorithmId(oid,
383395
digestEncryptionAlgorithmId.getParameters());
384396
algorithms.put(sigAlgId,
385-
"SignerInfo digestEncryptionAlgorithm field");
397+
new AlgorithmInfo(
398+
"SignerInfo digestEncryptionAlgorithm field", true));
386399
} catch (NoSuchAlgorithmException ignore) {
387400
}
388401

@@ -569,7 +582,8 @@ private void verifyTimestamp(TimestampToken token)
569582
throws NoSuchAlgorithmException, SignatureException {
570583

571584
AlgorithmId digestAlgId = token.getHashAlgorithm();
572-
algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
585+
algorithms.put(digestAlgId,
586+
new AlgorithmInfo("TimestampToken digestAlgorithm field", false));
573587

574588
MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
575589

@@ -626,18 +640,19 @@ public String toString() {
626640
*/
627641
public static Set<String> verifyAlgorithms(SignerInfo[] infos,
628642
JarConstraintsParameters params, String name) throws SignatureException {
629-
Map<AlgorithmId, String> algorithms = new HashMap<>();
643+
Map<AlgorithmId, AlgorithmInfo> algorithms = new HashMap<>();
630644
for (SignerInfo info : infos) {
631645
algorithms.putAll(info.algorithms);
632646
}
633647

634648
Set<String> enabledAlgorithms = new HashSet<>();
635649
try {
636-
for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
637-
params.setExtendedExceptionMsg(name, algorithm.getValue());
638-
AlgorithmId algId = algorithm.getKey();
650+
for (Map.Entry<AlgorithmId,AlgorithmInfo> algEntry : algorithms.entrySet()) {
651+
AlgorithmInfo info = algEntry.getValue();
652+
params.setExtendedExceptionMsg(name, info.field());
653+
AlgorithmId algId = algEntry.getKey();
639654
JAR_DISABLED_CHECK.permits(algId.getName(),
640-
algId.getParameters(), params);
655+
algId.getParameters(), params, info.checkKey());
641656
enabledAlgorithms.add(algId.getName());
642657
}
643658
} catch (CertPathValidatorException e) {

jdk/src/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

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

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

690690
// check the crl signature algorithm
691691
try {
692-
AlgorithmChecker.check(prevKey, crl, variant, anchor);
692+
AlgorithmChecker.check(prevKey, crlImpl.getSigAlgId(),
693+
variant, anchor);
693694
} catch (CertPathValidatorException cpve) {
694695
if (debug != null) {
695696
debug.println("CRL signature algorithm check failed: " + cpve);

jdk/src/share/classes/sun/security/tools/jarsigner/Main.java

+18-13
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,14 @@ void verifyJar(String jarName)
904904
Calendar c = Calendar.getInstance(
905905
TimeZone.getTimeZone("UTC"),
906906
Locale.getDefault(Locale.Category.FORMAT));
907-
c.setTime(tsTokenInfo.getDate());
907+
Date tsDate = tsTokenInfo.getDate();
908+
c.setTime(tsDate);
908909
JarConstraintsParameters jcp =
909-
new JarConstraintsParameters(chain, si.getTimestamp());
910+
new JarConstraintsParameters(chain, tsDate);
911+
JarConstraintsParameters jcpts =
912+
new JarConstraintsParameters(
913+
tsSi.getCertificateChain(tsToken),
914+
tsDate);
910915
history = String.format(
911916
rb.getString("history.with.ts"),
912917
signer.getSubjectX500Principal(),
@@ -915,9 +920,9 @@ void verifyJar(String jarName)
915920
verifyWithWeak(key, jcp),
916921
c,
917922
tsSigner.getSubjectX500Principal(),
918-
verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true, jcp),
919-
verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true, jcp),
920-
verifyWithWeak(tsKey, jcp));
923+
verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true, jcpts),
924+
verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true, jcpts),
925+
verifyWithWeak(tsKey, jcpts));
921926
} else {
922927
JarConstraintsParameters jcp =
923928
new JarConstraintsParameters(chain, null);
@@ -1267,13 +1272,13 @@ private String verifyWithWeak(String alg, Set<CryptoPrimitive> primitiveSet,
12671272
boolean tsa, JarConstraintsParameters jcp) {
12681273

12691274
try {
1270-
DISABLED_CHECK.permits(alg, jcp);
1275+
DISABLED_CHECK.permits(alg, jcp, false);
12711276
} catch (CertPathValidatorException e) {
12721277
disabledAlgFound = true;
12731278
return String.format(rb.getString("with.disabled"), alg);
12741279
}
12751280
try {
1276-
LEGACY_CHECK.permits(alg, jcp);
1281+
LEGACY_CHECK.permits(alg, jcp, false);
12771282
return alg;
12781283
} catch (CertPathValidatorException e) {
12791284
if (primitiveSet == SIG_PRIMITIVE_SET) {
@@ -1295,13 +1300,13 @@ private String verifyWithWeak(String alg, Set<CryptoPrimitive> primitiveSet,
12951300
private String verifyWithWeak(PublicKey key, JarConstraintsParameters jcp) {
12961301
int kLen = KeyUtil.getKeySize(key);
12971302
try {
1298-
DISABLED_CHECK.permits(key.getAlgorithm(), jcp);
1303+
DISABLED_CHECK.permits(key.getAlgorithm(), jcp, true);
12991304
} catch (CertPathValidatorException e) {
13001305
disabledAlgFound = true;
13011306
return String.format(rb.getString("key.bit.disabled"), kLen);
13021307
}
13031308
try {
1304-
LEGACY_CHECK.permits(key.getAlgorithm(), jcp);
1309+
LEGACY_CHECK.permits(key.getAlgorithm(), jcp, true);
13051310
if (kLen >= 0) {
13061311
return String.format(rb.getString("key.bit"), kLen);
13071312
} else {
@@ -1318,9 +1323,9 @@ private void checkWeakSign(String alg, Set<CryptoPrimitive> primitiveSet,
13181323
boolean tsa, JarConstraintsParameters jcp) {
13191324

13201325
try {
1321-
DISABLED_CHECK.permits(alg, jcp);
1326+
DISABLED_CHECK.permits(alg, jcp, false);
13221327
try {
1323-
LEGACY_CHECK.permits(alg, jcp);
1328+
LEGACY_CHECK.permits(alg, jcp, false);
13241329
} catch (CertPathValidatorException e) {
13251330
if (primitiveSet == SIG_PRIMITIVE_SET) {
13261331
legacyAlg |= 2;
@@ -1347,9 +1352,9 @@ private void checkWeakSign(String alg, Set<CryptoPrimitive> primitiveSet,
13471352

13481353
private void checkWeakSign(PrivateKey key, JarConstraintsParameters jcp) {
13491354
try {
1350-
DISABLED_CHECK.permits(key.getAlgorithm(), jcp);
1355+
DISABLED_CHECK.permits(key.getAlgorithm(), jcp, true);
13511356
try {
1352-
LEGACY_CHECK.permits(key.getAlgorithm(), jcp);
1357+
LEGACY_CHECK.permits(key.getAlgorithm(), jcp, true);
13531358
} catch (CertPathValidatorException e) {
13541359
legacyAlg |= 8;
13551360
}

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

+25-18
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,16 @@ 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
}
201201
}
202202

203203
private void permits(AlgorithmParameters ap, ConstraintsParameters cp)
204-
throws CertPathValidatorException {
204+
throws CertPathValidatorException {
205205

206206
switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
207207
case "RSASSA-PSS":
@@ -219,36 +219,38 @@ 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 {
236+
public final void permits(String algorithm, ConstraintsParameters cp,
237+
boolean checkKey) throws CertPathValidatorException {
238238

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(
239+
if (checkKey) {
240+
// Check if named curves in the key are disabled.
241+
for (Key key : cp.getKeys()) {
242+
for (String curve : getNamedCurveFromKey(key)) {
243+
if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
244+
throw new CertPathValidatorException(
244245
"Algorithm constraints check failed on disabled " +
245246
"algorithm: " + curve,
246247
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
248+
}
247249
}
248250
}
249251
}
250252

251-
algorithmConstraints.permits(algorithm, cp);
253+
algorithmConstraints.permits(algorithm, cp, checkKey);
252254
}
253255

254256
private static List<String> getNamedCurveFromKey(Key key) {
@@ -479,8 +481,8 @@ public boolean permits(String algorithm, AlgorithmParameters aps) {
479481
return true;
480482
}
481483

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

485487
if (debug != null) {
486488
debug.println("Constraints.permits(): " + algorithm + ", "
@@ -494,8 +496,10 @@ public void permits(String algorithm, ConstraintsParameters cp)
494496
algorithms.add(algorithm);
495497
}
496498

497-
for (Key key : cp.getKeys()) {
498-
algorithms.add(key.getAlgorithm());
499+
if (checkKey) {
500+
for (Key key : cp.getKeys()) {
501+
algorithms.add(key.getAlgorithm());
502+
}
499503
}
500504

501505
// Check all applicable constraints
@@ -505,6 +509,9 @@ public void permits(String algorithm, ConstraintsParameters cp)
505509
continue;
506510
}
507511
for (Constraint constraint : list) {
512+
if (!checkKey && constraint instanceof KeySizeConstraint) {
513+
continue;
514+
}
508515
constraint.permits(cp);
509516
}
510517
}

jdk/src/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

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -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);

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ private boolean permittedCheck(String key, String algorithm) {
360360
try {
361361
params.setExtendedExceptionMsg(name + ".SF", key + " attribute");
362362
DisabledAlgorithmConstraints
363-
.jarConstraints().permits(algorithm, params);
363+
.jarConstraints().permits(algorithm, params, false);
364364
} catch (GeneralSecurityException e) {
365365
permittedAlgs.put(algorithm, Boolean.FALSE);
366366
permittedAlgs.put(key.toUpperCase(), Boolean.FALSE);

0 commit comments

Comments
 (0)