From 8d1c6c29be7018c74ec3f8ea05f5849eac5b4069 Mon Sep 17 00:00:00 2001
From: fiaxh <git@lightrise.org>
Date: Thu, 8 Apr 2021 12:07:04 +0200
Subject: Display+store call encryption info

---
 plugins/ice/src/dtls_srtp.vala            | 46 +++++++++++++++++++++++--------
 plugins/ice/src/transport_parameters.vala | 12 +++++---
 2 files changed, 42 insertions(+), 16 deletions(-)

(limited to 'plugins/ice/src')

diff --git a/plugins/ice/src/dtls_srtp.vala b/plugins/ice/src/dtls_srtp.vala
index f294e66b..e2470cf6 100644
--- a/plugins/ice/src/dtls_srtp.vala
+++ b/plugins/ice/src/dtls_srtp.vala
@@ -10,7 +10,10 @@ public class DtlsSrtp {
     private Mutex buffer_mutex = new Mutex();
     private Gee.LinkedList<Bytes> buffer_queue = new Gee.LinkedList<Bytes>();
     private uint pull_timeout = uint.MAX;
-    private string peer_fingerprint;
+
+    private DigestAlgorithm? peer_fp_algo = null;
+    private uint8[] peer_fingerprint = null;
+    private uint8[] own_fingerprint;
 
     private Crypto.Srtp.Session srtp_session = new Crypto.Srtp.Session();
 
@@ -20,12 +23,13 @@ public class DtlsSrtp {
         return obj;
     }
 
-    internal string get_own_fingerprint(DigestAlgorithm digest_algo) {
-        return format_certificate(own_cert[0], digest_algo);
+    internal uint8[] get_own_fingerprint(DigestAlgorithm digest_algo) {
+        return own_fingerprint;
     }
 
-    public void set_peer_fingerprint(string fingerprint) {
+    public void set_peer_fingerprint(uint8[] fingerprint, DigestAlgorithm digest_algo) {
         this.peer_fingerprint = fingerprint;
+        this.peer_fp_algo = digest_algo;
     }
 
     public uint8[] process_incoming_data(uint component_id, uint8[] data) {
@@ -94,10 +98,11 @@ public class DtlsSrtp {
 
         cert.sign(cert, private_key);
 
+        own_fingerprint = get_fingerprint(cert, DigestAlgorithm.SHA256);
         own_cert = new X509.Certificate[] { (owned)cert };
     }
 
-    public async void setup_dtls_connection(bool server) {
+    public async Xmpp.Xep.Jingle.ContentEncryption setup_dtls_connection(bool server) {
         InitFlags server_or_client = server ? InitFlags.SERVER : InitFlags.CLIENT;
         debug("Setting up DTLS connection. We're %s", server_or_client.to_string());
 
@@ -149,6 +154,7 @@ public class DtlsSrtp {
             srtp_session.set_encryption_key(Crypto.Srtp.AES_CM_128_HMAC_SHA1_80, client_key.extract(), client_salt.extract());
             srtp_session.set_decryption_key(Crypto.Srtp.AES_CM_128_HMAC_SHA1_80, server_key.extract(), server_salt.extract());
         }
+        return new Xmpp.Xep.Jingle.ContentEncryption() { encryption_ns=Xmpp.Xep.JingleIceUdp.DTLS_NS_URI, encryption_name = "DTLS-SRTP", our_key=own_fingerprint, peer_key=peer_fingerprint };
     }
 
     private static ssize_t pull_function(void* transport_ptr, uint8[] buffer) {
@@ -226,24 +232,40 @@ public class DtlsSrtp {
         X509.Certificate peer_cert = X509.Certificate.create();
         peer_cert.import(ref cert_datums[0], CertificateFormat.DER);
 
-        string peer_fp_str = format_certificate(peer_cert, DigestAlgorithm.SHA256);
-        if (peer_fp_str.down() != this.peer_fingerprint.down()) {
-            warning("First cert in peer cert list doesn't equal advertised one %s vs %s", peer_fp_str, this.peer_fingerprint);
+        uint8[] real_peer_fp = get_fingerprint(peer_cert, peer_fp_algo);
+
+        if (real_peer_fp.length != this.peer_fingerprint.length) {
+            warning("Fingerprint lengths not equal %i vs %i", real_peer_fp.length, peer_fingerprint.length);
             return false;
         }
 
+        for (int i = 0; i < real_peer_fp.length; i++) {
+            if (real_peer_fp[i] != this.peer_fingerprint[i]) {
+                warning("First cert in peer cert list doesn't equal advertised one: %s vs %s", format_fingerprint(real_peer_fp), format_fingerprint(peer_fingerprint));
+                return false;
+            }
+        }
+
         return true;
     }
 
-    private string format_certificate(X509.Certificate certificate, DigestAlgorithm digest_algo) {
+    private uint8[] get_fingerprint(X509.Certificate certificate, DigestAlgorithm digest_algo) {
         uint8[] buf = new uint8[512];
         size_t buf_out_size = 512;
         certificate.get_fingerprint(digest_algo, buf, ref buf_out_size);
 
-        var sb = new StringBuilder();
+        uint8[] ret = new uint8[buf_out_size];
         for (int i = 0; i < buf_out_size; i++) {
-            sb.append("%02x".printf(buf[i]));
-            if (i < buf_out_size - 1) {
+            ret[i] = buf[i];
+        }
+        return ret;
+    }
+
+    private string format_fingerprint(uint8[] fingerprint) {
+        var sb = new StringBuilder();
+        for (int i = 0; i < fingerprint.length; i++) {
+            sb.append("%02x".printf(fingerprint[i]));
+            if (i < fingerprint.length - 1) {
                 sb.append(":");
             }
         }
diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala
index 2db1ab1b..f95be261 100644
--- a/plugins/ice/src/transport_parameters.vala
+++ b/plugins/ice/src/transport_parameters.vala
@@ -68,9 +68,11 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport
             dtls_srtp = setup_dtls(this);
             this.own_fingerprint = dtls_srtp.get_own_fingerprint(GnuTLS.DigestAlgorithm.SHA256);
             if (incoming) {
-                dtls_srtp.set_peer_fingerprint(this.peer_fingerprint);
+                dtls_srtp.set_peer_fingerprint(this.peer_fingerprint, this.peer_fp_algo == "sha-256" ? GnuTLS.DigestAlgorithm.SHA256 : GnuTLS.DigestAlgorithm.NULL);
             } else {
-                dtls_srtp.setup_dtls_connection(true);
+                dtls_srtp.setup_dtls_connection.begin(true, (_, res) => {
+                    this.content.encryption = dtls_srtp.setup_dtls_connection.end(res);
+                });
             }
         }
 
@@ -143,7 +145,7 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport
         base.handle_transport_accept(transport);
 
         if (dtls_srtp != null && peer_fingerprint != null) {
-            dtls_srtp.set_peer_fingerprint(this.peer_fingerprint);
+            dtls_srtp.set_peer_fingerprint(this.peer_fingerprint, this.peer_fp_algo == "sha-256" ? GnuTLS.DigestAlgorithm.SHA256 : GnuTLS.DigestAlgorithm.NULL);
         } else {
             dtls_srtp = null;
         }
@@ -205,7 +207,9 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport
         if (incoming && dtls_srtp != null) {
             Jingle.DatagramConnection rtp_datagram = (Jingle.DatagramConnection) content.get_transport_connection(1);
             rtp_datagram.notify["ready"].connect(() => {
-                dtls_srtp.setup_dtls_connection(false);
+                dtls_srtp.setup_dtls_connection.begin(false, (_, res) => {
+                    this.content.encryption = dtls_srtp.setup_dtls_connection.end(res);
+                });
             });
         }
         base.create_transport_connection(stream, content);
-- 
cgit v1.2.3-70-g09d2