From 6d3d9dfe26a83fb49cbc12009bc5dfe1bea09704 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 6 Sep 2022 16:43:51 +0200 Subject: [PATCH] support channel binding with tls-exporter --- .../crypto/sasl/SaslMechanism.java | 19 ++++++++------- .../crypto/sasl/ScramMechanism.java | 3 ++- .../crypto/sasl/ScramPlusMechanism.java | 23 +++++++++++++++---- .../crypto/sasl/ScramSha1Plus.java | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java index 5fafde9e9..4380ad93c 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java @@ -18,6 +18,14 @@ public abstract class SaslMechanism { this.account = account; } + public static String namespace(final Version version) { + if (version == Version.SASL) { + return Namespace.SASL; + } else { + return Namespace.SASL_2; + } + } + /** * The priority is used to pin the authentication mechanism. If authentication fails, it MAY be * retried with another mechanism of the same priority, but MUST NOT be tried with a mechanism @@ -97,6 +105,9 @@ public abstract class SaslMechanism { final Collection mechanisms, final Collection bindings) { if (mechanisms.contains(External.MECHANISM) && account.getPrivateKeyAlias() != null) { return new External(account); + } else if (mechanisms.contains(ScramSha1Plus.MECHANISM) + && bindings.contains(ChannelBinding.TLS_EXPORTER)) { + return new ScramSha1Plus(account, ChannelBinding.TLS_EXPORTER); } else if (mechanisms.contains(ScramSha512.MECHANISM)) { return new ScramSha512(account); } else if (mechanisms.contains(ScramSha256.MECHANISM)) { @@ -115,12 +126,4 @@ public abstract class SaslMechanism { } } } - - public static String namespace(final Version version) { - if (version == Version.SASL) { - return Namespace.SASL; - } else { - return Namespace.SASL_2; - } - } } diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java index e6bc3a15d..62f221b74 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramMechanism.java @@ -258,7 +258,8 @@ abstract class ScramMechanism extends SaslMechanism { } } - protected byte[] getChannelBindingData(final SSLSocket sslSocket) throws AuthenticationException { + protected byte[] getChannelBindingData(final SSLSocket sslSocket) + throws AuthenticationException { if (this.channelBinding == ChannelBinding.NONE) { return new byte[0]; } diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java index 0067a4237..3b0dbb6e1 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java @@ -1,22 +1,35 @@ package eu.siacs.conversations.crypto.sasl; +import org.conscrypt.Conscrypt; + +import javax.net.ssl.SSLException; import javax.net.ssl.SSLSocket; import eu.siacs.conversations.entities.Account; abstract class ScramPlusMechanism extends ScramMechanism { + + private static final String EXPORTER_LABEL = "EXPORTER-Channel-Binding"; + ScramPlusMechanism(Account account, ChannelBinding channelBinding) { super(account, channelBinding); } @Override - protected byte[] getChannelBindingData(final SSLSocket sslSocket) throws AuthenticationException { - if (this.channelBinding == ChannelBinding.NONE) { - throw new AuthenticationException(String.format("%s is not a valid channel binding", ChannelBinding.NONE)); - } + protected byte[] getChannelBindingData(final SSLSocket sslSocket) + throws AuthenticationException { if (sslSocket == null) { throw new AuthenticationException("Channel binding attempt on non secure socket"); } - throw new AssertionError("not yet implemented"); + if (this.channelBinding == ChannelBinding.TLS_EXPORTER) { + try { + return Conscrypt.exportKeyingMaterial(sslSocket, EXPORTER_LABEL, new byte[0], 32); + } catch (final SSLException e) { + throw new AuthenticationException("Could not export keying material"); + } + } else { + throw new AuthenticationException( + String.format("%s is not a valid channel binding", ChannelBinding.NONE)); + } } } diff --git a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java index 34d9009fc..d4f2fcb0b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java +++ b/src/main/java/eu/siacs/conversations/crypto/sasl/ScramSha1Plus.java @@ -26,7 +26,7 @@ public class ScramSha1Plus extends ScramPlusMechanism { @Override public int getPriority() { - return 35; //higher than SCRAM-SHA512 (30) + return 35; // higher than SCRAM-SHA512 (30) } @Override