From f535637a394eecca1af182fb09b175b53e9fbf1f Mon Sep 17 00:00:00 2001
From: Dimitri Staessens <dimitri@ouroboros.rocks>
Date: Fri, 25 Feb 2022 18:44:12 +0100
Subject: lib: Encrypt bare FRCP messages on encrypted flows

Bare FRCP messages (ACKs without data, Rendez-vous packets) were not
encrypted on encrypted flows, causing the receiver to fail decryption.

Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
---
 src/lib/crypt.c | 23 +++++++++--------------
 src/lib/dev.c   |  3 +--
 src/lib/frct.c  | 47 +++++++++++++++++++----------------------------
 3 files changed, 29 insertions(+), 44 deletions(-)

(limited to 'src/lib')

diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index 043eae13..e19981bc 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -217,8 +217,7 @@ static int openssl_encrypt(struct flow *        f,
         in = shm_du_buff_head(sdb);
         in_sz = shm_du_buff_tail(sdb) - in;
 
-        if (in_sz == 0)
-                return 0;
+        assert(in_sz > 0);
 
         if (random_buffer(iv, IVSZ) < 0)
                 goto fail_iv;
@@ -229,11 +228,7 @@ static int openssl_encrypt(struct flow *        f,
 
         EVP_CIPHER_CTX_reset(f->ctx);
 
-        ret = EVP_EncryptInit_ex(f->ctx,
-                                 EVP_aes_256_cbc(),
-                                 NULL,
-                                 f->key,
-                                 iv);
+        ret = EVP_EncryptInit_ex(f->ctx, EVP_aes_256_cbc(), NULL, f->key, iv);
         if (ret != 1)
                 goto fail_encrypt_init;
 
@@ -287,13 +282,17 @@ static int openssl_decrypt(struct flow *        f,
         int       in_sz;
         int       tmp_sz;
 
+        in = shm_du_buff_head(sdb);
+        in_sz = shm_du_buff_tail(sdb) - in;
+        if (in_sz < IVSZ)
+                return -ECRYPT;
+
         in = shm_du_buff_head_release(sdb, IVSZ);
 
         memcpy(iv, in, IVSZ);
 
         in = shm_du_buff_head(sdb);
-
-        in_sz = shm_du_buff_tail(sdb) - shm_du_buff_head(sdb);
+        in_sz = shm_du_buff_tail(sdb) - in;
 
         out = malloc(in_sz);
         if (out == NULL)
@@ -301,11 +300,7 @@ static int openssl_decrypt(struct flow *        f,
 
         EVP_CIPHER_CTX_reset(f->ctx);
 
-        ret = EVP_DecryptInit_ex(f->ctx,
-                                 EVP_aes_256_cbc(),
-                                 NULL,
-                                 f->key,
-                                 iv);
+        ret = EVP_DecryptInit_ex(f->ctx, EVP_aes_256_cbc(), NULL, f->key, iv);
         if (ret != 1)
                 goto fail_decrypt_init;
 
diff --git a/src/lib/dev.c b/src/lib/dev.c
index 5c57a538..ab02a783 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -153,8 +153,6 @@ struct {
         pthread_rwlock_t      lock;
 } ai;
 
-#include "frct.c"
-
 static void port_destroy(struct port * p)
 {
         pthread_mutex_lock(&p->state_lock);
@@ -265,6 +263,7 @@ static void flow_clear(int fd)
 }
 
 #include "crypt.c"
+#include "frct.c"
 
 static void flow_fini(int fd)
 {
diff --git a/src/lib/frct.c b/src/lib/frct.c
index e9741aaf..2793f3c4 100644
--- a/src/lib/frct.c
+++ b/src/lib/frct.c
@@ -232,16 +232,29 @@ static void __send_frct_pkt(int      fd,
         pci->ackno = hton32(ackno);
 
         f = &ai.flows[fd];
+
+        pthread_rwlock_rdlock(&ai.lock);
+
+        if (f->qs.cypher_s > 0 && crypt_encrypt(f, sdb) < 0)
+                goto fail;
+
 #ifdef RXM_BLOCKING
-        if (shm_rbuff_write_b(f->tx_rb, idx, NULL)) {
+        if (shm_rbuff_write_b(f->tx_rb, idx, NULL))
 #else
-        if (shm_rbuff_write(f->tx_rb, idx)) {
+        if (shm_rbuff_write(f->tx_rb, idx))
 #endif
-                ipcp_sdb_release(sdb);
-                return;
-        }
+                goto fail;
 
         shm_flow_set_notify(f->set, f->flow_id, FLOW_PKT);
+
+        pthread_rwlock_unlock(&ai.lock);
+
+        return;
+
+ fail:
+        pthread_rwlock_unlock(&ai.lock);
+        ipcp_sdb_release(sdb);
+        return;
 }
 
 static void send_frct_pkt(struct frcti * frcti)
@@ -287,29 +300,7 @@ static void send_frct_pkt(struct frcti * frcti)
 
 static void __send_rdv(int fd)
 {
-        struct shm_du_buff * sdb;
-        struct frct_pci *    pci;
-        ssize_t              idx;
-        struct flow *        f;
-
-        /* Raw calls needed to bypass frcti. */
-        idx = shm_rdrbuff_alloc_b(ai.rdrb, sizeof(*pci), NULL, &sdb, NULL);
-        if (idx < 0)
-                return;
-
-        pci = (struct frct_pci *) shm_du_buff_head(sdb);
-        memset(pci, 0, sizeof(*pci));
-
-        pci->flags = FRCT_RDVS;
-
-        f = &ai.flows[fd];
-
-        if (shm_rbuff_write_b(f->tx_rb, idx, NULL)) {
-                ipcp_sdb_release(sdb);
-                return;
-        }
-
-        shm_flow_set_notify(f->set, f->flow_id, FLOW_PKT);
+        __send_frct_pkt(fd, FRCT_RDVS, 0, 0);
 }
 
 static struct frcti * frcti_create(int fd)
-- 
cgit v1.2.3