From da01b1daec1d015deba08af8b2df5c272d719c43 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 6 Jan 2016 13:41:06 +0100 Subject: [PATCH] Decryption failed or bad mac record in Android 5.0 Motivation: Android 5.0 (API version 21) has a bug which not correctly set the bytesConsumed of SSLEngineResult when HandshakeStatus is FINISHED. Because of this we need to special handle the status and so workaround the Android bug. Modifications: - Break the unwrap for (;;) loop when HandshakeStatus is FINISHED and bytesConsumed == 0 && bytesProduced == 0. Result: SslHandler works with all known version of Android. --- .../main/java/io/netty/handler/ssl/SslHandler.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java index 9e3337c7b7c..b91cf238e19 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -1073,7 +1073,19 @@ private boolean unwrap( case FINISHED: setHandshakeSuccess(); wrapLater = true; - continue; + + // We 'break' here and NOT 'continue' as android API version 21 has a bug where they consume + // data from the buffer but NOT correctly set the SSLEngineResult.bytesConsumed(). + // Because of this it will raise an exception on the next iteration of the for loop on android + // API version 21. Just doing a break will work here as produced and consumed will both be 0 + // and so we break out of the complete for (;;) loop and so call decode(...) again later on. + // On other platforms this will have no negative effect as we will just continue with the + // for (;;) loop if something was either consumed or produced. + // + // See: + // - https://github.com/netty/netty/issues/4116 + // - https://code.google.com/p/android/issues/detail?id=198639&thanks=198639&ts=1452501203 + break; case NOT_HANDSHAKING: if (setHandshakeSuccessIfStillHandshaking()) { wrapLater = true;