Hi Daniel,

Would you mind file a bug for the tracking?

Xuelei

> On Oct 31, 2020, at 5:45 AM, Daniel Jeliński <djelins...@gmail.com> wrote:
> 
> Verified that this behavior is still observed with JDK 16 EA 22.
> 
> Client side code responsible for server certificate validation is located in 
> EndEntityChecker.checkTLSServer [1]. That code is not executed when the 
> certificate is trusted [2]. I believe this is a bug - I wouldn't choose to 
> accept a server certificate when that certificate was only meant for signing 
> other certificates, for example.
> 
> Server side code responsible for cipher selection may need some refactoring; 
> currently the server selects the first cipher that passes validation checks 
> and for which keyManager.chooseServerAlias(keyType,...) returns a key. The 
> key manager does not have information about the intended key usage (keyType 
> is "EC" for both ECDH and ECDSA, and we don't know which cipher is being 
> checked), so it returns the same certificate when querying for ECDH and ECDSA.
> 
> Fortunately ECDH is not popular, and most clients won't even try to negotiate 
> it. Still, I believe this is a bug that should be addressed. 
> 
> As far as I could tell, there were no bugs reported for this in the bug 
> system. Should I report them there?
> 
> If someone is interested in the server code, here's the interesting portion 
> of stack trace:
> chooseServerAlias:260, SunX509KeyManagerImpl (sun.security.ssl)
> createServerPossession:288, X509Authentication$X509PossessionGenerator 
> (sun.security.ssl)
> createPossession:214, X509Authentication$X509PossessionGenerator 
> (sun.security.ssl)
> createPossession:90, X509Authentication (sun.security.ssl)
> createPossessions:51, SSLKeyExchange (sun.security.ssl)
> chooseCipherSuite:443, ServerHello$T12ServerHelloProducer (sun.security.ssl)
> 
> [1] 
> http://hg.openjdk.java.net/jdk/jdk/file/ee1d592a9f53/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java#l276
>  
> <http://hg.openjdk.java.net/jdk/jdk/file/ee1d592a9f53/src/java.base/share/classes/sun/security/validator/EndEntityChecker.java#l276>
> [2] 
> http://hg.openjdk.java.net/jdk/jdk/file/ee1d592a9f53/src/java.base/share/classes/sun/security/validator/Validator.java#l267
>  
> <http://hg.openjdk.java.net/jdk/jdk/file/ee1d592a9f53/src/java.base/share/classes/sun/security/validator/Validator.java#l267>
> wt., 27 paź 2020 o 18:44 Daniel Jeliński <djelins...@gmail.com 
> <mailto:djelins...@gmail.com>> napisał(a):
> Hi all,
> 
> TL;DR: both SSL server and client ignore KeyUsage certificate extension when 
> determining the list of available cipher suites. They shouldn't; KeyUsage is 
> the only differentiator between ECDH and ECDSA certificates.
> 
> Long version:
> I'm experimenting with ECC certificates on my Jetty server; when I created an 
> ECC certificate and tested the server with nmap, I found that both ECDSA and 
> ECDH cipher suites are enabled. I don't want ECDH ciphers, but I don't want 
> to add explicit excludes either.
> 
> Reading into NIST recommendations [1] I found that ECDSA certificates should 
> define KeyUsage extension with value digitalSignature, vs ECDH which should 
> use keyAgreement value.
> I experimented with both combinations of KeyValue, both resulted in the same 
> set of ciphers being offered by the server. The client doesn't seem to care 
> about KeyUsage either - it accepts connections even when the selected cipher 
> doesn't match KeyUsage.
> 
> Chrome browser doesn't support ECDH ciphers, but it does support ECDSA. When 
> connecting to a Java server using ECDH certificate, it displays the error 
> "ERR_SSL_KEY_USAGE_INCOMPATIBLE"; the server offers an ECDSA cipher suite, 
> which is rejected by the browser.
> 
> The issue was already reported by Bernd Eckenfels here [2], but as far as I 
> can tell, it is not addressed yet; I was able to reproduce it using slightly 
> modified code of this gist [3]. Certificates were generated using keytool 
> commands:
> 
> ECDSA:
> keytool -genkeypair -alias ec -keyalg EC -keysize 256 -sigalg SHA256withECDSA 
> -validity 365 -dname 
> "CN=localhost,OU=Unknown,O=Unknown,L=Unknown,S=Unknown,C=Unknown" -storetype 
> JKS -keystore ectest.jks -storepass 123456 -ext 
> KeyUsage:c=digitalSignature,keyCertSign
> 
> ECDH:
> keytool -genkeypair -alias ec -keyalg EC -keysize 256 -sigalg SHA256withECDSA 
> -validity 365 -dname 
> "CN=localhost,OU=Unknown,O=Unknown,L=Unknown,S=Unknown,C=Unknown" -storetype 
> JKS -keystore ectest.jks -storepass 123456 -ext 
> KeyUsage:c=keyAgreement,keyCertSign
> 
> I'm not sure if keyCertSign is required on self-signed certificates, added it 
> just in case.
> 
> Tested on OpenJDK 11.0.6.
> 
> Regards,
> Daniel Jeliński
> 
> 
> [1] 
> https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf 
> <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf>
> [2] http://mail.openjdk.java.net/pipermail/security-dev/2017-May/015902.html 
> <http://mail.openjdk.java.net/pipermail/security-dev/2017-May/015902.html>
> [3] https://gist.github.com/djelinski/b4543a3eb7ea66306044c08b41bba00f 
> <https://gist.github.com/djelinski/b4543a3eb7ea66306044c08b41bba00f>

Reply via email to