support tls-unique for TLSv1.2

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java     | 12 
src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java      |  6 
src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java | 16 
3 files changed, 30 insertions(+), 4 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/sasl/ChannelBinding.java 🔗

@@ -4,6 +4,8 @@ import android.util.Log;
 
 import com.google.common.base.CaseFormat;
 
+import java.util.Collection;
+
 import eu.siacs.conversations.Config;
 
 public enum ChannelBinding {
@@ -24,4 +26,14 @@ public enum ChannelBinding {
             return null;
         }
     }
+
+    public static ChannelBinding best(final Collection<ChannelBinding> bindings) {
+        if (bindings.contains(TLS_EXPORTER)) {
+            return TLS_EXPORTER;
+        } else if (bindings.contains(TLS_UNIQUE)) {
+            return TLS_UNIQUE;
+        } else {
+            return null;
+        }
+    }
 }

src/main/java/eu/siacs/conversations/crypto/sasl/SaslMechanism.java 🔗

@@ -103,11 +103,11 @@ public abstract class SaslMechanism {
 
         public SaslMechanism of(
                 final Collection<String> mechanisms, final Collection<ChannelBinding> bindings) {
+            final ChannelBinding channelBinding = ChannelBinding.best(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(ScramSha1Plus.MECHANISM) && channelBinding != null) {
+                return new ScramSha1Plus(account, channelBinding);
             } else if (mechanisms.contains(ScramSha512.MECHANISM)) {
                 return new ScramSha512(account);
             } else if (mechanisms.contains(ScramSha256.MECHANISM)) {

src/main/java/eu/siacs/conversations/crypto/sasl/ScramPlusMechanism.java 🔗

@@ -22,11 +22,25 @@ abstract class ScramPlusMechanism extends ScramMechanism {
             throw new AuthenticationException("Channel binding attempt on non secure socket");
         }
         if (this.channelBinding == ChannelBinding.TLS_EXPORTER) {
+            final byte[] keyingMaterial;
             try {
-                return Conscrypt.exportKeyingMaterial(sslSocket, EXPORTER_LABEL, new byte[0], 32);
+                keyingMaterial =
+                        Conscrypt.exportKeyingMaterial(sslSocket, EXPORTER_LABEL, new byte[0], 32);
             } catch (final SSLException e) {
                 throw new AuthenticationException("Could not export keying material");
             }
+            if (keyingMaterial == null) {
+                throw new AuthenticationException(
+                        "Could not export keying material. Socket not ready");
+            }
+            return keyingMaterial;
+        } else if (this.channelBinding == ChannelBinding.TLS_UNIQUE) {
+            final byte[] unique = Conscrypt.getTlsUnique(sslSocket);
+            if (unique == null) {
+                throw new AuthenticationException(
+                        "Could not retrieve tls unique. Socket not ready");
+            }
+            return unique;
         } else {
             throw new AuthenticationException(
                     String.format("%s is not a valid channel binding", ChannelBinding.NONE));