Fixed
Status Update
Comments
en...@google.com <en...@google.com>
ma...@gmail.com <ma...@gmail.com> #2
I can also provide server source if that is helpful.
bd...@google.com <bd...@google.com> #3
This could be an already addressed SSLEngine issue.
can you attach a working .apk (or buildable example) that we can just use to reproduce with the aosp/master code base?
can you attach a working .apk (or buildable example) that we can just use to reproduce with the aosp/master code base?
ma...@gmail.com <ma...@gmail.com> #4
Apk is attached. Connection succeeds on Galaxy Nexus with Android 4.4.4 and fails on Nexus 5 with Android 5.0.1.
bd...@google.com <bd...@google.com> #5
I've get "Hello world!" with aosp/master. and on an internal build. so I think my SSLEngine guess was correct. Marking FutureRelease.
kl...@google.com <kl...@google.com> #6
On my one day old ToT AOSP build on Nexus 5 the UI starts out by displaying "Hello world!" it spews an exception in the log, the TLS/SSL handshake does not complete successfully (no application data is exchanged), and 35-40 seconds later the UI displays a "Handshake not received" exception. I'd say this is not fixed.
Below is the exception logged immediately during the handshake.
GRIZZLY0013: Exception during FilterChain execution
java.lang.IllegalArgumentException: one of the src == null
at com.android.org.conscrypt.OpenSSLEngineImpl.wrap(OpenSSLEngineImpl.java:525)
at org.glassfish.grizzly.ssl.SSLConnectionContext.wrap(SSLConnectionContext.java:286)
at org.glassfish.grizzly.ssl.SSLConnectionContext.wrapAll(SSLConnectionContext.java:227)
at org.glassfish.grizzly.ssl.SSLBaseFilter.wrapAll(SSLBaseFilter.java:411)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleWrite(SSLBaseFilter.java:326)
at org.glassfish.grizzly.ssl.SSLFilter.accurateWrite(SSLFilter.java:272)
at org.glassfish.grizzly.ssl.SSLFilter.handleWrite(SSLFilter.java:151)
at org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:111)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.filterchain.FilterChainContext$1.run(FilterChainContext.java:191)
at org.glassfish.grizzly.filterchain.FilterChainContext.resume(FilterChainContext.java:215)
at org.glassfish.grizzly.ssl.SSLFilter$SSLHandshakeContext.completed(SSLFilter.java:392)
at org.glassfish.grizzly.ssl.SSLFilter.notifyHandshakeComplete(SSLFilter.java:287)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleRead(SSLBaseFilter.java:281)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:818)
Below is the exception logged immediately during the handshake.
GRIZZLY0013: Exception during FilterChain execution
java.lang.IllegalArgumentException: one of the src == null
at com.android.org.conscrypt.OpenSSLEngineImpl.wrap(OpenSSLEngineImpl.java:525)
at org.glassfish.grizzly.ssl.SSLConnectionContext.wrap(SSLConnectionContext.java:286)
at org.glassfish.grizzly.ssl.SSLConnectionContext.wrapAll(SSLConnectionContext.java:227)
at org.glassfish.grizzly.ssl.SSLBaseFilter.wrapAll(SSLBaseFilter.java:411)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleWrite(SSLBaseFilter.java:326)
at org.glassfish.grizzly.ssl.SSLFilter.accurateWrite(SSLFilter.java:272)
at org.glassfish.grizzly.ssl.SSLFilter.handleWrite(SSLFilter.java:151)
at org.glassfish.grizzly.filterchain.ExecutorResolver$8.execute(ExecutorResolver.java:111)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.filterchain.FilterChainContext$1.run(FilterChainContext.java:191)
at org.glassfish.grizzly.filterchain.FilterChainContext.resume(FilterChainContext.java:215)
at org.glassfish.grizzly.ssl.SSLFilter$SSLHandshakeContext.completed(SSLFilter.java:392)
at org.glassfish.grizzly.ssl.SSLFilter.notifyHandshakeComplete(SSLFilter.java:287)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleRead(SSLBaseFilter.java:281)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:818)
kl...@google.com <kl...@google.com> #7
The difference between the behavior of the test app on stock Android 5.0 vs ToT AOSP is that on 5.0 the handshake stops before the client is supposed to send ClientKeyExchange + ChangeCipherSpec + Finished, whereas on ToT AOSP it gets farther and stops after the server replies with ChangeCipherSpec + Finished.
bd...@google.com <bd...@google.com> #8
Sorry, you are right. When WiFi was off, it actually reported an exception to the UI, so when I didn't see that after fixing WiFi, I thought it was working. It does seem like it gets farther now. I'll open a tracking bug for this new issue.
kl...@google.com <kl...@google.com> #9
BTW, the "java.lang.IllegalArgumentException: one of the src == null" above on ToT AOSP indicates a bug in the test app code. SSLEngine.wrap does not accept ByteBuffer[] containing null elements.
bd...@google.com <bd...@google.com> #10
Internal issue 36949180
ma...@gmail.com <ma...@gmail.com> #11
The test app just opens a websocket using the Tyrus implementation. If there is a problem with that implementation, we will probably need to coordinate fixes with the Tyrus project. I will post to the Tyrus list to keep them informed.
kr...@google.com <kr...@google.com> #12
There was a bug that was fixed in returning bytes consumed during a handshake. See issue https://code.google.com/p/android/issues/detail?id=93740 for more details on possible work-arounds.
bd...@google.com <bd...@google.com> #13
handshake issue is future release, the follow on error will have to be fixed in the library code.
ma...@gmail.com <ma...@gmail.com> #14
Can you explain what has to be fixed in what library? Does comment #13 relate to the handshake issue in the future release, or to the follow on error?
bd...@google.com <bd...@google.com> #15
The call to SSLEngine.wrap(ByteBuffer[] srcs, ...) has a null entry in the ByteBuffer which is causing the current error.
@Override
public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
throws SSLException {
if (srcs == null) {
throw new IllegalArgumentException("srcs == null");
} else if (dst == null) {
throw new IllegalArgumentException("dst == null");
} else if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
for (ByteBuffer src : srcs) {
if (src == null) {
throw new IllegalArgumentException("one of the src == null");
}
}
so the library shouldn't be passing in a null value in the srcs array.
I think #13 is suggesting that bug is what is responsible for your issue in 5.0, and that the other bug suggests how to workaround it.
@Override
public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
throws SSLException {
if (srcs == null) {
throw new IllegalArgumentException("srcs == null");
} else if (dst == null) {
throw new IllegalArgumentException("dst == null");
} else if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
for (ByteBuffer src : srcs) {
if (src == null) {
throw new IllegalArgumentException("one of the src == null");
}
}
so the library shouldn't be passing in a null value in the srcs array.
I think #13 is suggesting that bug is what is responsible for your issue in 5.0, and that the other bug suggests how to workaround it.
ja...@gmail.com <ja...@gmail.com> #16
Hi,
I am a developer of the Websocket library that was used when this bug was observed (org.glassfish.tyrus from the stack trace). I have had a look at it and can confirm that our library always throws this exception on android 5 when using SSL.
The library that we use for transport (org.glassfish.grizzly) really uses an array of ByteBuffers with some elements set to null, but the ones set to null are not within offset and length.
I think the problem is in the validation logic of OpenSSLEngineImpl.java, because it completely ignores offset and length parameters. The validation should be something like:
for (int i = offset; i < offset + length; i++) {
if (appData[i] == null) {
throw new IllegalArgumentException(
"appData[" + i + "] == null");
}
}
This is how OpenJDK does it.
I am a developer of the Websocket library that was used when this bug was observed (org.glassfish.tyrus from the stack trace). I have had a look at it and can confirm that our library always throws this exception on android 5 when using SSL.
The library that we use for transport (org.glassfish.grizzly) really uses an array of ByteBuffers with some elements set to null, but the ones set to null are not within offset and length.
I think the problem is in the validation logic of OpenSSLEngineImpl.java, because it completely ignores offset and length parameters. The validation should be something like:
for (int i = offset; i < offset + length; i++) {
if (appData[i] == null) {
throw new IllegalArgumentException(
"appData[" + i + "] == null");
}
}
This is how OpenJDK does it.
ja...@gmail.com <ja...@gmail.com> #17
Hi,
a small addition to my previous comment. I read it again and it sounds like my argument is that you should change the validation, because OpenJDK does it differently. That wasn't my intention. The main argument why to change it is the javadoc of SSLEngine#wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer destination) which says that the validation should be done as I suggested:
* @throws IllegalArgumentException
* if either <code>srcs</code> or <code>dst</code>
* is null, or if any element in the <code>srcs</code>
* subsequence specified is null.
Source:http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html
a small addition to my previous comment. I read it again and it sounds like my argument is that you should change the validation, because OpenJDK does it differently. That wasn't my intention. The main argument why to change it is the javadoc of SSLEngine#wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer destination) which says that the validation should be done as I suggested:
* @throws IllegalArgumentException
* if either <code>srcs</code> or <code>dst</code>
* is null, or if any element in the <code>srcs</code>
* subsequence specified is null.
Source:
Description
while developing Android applications. Use the Tools templates for issues
with the developer tools.
Please describe the problem in detail. Be sure to include:
Android 5.0 fails the SSL handshake while connecting websocket to spring boot 1.2.1 Tomcat 8.0.15 server with an authority signed certificate. This is an Ubuntu 14.04 server with OpenSSL 1.0.1f 6 Jan 2014
built on: Fri Jan 9 17:52:35 UTC 2015. Android 4.4.4 (Galaxy Nexus), Firefox, and Chrome successfully handshake and connect the websocket.
Server is configured with cipher suites:
server.ssl.ciphers = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA
- Steps to reproduce the problem (including sample code if appropriate).
Sample Android application is attached. The referenced server is publicly accessible and is available indefinitely. This code works for me on a Galaxy Nexus with Android 4.4.4 and fails always with a Nexus 5 running Android 5.0.1.
- What happened.
The Android 5 client fails with an exception.
01-20 14:54:12.712 22341-22857/edu.umd.mindlab.androidssldebug E/edu.umd.mindlab.androidssldebug﹕ javax.websocket.DeploymentException: SSL handshake has failed
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket._connect(GrizzlyClientSocket.java:380)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.access$000(GrizzlyClientSocket.java:103)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket$1.call(GrizzlyClientSocket.java:228)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket$1.call(GrizzlyClientSocket.java:224)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.connect(GrizzlyClientSocket.java:242)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.openClientSocket(GrizzlyClientContainer.java:95)
at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:626)
at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:673)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:826)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:81)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:496)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:366)
at edu.umd.mindlab.androidssldebug.MainActivity$1.run(MainActivity.java:46)
at java.lang.Thread.run(Thread.java:818)
Caused by: javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:436)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1006)
at org.glassfish.grizzly.ssl.SSLConnectionContext.unwrap(SSLConnectionContext.java:172)
at org.glassfish.grizzly.ssl.SSLUtils.handshakeUnwrap(SSLUtils.java:263)
at org.glassfish.grizzly.ssl.SSLBaseFilter.doHandshakeStep(SSLBaseFilter.java:603)
at org.glassfish.grizzly.ssl.SSLFilter.doHandshakeStep(SSLFilter.java:312)
at org.glassfish.grizzly.ssl.SSLBaseFilter.doHandshakeStep(SSLBaseFilter.java:552)
at org.glassfish.grizzly.ssl.SSLBaseFilter.handleRead(SSLBaseFilter.java:273)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:818)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xa1f16200: Failure in SSL library, usually a protocol error
error:1408E0F4:SSL routines:SSL3_GET_MESSAGE:unexpected message (external/openssl/ssl/s3_both.c:498 0xac449e61:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake_bio(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:423)
... 21 more
The network trace failure is attached. The Android 5 client sends a FIN,ACK after receiving the Server Hello, Certificate, Server Key Exchange, and Server Hello Done.
- What you think the correct behavior should be.
SSL handshake should succeed, as it does with Android 4.4.4 because there is a cipher present supported by Android 5.0.
The server supports TLS1.2.
openssl s_client
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-SHA
This cipher is listed as supported for API 11+:
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA