From 9ad5b68d572f1dd6789dc1a02d9d7ab27a34f8ae Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 10 Mar 2024 17:40:41 +0100 Subject: [PATCH] do not attempt unique/exporter channel binding on non conscrypt sockets --- .../crypto/sasl/ChannelBinding.java | 29 ++++------ .../crypto/sasl/ChannelBindingMechanism.java | 17 ++++-- .../siacs/conversations/utils/SSLSockets.java | 56 +++++++++---------- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java index 2eb5e39fb..3cbaaeeb9 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java @@ -10,15 +10,15 @@ import com.google.common.collect.BiMap; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableBiMap; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.SSLSockets; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + public enum ChannelBinding { NONE, TLS_EXPORTER, @@ -104,22 +104,17 @@ public enum ChannelBinding { } private static String shortName(final ChannelBinding channelBinding) { - switch (channelBinding) { - case TLS_UNIQUE: - return "UNIQ"; - case TLS_EXPORTER: - return "EXPR"; - case TLS_SERVER_END_POINT: - return "ENDP"; - case NONE: - return "NONE"; - default: - throw new AssertionError("Missing short name for " + channelBinding); - } + return switch (channelBinding) { + case TLS_UNIQUE -> "UNIQ"; + case TLS_EXPORTER -> "EXPR"; + case TLS_SERVER_END_POINT -> "ENDP"; + case NONE -> "NONE"; + default -> throw new AssertionError("Missing short name for " + channelBinding); + }; } public static int priority(final ChannelBinding channelBinding) { - if (Arrays.asList(TLS_EXPORTER,TLS_UNIQUE).contains(channelBinding)) { + if (Arrays.asList(TLS_EXPORTER, TLS_UNIQUE).contains(channelBinding)) { return 2; } else if (channelBinding == ChannelBinding.TLS_SERVER_END_POINT) { return 1; diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java index 7343eb86e..6c763a382 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBindingMechanism.java @@ -20,12 +20,18 @@ public interface ChannelBindingMechanism { ChannelBinding getChannelBinding(); - static byte[] getChannelBindingData(final SSLSocket sslSocket, final ChannelBinding channelBinding) + static byte[] getChannelBindingData( + final SSLSocket sslSocket, final ChannelBinding channelBinding) throws SaslMechanism.AuthenticationException { if (sslSocket == null) { - throw new SaslMechanism.AuthenticationException("Channel binding attempt on non secure socket"); + throw new SaslMechanism.AuthenticationException( + "Channel binding attempt on non secure socket"); } if (channelBinding == ChannelBinding.TLS_EXPORTER) { + if (!Conscrypt.isConscrypt(sslSocket)) { + throw new SaslMechanism.AuthenticationException( + "Channel binding attempt on non supporting socket"); + } final byte[] keyingMaterial; try { keyingMaterial = @@ -39,6 +45,10 @@ public interface ChannelBindingMechanism { } return keyingMaterial; } else if (channelBinding == ChannelBinding.TLS_UNIQUE) { + if (!Conscrypt.isConscrypt(sslSocket)) { + throw new SaslMechanism.AuthenticationException( + "Channel binding attempt on non supporting socket"); + } final byte[] unique = Conscrypt.getTlsUnique(sslSocket); if (unique == null) { throw new SaslMechanism.AuthenticationException( @@ -99,8 +109,7 @@ public interface ChannelBindingMechanism { } static int getPriority(final SaslMechanism mechanism) { - if (mechanism instanceof ChannelBindingMechanism) { - final ChannelBindingMechanism channelBindingMechanism = (ChannelBindingMechanism) mechanism; + if (mechanism instanceof ChannelBindingMechanism channelBindingMechanism) { return ChannelBinding.priority(channelBindingMechanism.getChannelBinding()); } else { return 0; diff --git a/src/main/java/eu/siacs/conversations/utils/SSLSockets.java b/src/main/java/eu/siacs/conversations/utils/SSLSockets.java index ae853bea8..4a8680e20 100644 --- a/src/main/java/eu/siacs/conversations/utils/SSLSockets.java +++ b/src/main/java/eu/siacs/conversations/utils/SSLSockets.java @@ -7,6 +7,9 @@ import androidx.annotation.RequiresApi; import com.google.common.base.Strings; +import eu.siacs.conversations.Config; +import eu.siacs.conversations.entities.Account; + import org.conscrypt.Conscrypt; import java.lang.reflect.Method; @@ -24,22 +27,19 @@ import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; -import eu.siacs.conversations.Config; -import eu.siacs.conversations.entities.Account; - public class SSLSockets { public static void setSecurity(final SSLSocket sslSocket) { final String[] supportProtocols; - final Collection supportedProtocols = new LinkedList<>( - Arrays.asList(sslSocket.getSupportedProtocols())); + final Collection supportedProtocols = + new LinkedList<>(Arrays.asList(sslSocket.getSupportedProtocols())); supportedProtocols.remove("SSLv3"); supportProtocols = supportedProtocols.toArray(new String[0]); sslSocket.setEnabledProtocols(supportProtocols); - final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( - sslSocket.getSupportedCipherSuites()); + final String[] cipherSuites = + CryptoHelper.getOrderedCipherSuites(sslSocket.getSupportedCipherSuites()); if (cipherSuites.length > 0) { sslSocket.setEnabledCipherSuites(cipherSuites); } @@ -70,7 +70,8 @@ public class SSLSockets { socket.setSSLParameters(parameters); } - private static void setApplicationProtocolReflection(final SSLSocket socket, final String protocol) { + private static void setApplicationProtocolReflection( + final SSLSocket socket, final String protocol) { try { final Method method = socket.getClass().getMethod("setAlpnProtocols", byte[].class); // the concatenation of 8-bit, length prefixed protocol names, just one in our case... @@ -78,16 +79,17 @@ public class SSLSockets { final byte[] protocolUTF8Bytes = protocol.getBytes(StandardCharsets.UTF_8); final byte[] lengthPrefixedProtocols = new byte[protocolUTF8Bytes.length + 1]; lengthPrefixedProtocols[0] = (byte) protocol.length(); // cannot be over 255 anyhow - System.arraycopy(protocolUTF8Bytes, 0, lengthPrefixedProtocols, 1, protocolUTF8Bytes.length); - method.invoke(socket, new Object[]{lengthPrefixedProtocols}); + System.arraycopy( + protocolUTF8Bytes, 0, lengthPrefixedProtocols, 1, protocolUTF8Bytes.length); + method.invoke(socket, new Object[] {lengthPrefixedProtocols}); } catch (Throwable e) { - Log.e(Config.LOGTAG,"unable to set ALPN on socket",e); + Log.e(Config.LOGTAG, "unable to set ALPN on socket", e); } } public static void setApplicationProtocol(final SSLSocket socket, final String protocol) { if (Conscrypt.isConscrypt(socket)) { - Conscrypt.setApplicationProtocols(socket, new String[]{protocol}); + Conscrypt.setApplicationProtocols(socket, new String[] {protocol}); } else { setApplicationProtocolReflection(socket, protocol); } @@ -113,9 +115,12 @@ public class SSLSockets { } public static Version version(final Socket socket) { - if (socket instanceof SSLSocket) { - final SSLSocket sslSocket = (SSLSocket) socket; - return Version.of(sslSocket.getSession().getProtocol()); + if (socket instanceof SSLSocket sslSocket) { + if (Conscrypt.isConscrypt(sslSocket)) { + return Version.of(sslSocket.getSession().getProtocol()); + } else { + return Version.TLS_UNSUPPORTED_VERSION; + } } else { return Version.NONE; } @@ -126,22 +131,17 @@ public class SSLSockets { TLS_1_1, TLS_1_2, TLS_1_3, - UNKNOWN, + TLS_UNSUPPORTED_VERSION, NONE; private static Version of(final String protocol) { - switch (Strings.nullToEmpty(protocol)) { - case "TLSv1": - return TLS_1_0; - case "TLSv1.1": - return TLS_1_1; - case "TLSv1.2": - return TLS_1_2; - case "TLSv1.3": - return TLS_1_3; - default: - return UNKNOWN; - } + return switch (Strings.nullToEmpty(protocol)) { + case "TLSv1" -> TLS_1_0; + case "TLSv1.1" -> TLS_1_1; + case "TLSv1.2" -> TLS_1_2; + case "TLSv1.3" -> TLS_1_3; + default -> TLS_UNSUPPORTED_VERSION; + }; } } }