summaryrefslogtreecommitdiff
path: root/src/irmd/tests/oap_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/tests/oap_test.c')
-rw-r--r--src/irmd/tests/oap_test.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/irmd/tests/oap_test.c b/src/irmd/tests/oap_test.c
new file mode 100644
index 00000000..e9f67505
--- /dev/null
+++ b/src/irmd/tests/oap_test.c
@@ -0,0 +1,273 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Unit tests of Ouroboros flow allocation protocol
+ * 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/.
+ */
+
+#include "config.h"
+
+#include "oap.c"
+
+#include <ouroboros/random.h>
+#include <ouroboros/test.h>
+
+static const char * pkp_str = \
+"-----BEGIN EC PRIVATE KEY-----\n"
+"MHcCAQEEIC13y+5jdKe80HBJD7WITpQamcn3rrkTX1r0v+JwSk4NoAoGCCqGSM49\n"
+"AwEHoUQDQgAEcC0yLAfUtufH8cdLybrdWPc6U+xRuhDhqqrEcBO5+eob2xyqEaNk\n"
+"nIV/86724zPptGRahWz0rzW2PvNppJdNBg==\n"
+"-----END EC PRIVATE KEY-----\n";
+
+/* Valid signed server certificate for server-2.unittest.o7s */
+static const char * crt_str = \
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDgjCCAyigAwIBAgICEAIwCgYIKoZIzj0EAwIwWzELMAkGA1UEBhMCQkUxDDAK\n"
+"BgNVBAgMA09WTDEMMAoGA1UECgwDbzdzMRUwEwYDVQQLDAx1bml0dGVzdC5vN3Mx\n"
+"GTAXBgNVBAMMEGltMi51bml0dGVzdC5vN3MwHhcNMjUwNzA0MTMxODI5WhcNMzUw\n"
+"NzAyMTMxODI5WjBwMQswCQYDVQQGEwJCRTEMMAoGA1UECAwDT1ZMMQ4wDAYDVQQH\n"
+"DAVHaGVudDEMMAoGA1UECgwDbzdzMRUwEwYDVQQLDAx1bml0dGVzdC5vN3MxHjAc\n"
+"BgNVBAMMFXNlcnZlci0yLnVuaXR0ZXN0Lm83czBZMBMGByqGSM49AgEGCCqGSM49\n"
+"AwEHA0IABHAtMiwH1Lbnx/HHS8m63Vj3OlPsUboQ4aqqxHATufnqG9scqhGjZJyF\n"
+"f/Ou9uMz6bRkWoVs9K81tj7zaaSXTQajggHFMIIBwTAJBgNVHRMEAjAAMBEGCWCG\n"
+"SAGG+EIBAQQEAwIGQDA6BglghkgBhvhCAQ0ELRYrR3JpbGxlZCBDaGVlc2UgR2Vu\n"
+"ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUTt3xHTwE9amoglxh\n"
+"cEMqWv+PpDMwgb8GA1UdIwSBtzCBtIAUFfeZRx8QWWKQr7Aw8zjDu2shvcShgZek\n"
+"gZQwgZExCzAJBgNVBAYTAkJFMQwwCgYDVQQIDANPVkwxDjAMBgNVBAcMBUdoZW50\n"
+"MQwwCgYDVQQKDANvN3MxFTATBgNVBAsMDHVuaXR0ZXN0Lm83czEZMBcGA1UEAwwQ\n"
+"Y2EyLnVuaXR0ZXN0Lm83czEkMCIGCSqGSIb3DQEJARYVZHVtbXlAb3Vyb2Jvcm9z\n"
+"LnJvY2tzggIQAjAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEw\n"
+"EQYDVR0fBAowCDAGoASgAoYAMCoGCCsGAQUFBwEBBB4wHDAMBggrBgEFBQcwAoYA\n"
+"MAwGCCsGAQUFBzABhgAwIAYDVR0RBBkwF4IVc2VydmVyLTEudW5pdHRlc3Qubzdz\n"
+"MAoGCCqGSM49BAMCA0gAMEUCIQDHuDb62w/Uah4nKwUFoJVkr4rgdNGh2Rn3SWaK\n"
+"0FV/gAIgOLKorTwSgrTFdyOUkuPOhRs8BEMpah+dp8UTO8AnLvY=\n"
+"-----END CERTIFICATE-----\n";
+
+static int test_oap_hdr_init_fini(void)
+{
+ struct oap_hdr oap_hdr;
+ struct timespec now;
+ uint64_t stamp;
+ buffer_t ephkey = BUF_INIT;
+ buffer_t data = BUF_INIT;
+ uint8_t buf[OAP_ID_SIZE];
+ buffer_t id;
+ void * pkp = NULL;
+ void * pubcrt = NULL;
+
+ TEST_START();
+
+ random_buffer(buf, OAP_ID_SIZE);
+ id.data = buf;
+ id.len = OAP_ID_SIZE;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ stamp = TS_TO_UINT64(now);
+
+ if (oap_hdr_init(id, pkp, pubcrt, ephkey, data, &oap_hdr) < 0) {
+ printf("Failed to init OAP request header.\n");
+ goto fail_req_hdr;
+ }
+
+ if (oap_hdr.hdr.len != OAP_HDR_MIN_SIZE) {
+ printf("OAP request header wrong: %zu < %zu.\n",
+ oap_hdr.hdr.len, OAP_HDR_MIN_SIZE);
+ goto fail_req_hdr_chk;
+ }
+
+ if (oap_hdr.id.len != OAP_ID_SIZE) {
+ printf("OAP request header ID wrong size: %zu != %zu.\n",
+ oap_hdr.id.len, (size_t) OAP_ID_SIZE);
+ goto fail_req_hdr_chk;
+ }
+
+ if (memcmp(oap_hdr.id.data, id.data, OAP_ID_SIZE) != 0) {
+ printf("OAP request header ID mismatch.\n");
+ goto fail_req_hdr_chk;
+ }
+
+ if (oap_hdr.timestamp < stamp) {
+ printf("OAP request header timestamp is too old.\n");
+ goto fail_req_hdr_chk;
+ }
+
+ if (oap_hdr.timestamp > stamp + 1 * BILLION) {
+ printf("OAP request header timestamp is too new.\n");
+ goto fail_req_hdr_chk;
+ }
+
+ oap_hdr_fini(&oap_hdr);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+
+ fail_req_hdr_chk:
+ oap_hdr_fini(&oap_hdr);
+ fail_req_hdr:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_oap_hdr_init_fini_data(void)
+
+{
+ struct oap_hdr oap_hdr;
+ buffer_t data;
+ buffer_t ephkey = BUF_INIT;
+ uint8_t buf[OAP_ID_SIZE];
+ buffer_t id;
+ void * pkp = NULL;
+ void * pubcrt = NULL;
+
+ TEST_START();
+
+ random_buffer(buf, OAP_ID_SIZE);
+ id.data = buf;
+ id.len = OAP_ID_SIZE;
+
+ data.len = 100;
+ data.data = malloc(data.len);
+ if (data.data == NULL) {
+ printf("Failed to allocate data buffer.\n");
+ goto fail_data;
+ }
+
+ random_buffer(data.data, data.len);
+
+ if (oap_hdr_init(id, pkp, pubcrt, ephkey, data, &oap_hdr) < 0) {
+ printf("Failed to create OAP request header.\n");
+ goto fail_req_hdr;
+ }
+
+ if (oap_hdr.hdr.len != OAP_HDR_MIN_SIZE + data.len) {
+ printf("OAP request header wrong: %zu < %zu.\n",
+ oap_hdr.hdr.len, OAP_HDR_MIN_SIZE + data.len);
+ goto fail_req_hdr_sz;
+ }
+
+ oap_hdr_fini(&oap_hdr);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+
+ fail_req_hdr_sz:
+ oap_hdr_fini(&oap_hdr);
+ fail_req_hdr:
+ freebuf(data);
+ fail_data:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_oap_hdr_init_fini_signed(void)
+{
+ struct oap_hdr oap_hdr;
+ buffer_t ephkey = BUF_INIT;
+ buffer_t data = BUF_INIT;
+ buffer_t sign;
+ buffer_t id;
+ uint8_t buf[OAP_ID_SIZE];
+ void * pkp;
+ void * pk;
+ void * pubcrt;
+ void * pubcrt2;
+
+ TEST_START();
+
+ random_buffer(buf, OAP_ID_SIZE);
+ id.data = buf;
+ id.len = OAP_ID_SIZE;
+
+ if (crypt_load_privkey_str(pkp_str, &pkp) < 0) {
+ printf("Failed to load private key.\n");
+ goto fail_pkp;
+ }
+
+ if (crypt_load_crt_str(crt_str, &pubcrt) < 0) {
+ printf("Failed to load public certificate.\n");
+ goto fail_pubcrt;
+ }
+
+ if (oap_hdr_init(id, pkp, pubcrt, ephkey, data, &oap_hdr) < 0) {
+ printf("Failed to create OAP request header.\n");
+ goto fail_req_hdr;
+ }
+
+ if (crypt_load_crt_der(oap_hdr.crt, &pubcrt2) < 0) {
+ printf("Failed to load public certificate from DER.\n");
+ goto fail_crt_der;
+ }
+
+ if (crypt_get_pubkey_crt(pubcrt2, &pk) < 0) {
+ printf("Failed to get public key from certificate.\n");
+ goto fail_crt_pk;
+ }
+
+ sign = oap_hdr.hdr;
+ sign.len -= (oap_hdr.sig.len + sizeof(uint16_t));
+
+ if (auth_verify_sig(pk, sign, oap_hdr.sig) < 0) {
+ printf("Failed to verify OAP request header signature.\n");
+ goto fail_check_sig;
+ }
+
+ oap_hdr_fini(&oap_hdr);
+
+ crypt_free_crt(pubcrt2);
+ crypt_free_crt(pubcrt);
+ crypt_free_key(pk);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+
+ fail_check_sig:
+ crypt_free_key(pk);
+ fail_crt_pk:
+ crypt_free_crt(pubcrt2);
+ fail_crt_der:
+ oap_hdr_fini(&oap_hdr);
+ fail_req_hdr:
+ crypt_free_crt(pubcrt);
+ fail_pubcrt:
+ crypt_free_key(pkp);
+ fail_pkp:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int oap_test(int argc,
+ char **argv)
+{
+ int ret = 0;
+
+ (void) argc;
+ (void) argv;
+
+ ret |= test_oap_hdr_init_fini();
+ ret |= test_oap_hdr_init_fini_data();
+#ifdef HAVE_OPENSSL
+ ret |= test_oap_hdr_init_fini_signed();
+#else
+ (void) test_oap_hdr_init_fini_signed;
+
+ ret = TEST_RC_SKIP;
+#endif
+ return ret;
+}