add connections with CM (not tested)
authorMazet Laurent <laurent.mazet@thalesgroup.com>
Thu, 5 Jun 2025 17:58:47 +0000 (19:58 +0200)
committerMazet Laurent <laurent.mazet@thalesgroup.com>
Thu, 5 Jun 2025 17:58:47 +0000 (19:58 +0200)
makefile
mapec.c
udp_valid.c
ulvpn.c

index 6e112547db4343a263a1367f192fc2d0b1d53bce..af2f212a75f930dc34604e460c37088d47c15fb8 100644 (file)
--- a/makefile
+++ b/makefile
@@ -144,7 +144,7 @@ gcov_%:
        $(MAKE) purge
        $(MAKE) depends
        OPTIONS="-coverage -O0" $(MAKE) ${@:gcov_%=%}.exe
-       $(MAKE) test_$(@:gcov_%=%)
+       umask 000; $(MAKE) test_$(@:gcov_%=%)
        gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g;s/ -l[^ ]*//g' $(@:gcov_%=%.ld)`
        $(MAKE) purge
        grep '^ *#####' *.c.gcov || true
diff --git a/mapec.c b/mapec.c
index 87f427add68be9fd15dfc4c425c0d3608e68a8da..4f8877f4d9e3c6955eefa45a8152f9343de88cab 100644 (file)
--- a/mapec.c
+++ b/mapec.c
@@ -88,7 +88,7 @@ void free_all_mapecs (void)
     }
 }
 
-void __attribute__ ((constructor)) _init_morep_ (void)
+void __attribute__ ((constructor)) _init_mapec_ (void)
 {
     atexit (free_all_mapecs);
 }
index 10fea07022e197f11f33941db7a38332bd32c4f6..15899600453a44d101ede1c6cc1d12c7f6f19d23 100644 (file)
@@ -490,7 +490,6 @@ int main (int argc, char **argv)
 }
 
 /* test: udp_valid.exe -h | grep usage */
-/* test: chmod a+w *.gcda */
 /* test: udp_valid.exe -l 2>&1 | grep 'log file not specified' */
 /* test: udp_valid.exe -r 2>&1 | grep 'receiver url not specified' */
 /* test: udp_valid.exe -s 2>&1 | grep 'service name not specified' */
diff --git a/ulvpn.c b/ulvpn.c
index 6138c733cf6badb9006a5f1991b76b3793bbf806..d4601205de7affa5683489fc93ce9b97ff7e1160 100644 (file)
--- a/ulvpn.c
+++ b/ulvpn.c
@@ -14,7 +14,7 @@
 
 /* depend: */
 /* cflags: */
-/* linker: mapec.o */
+/* linker: mapec.o -lmorep */
 
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <morep/morep.h>
+#include <morep/pdu_clear_data.h>
+#include <morep/pdu_encrypted_data.h>
+
 #include "mapec.h"
 #include "verbose.h"
 
 char *progname = NULL;
-char *version = "0.1";
+char *version = "0.9";
 
 char *devtun = "tun://tun0:1440";
 char *loctun = "tun://10.2.0.1";
 char *remtun = "tun://10.2.1.0";
 char *locudp = "udp://10.1.0.1:1234";
 char *remudp = "udp://10.1.0.2:1235";
+char *cmblack = "";
+char *cmred = "";
 
 int stop = 0;
 
@@ -44,6 +50,12 @@ int stop = 0;
 
 DECLARE_VERBOSE_LEVEL (ulvpn, INFO);
 
+typedef struct {
+    uint8_t aad[4];
+    int red;
+    int black;
+} cm_t;
+
 void sig_handler (int sig)
 {
     switch (sig) {
@@ -67,9 +79,143 @@ void usage (void)
     printf (" -u: remote udp (%s)\n", remudp);
     printf (" -v: program verbose level [%d..%d] (%d)\n", ERROR, TRACE, GET_VERBOSE_LEVEL (ulvpn));
     printf (" -V: library verbose level [%d..%d] (%d)\n", ERROR, TRACE, GET_VERBOSE_LEVEL (mapec));
+    printf (" -x: black CM service (%s)\n", cmblack);
+    printf (" -y: red CM service (%s)\n", cmred);
     printf ("%s version %s\n", progname, version);
 }
 
+int encrypt (uint8_t *buffer, int len, cm_t *cm)
+{
+
+    /* create clear  message */
+    CLEAR_DATA_t msg = {0};
+    msg.channel_id = 0;
+    msg.bypass_len = 0;
+    memcpy (msg.aad + sizeof (msg.aad) - sizeof (cm->aad), cm->aad, sizeof (cm->aad));
+    int npad =  16 - (len % 16);
+    if (len + npad > (int)sizeof (msg.data)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("too long payload (%d)\n", len));
+        len = sizeof (msg.data) - 1;
+        npad = 1;
+    }
+    VERBOSE (ulvpn, DEBUG, PRINTF ("padding %d byte%s\n", npad, (npad > 1) ? "s" : ""));
+    memcpy (msg.data, buffer, len);
+    msg.data[len + npad - 1] = npad;
+    //memset (buffer, 0, len);
+    msg.data_len = len + npad;
+
+    /* serialize message and send it */
+    uint8_t out[MAXPAYLOAD] = {0};
+    int out_len = serial_clear_data (&msg, out, sizeof (out));
+    if (out_len < 0) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("error when serializing clear message\n"));
+        return 0;
+    }
+    int seqtx = MOREP_Send (cm->red, 0x00, out, out_len);
+
+    /* get encrypted message and check it */
+    uint8_t in[MAXPAYLOAD] = {0};
+    uint8_t msgtype = 0;
+    int in_len = 0;
+    int seqrx = MOREP_Receive (cm->black, &msgtype, in, &in_len);
+    if ((msgtype != 0x01) || (in_len != out_len + 16) || (seqtx != seqrx)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent encrypyted message\n"));
+        return 0;
+    }
+    ENCRYPTED_DATA_t enc = {0};
+    if (!deserial_encrypted_data (in, in_len, &enc)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("error when deserializing encrypted message\n"));
+        return 0;
+    }
+
+    /* build output message */
+    len = 0;
+    //buf[len++] = enc.channel_id;
+    //check msg.bypass_len
+    memcpy (buffer + len, cm->aad, sizeof (cm->aad));
+    len += sizeof (cm->aad);
+    memcpy (buffer + len, enc.iv, sizeof (enc.iv));
+    len += sizeof (enc.iv);
+    memcpy (buffer + len, enc.data, enc.data_len);
+    len += enc.data_len;
+
+    return len;
+}
+
+int decrypt (uint8_t *buffer, int len, cm_t *cm)
+{
+
+    /* create encrypted  message */
+    ENCRYPTED_DATA_t enc = {0};
+    int i = 0;
+    //if (i + 1 > len) {
+    //    VERBOSE (ulvpn, WARNING, PRINTF ("no channel id\n");
+    //    return 0;
+    //}
+    //enc.channel_id = buffer[i++];
+    enc.bypass_len = 0;
+    if (i + (int)sizeof (cm->aad) > len) {
+        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted aad\n"));
+        return 0;
+    }
+    memcpy (enc.aad + sizeof (enc.aad) - sizeof (cm->aad), buffer + i, sizeof (cm->aad));
+    i += sizeof (cm->aad);
+    if (i + (int)sizeof (enc.iv) > len) {
+        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted iv\n"));
+        return 0;
+    }
+    memcpy (enc.iv, buffer + i, sizeof (enc.iv));
+    i += sizeof (enc.iv);
+    if (len - i < 32) {
+        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted tag\n"));
+        return 0;
+    }
+    if ((len - i) % 16 != 0) {
+        VERBOSE (ulvpn, ERROR, PRINTF ("incompleted encrypted message\n"));
+        return 0;
+    }
+    memcpy (enc.data, buffer + i, len - i);
+    enc.data_len = len - i;
+
+    /* serialize message and send it */
+    uint8_t out[MAXPAYLOAD] = {0};
+    int out_len = serial_encrypted_data (&enc, out, sizeof (out));
+    if (out_len < 0) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("error when serializing encrypted message\n"));
+        return 0;
+    }
+    int seqtx = MOREP_Send (cm->black, 0x02, out, out_len);
+
+    /* get clear message and check it */
+    uint8_t in[MAXPAYLOAD] = {0};
+    uint8_t msgtype = 0;
+    int in_len = 0;
+    int seqrx = MOREP_Receive (cm->red, &msgtype, in, &in_len);
+    if ((msgtype != 0x03) || (in_len != out_len - 16) || (seqtx != seqrx)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent decrypted message\n"));
+        return 0;
+    }
+    CLEAR_DATA_t msg = {0};
+    if (!deserial_clear_data (in, in_len, &msg)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("error when deserializing decrypted message\n"));
+        return 0;
+    }
+
+    /* build output message */
+    len = 0;
+    //buf[len++] = enc.channel_id;
+    //check msg.bypass_len
+    int npad = in[in_len - 1];
+    if ((npad > 16) || (msg.data_len < npad)) {
+        VERBOSE (ulvpn, WARNING, PRINTF ("non-coherent padding (%d)\n", npad));
+        return 0;
+    }
+    memcpy (buffer + len, enc.data, enc.data_len - npad);
+    len += enc.data_len - npad;
+
+    return len;
+}
+
 int main (int argc, char **argv)
 {
 
@@ -147,6 +293,22 @@ int main (int argc, char **argv)
             }
             CHANGE_VERBOSE_LEVEL (mapec, atoi (arg));
             break;
+        case 'x':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ulvpn, ERROR, PRINTF ("%s: black cm service not specified\n", progname));
+                return 1;
+            }
+            cmblack = arg;
+            break;
+        case 'y':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ulvpn, ERROR, PRINTF ("%s: red cm service not specified\n", progname));
+                return 1;
+            }
+            cmred = arg;
+            break;
         case 'h':
         default:
             usage ();
@@ -166,6 +328,19 @@ int main (int argc, char **argv)
         return -1;
     }
 
+    /* init crypto module */
+    cm_t cm = {{0, 0, 0, 0}, -1, -1};
+    if ((cmblack) && (*cmblack)) {
+        cm.black = MOREP_Connect (cmblack);
+    }
+    if ((cmred) && (*cmred)) {
+        cm.red = MOREP_Connect (cmred);
+    }
+    int cmok = (cm.black >= 0) && (cm.red >= 0);
+    if (!cmok) {
+        VERBOSE (ulvpn, INFO, PRINTF ("CM desactivated\n"));
+    }
+
     /* signals */
     signal(SIGINT, sig_handler);
     signal(SIGTERM, sig_handler);
@@ -199,7 +374,9 @@ int main (int argc, char **argv)
             } else {
                 VERBOSE (ulvpn, DEBUG, PRINTF ("received from tun %d bytes\n", r));
 
-                //encrypt it
+                if (cmok) {
+                    r = encrypt (buffer, r, &cm);
+                }
 
                 r = MAPEC_Send (udp_fd, buffer, r);
                 if (r < 0) {
@@ -220,7 +397,9 @@ int main (int argc, char **argv)
             } else {
                 VERBOSE (ulvpn, DEBUG, PRINTF ("received from udp %d bytes\n", r));
 
-                //decrypt it
+                if (cmok) {
+                    r = decrypt (buffer, r, &cm);
+                }
 
                 r = MAPEC_Send (tun_fd, buffer, r);
                 if (r < 0) {
@@ -244,7 +423,6 @@ int main (int argc, char **argv)
 }
 
 /* test: ulvpn.exe -h | grep usage */
-/* test: chmod a+w *.gcda */
 /* test: ulvpn.exe help 2>&1 | grep usage */
 /* test: ulvpn.exe -d 2>&1 | grep 'dev tun not specified' */
 /* test: ulvpn.exe -l 2>&1 | grep 'local tun not specified' */
@@ -253,6 +431,8 @@ int main (int argc, char **argv)
 /* test: ulvpn.exe -u 2>&1 | grep 'remote udp not specified' */
 /* test: ulvpn.exe -v 2>&1 | grep 'verbose level not specified' */
 /* test: ulvpn.exe -V 2>&1 | grep 'verbose level not specified' */
+/* test: ulvpn.exe -x 2>&1 | grep 'black cm service not specified' */
+/* test: ulvpn.exe -y 2>&1 | grep 'red cm service not specified' */
 
 /* test: sudo -u `awk -F: '/sh$/ && $3 != 0 {print $1; exit}' /etc/passwd` ulvpn.exe; test $? -ne 0 */