RFR: 8273236: keytool does not accurately warn about algorithms that are disabled but have additional constraints [v2]

Hai-May Chao hchao at openjdk.java.net
Fri Jan 21 03:34:31 UTC 2022


On Thu, 13 Jan 2022 16:31:35 GMT, Sean Mullan <mullan at openjdk.org> wrote:

>> Hai-May Chao has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   Update with review comments
>
> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 187:
> 
>> 185:     private List<String> weakWarnings = new ArrayList<>();
>> 186: 
>> 187:     Set<X509Certificate> trustedCerts = new HashSet<>();
> 
> Make private.

Fixed.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 1129:
> 
>> 1127:         }
>> 1128: 
>> 1129:         buildTrustedCerts();
> 
> Can we reuse the keystore loaded by `buildTrustedCerts()` instead of reloading it again on line 1138?

No change. This is because `caks` global variable can only be initialized with cacerts keystore  when the `trustcacerts` option is specified; otherwise if has to be kept null. `buildTrustedCerts`() is always executed.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 1558:
> 
>> 1556:         checkWeakConstraint(rb.getString("the.issuer"),
>> 1557:                 keyStore.getCertificateChain(alias));
>> 1558:         cpcp = new CertPathConstraintsParameters(cert, null, null, null);
> 
> You could also specify the variant parameter if the certificate contains an EKU extension. The mapping from EKU to variant would be:
> 
> - anyExtendedKeyUsage -> VAR_GENERIC
> - serverAuth -> VAR_TLS_SERVER
> - clientAuth -> VAR_TLS_CLIENT
> - codeSigning -> VAR_CODE_SIGNING
> - emailProtection -> none defined, so just use null or VAR_GENERIC
> - timeStamping -> VAR_TSA_SERVER
> - OCSPSigning -> none defined, so just use null or VAR_GENERIC

Fixed.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 1706:
> 
>> 1704:         }
>> 1705:         dumpCert(cert, out);
>> 1706:         CertPathConstraintsParameters cpcp =
> 
> Here you could also specify the variant if the cert contains an EKU extension. Same comment applies to other places where you are checking the algorithm constraints of a certificate.

Fixed.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 2198:
> 
>> 2196:                         ("Certificate.chain.length.") + chain.length);
>> 2197: 
>> 2198:                     X509Certificate[] xcerts = convertCerts(chain);
> 
> I think you can just cast to an `X509Certificate[]` instead of reparsing all the certificates, i.e.:
> 
> `X509Certificate[] xcerts = (X509Certificate[]) chain;`

I got `java.lang.ClassCastException` when casting `Certificate[]` array form here. However, I should cast Certificate object directly instead of reparsing the certificate, and made the change to do so.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 2259:
> 
>> 2257:             }
>> 2258:             cpcp = new CertPathConstraintsParameters((X509Certificate)cert,
>> 2259:                     null,null, null);
> 
> Nit - add space between `null,null`.

Fixed.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 5039:
> 
>> 5037:                         trustedCerts.add((X509Certificate)caks.getCertificate(a));
>> 5038:                     } catch (Exception e2) {
>> 5039:                         // ignore, when a SecretkeyEntry does not include a cert
> 
> Not sure I understand this comment, as these should not be SecretKeyEntries. You should still ignore it but this should not throw an Exception unless the KeyStore was not loaded/initialized properly (which normally won't occur).

Updated with the suggested comments.

> src/java.base/share/classes/sun/security/tools/keytool/Main.java line 5048:
> 
>> 5046:     }
>> 5047: 
>> 5048:     private TrustAnchor findTrustAnchor(List<X509Certificate> chain) {
> 
> I would consider having an initial check that returns `null` if `chain.isEmpty()`. Not sure if that is a valid scenario, but it would avoid an `IndexOOBException` just in case.

Added the initial check.

> src/java.base/share/classes/sun/security/tools/keytool/Resources.java line 486:
> 
>> 484:         {"verified.by.s.in.s.weak", "Verified by %1$s in %2$s with a %3$s"},
>> 485:         {"whose.sigalg.disabled", "%1$s uses the %2$s signature algorithm which is considered a security risk and is disabled."},
>> 486:         {"whose.sigalg.usagesignedjar", "%1$s uses the %2$s signature algorithm which is considered a security risk and cannot be used to sign JARs after 2019-01-01."},
> 
> Instead of hard-coding "2019-01-01", we should extract this date from the `denyAfter` attribute of the `jdk.certpath.disabledAlgorithms` security property and pass it in as a parameter.

Fixed.

-------------

PR: https://git.openjdk.java.net/jdk/pull/7039



More information about the security-dev mailing list