Okhttp: When TLS uses pre-shared keys the Handshake has no peer certs

Created on 10 Mar 2019  Â·  6Comments  Â·  Source: square/okhttp

Java 11’s TLS stack automatically supports pre-shared keys when attempting a repeat TLS connection to a server.

Unfortunately these TLS handshakes don’t have peer certificates and SSLSession.getPeerCertificates() throws.

Without the peer certificates other things break including certificate pinning.

java.util.NoSuchElementException
    at java.base/java.util.ArrayDeque.removeFirst(ArrayDeque.java:363)
    at okhttp3.internal.tls.BasicCertificateChainCleaner.clean(BasicCertificateChainCleaner.java:58)
    at okhttp3.CertificatePinner.check(CertificatePinner.java:166)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:358)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:300)

This is reproduced by CallTest.matchingPinnedCertificate() on Java 11.

bug

All 6 comments

I submitted a bug report to OpenJDK using this isolated test:
https://gist.github.com/swankjesse/589e3e1c4a566e4a9aaec66f0f3a6223

@swankjesse
We've faced strange exception after updating to 3.14.2 version and migrating to Java 11
from time to time requests fail with the exception:

Caused by: javax.net.ssl.SSLPeerUnverifiedException: Hostname graph.facebook.com not verified (no certificates)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:353) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:300) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:185) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.java:224) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.java:108) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.java:88) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:169) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.2.jar:?]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.2.jar:?]
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221) ~[okhttp-3.14.2.jar:?]
    at okhttp3.RealCall.execute(RealCall.java:81) ~[okhttp-3.14.2.jar:?]

As I see in OkHostnameVerifier.verify()
session.getPeerCertificates() returns null.
works fine with java 8 and version 3.12.1
could those issues be connected?

What does the test above report on your Java 11?

This might have been fixed in Java 11.0.2.
https://bugs.openjdk.java.net/browse/JDK-8211806

on the OpenJDK 11.0.2 it says:

handshake success: peer=CN=localhost
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at java.base/sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:526)
    at PreSharedKeyTest.clientHandshake(PreSharedKeyTest.java:93)
    at PreSharedKeyTest.runClient(PreSharedKeyTest.java:79)
    at PreSharedKeyTest.main(PreSharedKeyTest.java:41)

OpenJDK 11.0.3 works fine. It seems like another related bug was resolved in OpenJDK 11.0.3.
TLS 1.3 resumed session does not retain peer certificate chain
OpenJDK 11.0.3 Release note

@swankjesse We'll probably close this issue?

Was this page helpful?
0 / 5 - 0 ratings