summaryrefslogtreecommitdiff
path: root/src/irmd/oap.c
diff options
context:
space:
mode:
authorDimitri Staessens <dmarc-noreply@freelists.org>2025-07-13 07:42:58 +0200
committerSander Vrijders <sander@ouroboros.rocks>2025-07-16 08:34:17 +0200
commit2e505c2dc7a7e849fe7a327f9cbdfc587477a3d1 (patch)
treec303098450a9a361d3d16738a78cbfdc452326f6 /src/irmd/oap.c
parent589e273a446cdcec7e9c5e3a85256b7b8554e4f0 (diff)
downloadouroboros-2e505c2dc7a7e849fe7a327f9cbdfc587477a3d1.tar.gz
ouroboros-2e505c2dc7a7e849fe7a327f9cbdfc587477a3d1.zip
irmd: Initial Flow Allocation Protocol Header
This adds the initial version for the flow allocation protocol header between IRMd instances. This is a step towards flow authentication. The header supports secure and authenticated flow allocation, supporting certificate-based authentication and ephemeral key exchange for end-to-end encryption. id: 128-bit identifier for the entity. timestamp: 64-bit timestamp (replay protection). certificate: Certificate for authentication. public key: ECDHE public key for key exchange. data: Application data. signature: Signature for integrity/authenticity. Authentication and encryption require OpenSSL to be installed. The IRMd compares the allocation request delay with the MPL of the Layer over which the flow allocation was sent. MPL is now reported by the Layer in ms instead of seconds. Time functions revised for consistency and adds some tests. The TPM can now print thread running times in Debug builds (TPM_DEBUG_REPORT_INTERVAL) and abort processes with hung threads (TPM_DEBUG_ABORT_TIMEOUT). Long running threads waiting for input should call tpm_wait_work() to avoid trigger a process abort. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/irmd/oap.c')
-rw-r--r--src/irmd/oap.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/irmd/oap.c b/src/irmd/oap.c
new file mode 100644
index 00000000..d5e5b7cc
--- /dev/null
+++ b/src/irmd/oap.c
@@ -0,0 +1,220 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Ouroboros flow allocation protocol header
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#if defined(__linux__) || defined(__CYGWIN__)
+ #define _DEFAULT_SOURCE
+#else
+ #define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <ouroboros/crypt.h>
+#include <ouroboros/endian.h>
+#include <ouroboros/time.h>
+
+#include "oap.h"
+
+#include <assert.h>
+
+int oap_hdr_init(buffer_t id,
+ void * pkp,
+ void * pubcrt,
+ buffer_t ephkey,
+ buffer_t data,
+ struct oap_hdr * oap_hdr)
+{
+ struct timespec now;
+ uint64_t stamp;
+ buffer_t hdr;
+ buffer_t der = BUF_INIT;
+ buffer_t sig = BUF_INIT;
+ buffer_t sign;
+ uint16_t len;
+ off_t offset;
+
+ assert(id.data != NULL && id.len == OAP_ID_SIZE);
+ assert(oap_hdr != NULL);
+ memset(oap_hdr, 0, sizeof(*oap_hdr));
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ stamp = hton64(TS_TO_UINT64(now));
+
+ if (pubcrt != NULL && crypt_crt_der(pubcrt, &der) < 0)
+ goto fail_der;
+
+ hdr.len = id.len +
+ sizeof(stamp) +
+ sizeof(len) + der.len +
+ sizeof(len) + ephkey.len +
+ sizeof(len) + data.len +
+ sizeof(len); /* sig len */
+
+ hdr.data = malloc(hdr.len);
+ if (hdr.data == NULL)
+ goto fail_hdr;
+
+ offset = 0;
+
+ memcpy(hdr.data, id.data, id.len);
+ offset += id.len;
+
+ memcpy(hdr.data + offset, &stamp, sizeof(stamp));
+ offset += sizeof(stamp);
+
+ /* pubcrt */
+ len = hton16((uint16_t) der.len);
+ memcpy(hdr.data + offset, &len, sizeof(len));
+ offset += sizeof(len);
+ if (der.len != 0)
+ memcpy(hdr.data + offset, der.data, der.len);
+ offset += der.len;
+
+ /* ephkey */
+ len = hton16((uint16_t) ephkey.len);
+ memcpy(hdr.data + offset, &len, sizeof(len));
+ offset += sizeof(len);
+ if (ephkey.len != 0)
+ memcpy(hdr.data + offset, ephkey.data, ephkey.len);
+ offset += ephkey.len;
+
+ /* data */
+ len = hton16((uint16_t) data.len);
+ memcpy(hdr.data + offset, &len, sizeof(len));
+ offset += sizeof(len);
+ if (data.len != 0)
+ memcpy(hdr.data + offset, data.data, data.len);
+ offset += data.len;
+
+ sign.data = hdr.data;
+ sign.len = hdr.len - sizeof(len);
+
+ if (pkp != NULL && auth_sign(pkp, sign, &sig) < 0)
+ goto fail_sig;
+
+ len = hton16((uint16_t) sig.len);
+ memcpy(hdr.data + offset, &len, sizeof(len));
+ offset += sizeof(len);
+
+ oap_hdr->hdr = hdr;
+
+ assert((size_t) offset == hdr.len);
+
+ if (sig.len > 0) {
+ oap_hdr->hdr.len += sig.len;
+ oap_hdr->hdr.data = realloc(hdr.data, oap_hdr->hdr.len);
+ if (oap_hdr->hdr.data == NULL)
+ goto fail_oap_hdr;
+
+ memcpy(oap_hdr->hdr.data + offset, sig.data, sig.len);
+ clrbuf(hdr);
+ }
+
+ if (oap_hdr_decode(oap_hdr->hdr, oap_hdr) < 0)
+ goto fail_decode;
+
+ freebuf(der);
+ freebuf(sig);
+
+ return 0;
+
+ fail_decode:
+ oap_hdr_fini(oap_hdr);
+ fail_oap_hdr:
+ freebuf(sig);
+ fail_sig:
+ freebuf(hdr);
+ fail_hdr:
+ freebuf(der);
+ fail_der:
+ memset(oap_hdr, 0, sizeof(*oap_hdr));
+ return -1;
+}
+
+void oap_hdr_fini(struct oap_hdr * oap_hdr)
+{
+ assert(oap_hdr != NULL);
+
+ freebuf(oap_hdr->hdr);
+ memset(oap_hdr, 0, sizeof(*oap_hdr));
+}
+
+int oap_hdr_decode(buffer_t hdr,
+ struct oap_hdr * oap_hdr)
+{
+ off_t offset;
+
+ assert(oap_hdr != NULL);
+ memset(oap_hdr, 0, sizeof(*oap_hdr));
+
+ if (hdr.len < OAP_HDR_MIN_SIZE)
+ goto fail_decode;
+
+ oap_hdr->id.data = hdr.data;
+ oap_hdr->id.len = OAP_ID_SIZE;
+
+ offset = OAP_ID_SIZE;
+
+ oap_hdr->timestamp = ntoh64(*(uint64_t *)(hdr.data + offset));
+
+ offset += sizeof(uint64_t);
+
+ oap_hdr->crt.len = (size_t) ntoh16(*(uint16_t *)(hdr.data + offset));
+ oap_hdr->crt.data = hdr.data + offset + sizeof(uint16_t);
+
+ offset += sizeof(uint16_t) + oap_hdr->crt.len;
+
+ if ((size_t) offset + sizeof(uint16_t) >= hdr.len)
+ goto fail_decode;
+
+ oap_hdr->eph.len = (size_t) ntoh16(*(uint16_t *)(hdr.data + offset));
+ oap_hdr->eph.data = hdr.data + offset + sizeof(uint16_t);
+
+ offset += sizeof(uint16_t) + oap_hdr->eph.len;
+
+ if ((size_t) offset + sizeof(uint16_t) >= hdr.len)
+ goto fail_decode;
+
+ oap_hdr->data.len = (size_t) ntoh16(*(uint16_t *)(hdr.data + offset));
+ oap_hdr->data.data = hdr.data + offset + sizeof(uint16_t);
+
+ offset += sizeof(uint16_t) + oap_hdr->data.len;
+
+ if ((size_t) offset + sizeof(uint16_t) > hdr.len)
+ goto fail_decode;
+
+ oap_hdr->sig.len = (size_t) ntoh16(*(uint16_t *)(hdr.data + offset));
+ oap_hdr->sig.data = hdr.data + offset + sizeof(uint16_t);
+
+ offset += sizeof(uint16_t) + oap_hdr->sig.len;
+
+ if ((size_t) offset != hdr.len)
+ goto fail_decode;
+
+ oap_hdr->hdr = hdr;
+
+ return 0;
+
+ fail_decode:
+ memset(oap_hdr, 0, sizeof(*oap_hdr));
+ return -1;
+}
+
+