add (inactive) channel binding end-point code
This commit is contained in:
parent
d4ec1eaf38
commit
018e0d9edf
|
@ -1,11 +1,24 @@
|
||||||
package eu.siacs.conversations.crypto.sasl;
|
package eu.siacs.conversations.crypto.sasl;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.bouncycastle.jcajce.provider.digest.SHA256;
|
||||||
import org.conscrypt.Conscrypt;
|
import org.conscrypt.Conscrypt;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
import javax.net.ssl.SSLSocket;
|
import javax.net.ssl.SSLSocket;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
|
|
||||||
abstract class ScramPlusMechanism extends ScramMechanism {
|
abstract class ScramPlusMechanism extends ScramMechanism {
|
||||||
|
|
||||||
|
@ -41,9 +54,59 @@ abstract class ScramPlusMechanism extends ScramMechanism {
|
||||||
"Could not retrieve tls unique. Socket not ready");
|
"Could not retrieve tls unique. Socket not ready");
|
||||||
}
|
}
|
||||||
return unique;
|
return unique;
|
||||||
|
} else if (this.channelBinding == ChannelBinding.TLS_SERVER_END_POINT) {
|
||||||
|
final byte[] endPoint = getServerEndPointChannelBinding(sslSocket.getSession());
|
||||||
|
Log.d(Config.LOGTAG, "retrieved endpoint " + CryptoHelper.bytesToHex(endPoint));
|
||||||
|
return endPoint;
|
||||||
} else {
|
} else {
|
||||||
throw new AuthenticationException(
|
throw new AuthenticationException(
|
||||||
String.format("%s is not a valid channel binding", ChannelBinding.NONE));
|
String.format("%s is not a valid channel binding", ChannelBinding.NONE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] getServerEndPointChannelBinding(final SSLSession session)
|
||||||
|
throws AuthenticationException {
|
||||||
|
final Certificate[] certificates;
|
||||||
|
try {
|
||||||
|
certificates = session.getPeerCertificates();
|
||||||
|
} catch (final SSLPeerUnverifiedException e) {
|
||||||
|
throw new AuthenticationException("Could not verify peer certificates");
|
||||||
|
}
|
||||||
|
if (certificates == null || certificates.length == 0) {
|
||||||
|
throw new AuthenticationException("Could not retrieve peer certificate");
|
||||||
|
}
|
||||||
|
final X509Certificate certificate;
|
||||||
|
if (certificates[0] instanceof X509Certificate) {
|
||||||
|
certificate = (X509Certificate) certificates[0];
|
||||||
|
} else {
|
||||||
|
throw new AuthenticationException("Certificate was not X509");
|
||||||
|
}
|
||||||
|
final String algorithm = certificate.getSigAlgName();
|
||||||
|
final int withIndex = algorithm.indexOf("with");
|
||||||
|
if (withIndex <= 0) {
|
||||||
|
throw new AuthenticationException("Unable to parse SigAlgName");
|
||||||
|
}
|
||||||
|
final String hashAlgorithm = algorithm.substring(0, withIndex);
|
||||||
|
final MessageDigest messageDigest;
|
||||||
|
// https://www.rfc-editor.org/rfc/rfc5929#section-4.1
|
||||||
|
if ("MD5".equalsIgnoreCase(hashAlgorithm) || "SHA1".equalsIgnoreCase(hashAlgorithm)) {
|
||||||
|
messageDigest = new SHA256.Digest();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
messageDigest = MessageDigest.getInstance(hashAlgorithm);
|
||||||
|
} catch (final NoSuchAlgorithmException e) {
|
||||||
|
throw new AuthenticationException(
|
||||||
|
"Could not instantiate message digest for " + hashAlgorithm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(Config.LOGTAG, "hashing certificate with " + messageDigest.getAlgorithm());
|
||||||
|
final byte[] encodedCertificate;
|
||||||
|
try {
|
||||||
|
encodedCertificate = certificate.getEncoded();
|
||||||
|
} catch (final CertificateEncodingException e) {
|
||||||
|
throw new AuthenticationException("Could not encode certificate");
|
||||||
|
}
|
||||||
|
messageDigest.update(encodedCertificate);
|
||||||
|
return messageDigest.digest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue