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>