summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ipcpd/ipcp.c51
-rw-r--r--src/ipcpd/ipcp.h3
-rw-r--r--src/ipcpd/unicast/dir/dht.c8
-rw-r--r--src/irmd/ipcp.c12
-rw-r--r--src/irmd/main.c14
-rw-r--r--src/irmd/reg/proc.h4
-rw-r--r--src/irmd/reg/tests/flow_test.c38
-rw-r--r--src/irmd/reg/tests/name_test.c43
-rw-r--r--src/irmd/reg/tests/proc_test.c25
-rw-r--r--src/irmd/reg/tests/prog_test.c22
-rw-r--r--src/irmd/reg/tests/reg_test.c114
-rw-r--r--src/lib/CMakeLists.txt4
-rw-r--r--src/lib/config.h.in1
-rw-r--r--src/lib/crypt.c577
-rw-r--r--src/lib/crypt/openssl.c744
-rw-r--r--src/lib/crypt/openssl.h106
-rw-r--r--src/lib/dev.c93
-rw-r--r--src/lib/frct.c2
-rw-r--r--src/lib/random.c20
-rw-r--r--src/lib/sockets.c22
-rw-r--r--src/lib/tests/CMakeLists.txt7
-rw-r--r--src/lib/tests/auth_test.c571
-rw-r--r--src/lib/tests/crypt_test.c256
-rw-r--r--src/lib/tests/sockets_test.c98
-rw-r--r--src/lib/tests/time_test.c6
-rw-r--r--src/lib/tests/tpm_test.c104
-rw-r--r--src/lib/tpm.c124
-rw-r--r--src/tools/oping/oping_server.c9
28 files changed, 2497 insertions, 581 deletions
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index c2678fc8..39b053d6 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -643,17 +643,17 @@ static void do_flow_dealloc(int flow_id,
static void * mainloop(void * o)
{
- int sfd;
- buffer_t buffer;
- ipcp_msg_t * msg;
+ int sfd;
+ buffer_t buffer;
+ ipcp_msg_t * msg;
(void) o;
while (true) {
- ipcp_msg_t ret_msg = IPCP_MSG__INIT;
- qosspec_t qs;
- struct cmd * cmd;
- buffer_t data;
+ ipcp_msg_t ret_msg = IPCP_MSG__INIT;
+ qosspec_t qs;
+ struct cmd * cmd;
+ buffer_t data;
ret_msg.code = IPCP_MSG_CODE__IPCP_REPLY;
@@ -679,7 +679,7 @@ static void * mainloop(void * o)
continue;
}
- tpm_dec(ipcpi.tpm);
+ tpm_begin_work(ipcpi.tpm);
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(free_msg, msg);
@@ -753,7 +753,7 @@ static void * mainloop(void * o)
if (buffer.len == 0) {
log_err("Failed to pack reply message");
close(sfd);
- tpm_inc(ipcpi.tpm);
+ tpm_end_work(ipcpi.tpm);
continue;
}
@@ -761,7 +761,7 @@ static void * mainloop(void * o)
if (buffer.data == NULL) {
log_err("Failed to create reply buffer.");
close(sfd);
- tpm_inc(ipcpi.tpm);
+ tpm_end_work(ipcpi.tpm);
continue;
}
@@ -770,16 +770,16 @@ static void * mainloop(void * o)
if (ret_msg.layer_info != NULL)
layer_info_msg__free_unpacked(ret_msg.layer_info, NULL);
- pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(free, buffer.data)
+ pthread_cleanup_push(__cleanup_close_ptr, &sfd);
if (write(sfd, buffer.data, buffer.len) == -1)
log_warn("Failed to send reply message");
- pthread_cleanup_pop(true);
- pthread_cleanup_pop(true);
+ pthread_cleanup_pop(true); /* close sfd */
+ pthread_cleanup_pop(true); /* free buffer.data */
- tpm_inc(ipcpi.tpm);
+ tpm_end_work(ipcpi.tpm);
}
return (void *) 0;
@@ -817,39 +817,38 @@ int ipcp_init(int argc,
{
bool log;
pthread_condattr_t cattr;
- int ret = -1;
if (parse_args(argc, argv, &log))
return -1;
log_init(log);
- ipcpi.irmd_fd = -1;
ipcpi.state = IPCP_NULL;
ipcpi.type = type;
#if defined (__linux__)
prctl(PR_SET_TIMERSLACK, IPCP_LINUX_SLACK_NS, 0, 0, 0);
#endif
- ipcpi.sock_path = ipcp_sock_path(getpid());
+ ipcpi.sock_path = sock_path(getpid(), IPCP_SOCK_PATH_PREFIX);
if (ipcpi.sock_path == NULL)
goto fail_sock_path;
ipcpi.sockfd = server_socket_open(ipcpi.sock_path);
if (ipcpi.sockfd < 0) {
- log_err("Could not open server socket.");
+ log_err("Failed to open server socket at %s.",
+ ipcpi.sock_path);
goto fail_serv_sock;
}
ipcpi.ops = ops;
if (pthread_mutex_init(&ipcpi.state_mtx, NULL)) {
- log_err("Could not create mutex.");
+ log_err("Failed to create mutex.");
goto fail_state_mtx;
}
if (pthread_condattr_init(&cattr)) {
- log_err("Could not create condattr.");
+ log_err("Failed to create condattr.");
goto fail_cond_attr;
}
@@ -857,7 +856,7 @@ int ipcp_init(int argc,
pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
#endif
if (pthread_cond_init(&ipcpi.state_cond, &cattr)) {
- log_err("Could not init condvar.");
+ log_err("Failed to init condvar.");
goto fail_state_cond;
}
@@ -891,6 +890,8 @@ int ipcp_init(int argc,
goto fail_rib_reg;
}
+ list_head_init(&ipcpi.cmds);
+
ipcpi.tpm = tpm_create(IPCP_MIN_THREADS, IPCP_ADD_THREADS,
mainloop, NULL);
if (ipcpi.tpm == NULL) {
@@ -898,8 +899,6 @@ int ipcp_init(int argc,
goto fail_tpm_create;
}
- list_head_init(&ipcpi.cmds);
-
ipcpi.alloc_id = -1;
pthread_condattr_destroy(&cattr);
@@ -931,7 +930,7 @@ int ipcp_init(int argc,
fail_serv_sock:
free(ipcpi.sock_path);
fail_sock_path:
- return ret;
+ return -1;
}
int ipcp_start(void)
@@ -952,8 +951,10 @@ int ipcp_start(void)
strcpy(info.name, ipcpi.name);
info.state = IPCP_OPERATIONAL;
- if (tpm_start(ipcpi.tpm))
+ if (tpm_start(ipcpi.tpm)) {
+ log_err("Failed to start threadpool manager.");
goto fail_tpm_start;
+ }
if (pthread_create(&ipcpi.acceptor, NULL, acceptloop, NULL)) {
log_err("Failed to create acceptor thread.");
diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h
index aab490c7..b29f0bf4 100644
--- a/src/ipcpd/ipcp.h
+++ b/src/ipcpd/ipcp.h
@@ -123,9 +123,6 @@ void ipcp_set_state(enum ipcp_state state);
enum ipcp_state ipcp_get_state(void);
-int ipcp_parse_arg(int argc,
- char * argv[]);
-
/* Helper functions to handle races during flow allocation */
int ipcp_wait_flow_req_arr(const uint8_t * dst,
qosspec_t qs,
diff --git a/src/ipcpd/unicast/dir/dht.c b/src/ipcpd/unicast/dir/dht.c
index 08a5a5a9..95c5f19a 100644
--- a/src/ipcpd/unicast/dir/dht.c
+++ b/src/ipcpd/unicast/dir/dht.c
@@ -884,12 +884,12 @@ static void lookup_update(struct dht * dht,
contact_destroy(c);
} else {
struct contact * d;
- list_add_tail(&c->next, p);
d = list_last_entry(&lu->contacts,
struct contact, next);
list_del(&d->next);
assert(lu->contacts.prv != &d->next);
contact_destroy(d);
+ list_add_tail(&c->next, p);
mod = true;
}
}
@@ -2503,7 +2503,7 @@ static void * dht_handle_packet(void * o)
continue;
}
- tpm_dec(dht->tpm);
+ tpm_begin_work(dht->tpm);
addr = msg->s_addr;
@@ -2604,7 +2604,7 @@ static void * dht_handle_packet(void * o)
free(resp_msg.addrs);
if (resp_msg.n_contacts == 0) {
- tpm_inc(dht->tpm);
+ tpm_end_work(dht->tpm);
continue;
}
@@ -2613,7 +2613,7 @@ static void * dht_handle_packet(void * o)
NULL);
free(resp_msg.contacts);
- tpm_inc(dht->tpm);
+ tpm_end_work(dht->tpm);
}
return (void *) 0;
diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c
index 5a9a79d3..28f870a7 100644
--- a/src/irmd/ipcp.c
+++ b/src/irmd/ipcp.c
@@ -83,7 +83,7 @@ ipcp_msg_t * send_recv_ipcp_msg(pid_t pid,
{
int sockfd;
uint8_t buf[SOCK_BUF_SIZE];
- char * sock_path;
+ char * spath;
ssize_t len;
ipcp_msg_t * recv_msg;
struct timeval tv;
@@ -94,17 +94,17 @@ ipcp_msg_t * send_recv_ipcp_msg(pid_t pid,
if (kill(pid, 0) < 0)
return NULL;
- sock_path = ipcp_sock_path(pid);
- if (sock_path == NULL)
+ spath = sock_path(pid, IPCP_SOCK_PATH_PREFIX);
+ if (spath == NULL)
return NULL;
- sockfd = client_socket_open(sock_path);
+ sockfd = client_socket_open(spath);
if (sockfd < 0) {
- free(sock_path);
+ free(spath);
return NULL;
}
- free(sock_path);
+ free(spath);
len = ipcp_msg__get_packed_size(msg);
if (len == 0 || len >= SOCK_BUF_SIZE) {
diff --git a/src/irmd/main.c b/src/irmd/main.c
index cc15078f..cf079698 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -72,7 +72,6 @@
#define IPCP_HASH_LEN(p) hash_len((p)->dir_hash_algo)
#define BIND_TIMEOUT 10 /* ms */
#define DEALLOC_TIME 300 /* s */
-#define MSGBUFSZ 2048
enum irm_state {
IRMD_NULL = 0,
@@ -1024,7 +1023,6 @@ static int flow_alloc(struct flow_info * flow,
log_info("Allocating flow for %d to %s.", flow->n_pid, dst);
-
if (flow->qs.cypher_s > 0) {
ssize_t key_len;
@@ -1380,7 +1378,7 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
res = disconnect_ipcp(msg->pid, msg->dst, msg->comp);
break;
case IRM_MSG_CODE__IRM_BIND_PROGRAM:
- /* Make exec NULL terminated instead of empty string terminated */
+ /* Terminate with NULL instead of "" */
free(msg->exec[msg->n_exec - 1]);
msg->exec[msg->n_exec - 1] = NULL;
res = bind_program(msg->exec, msg->name, msg->opts);
@@ -1540,7 +1538,7 @@ static void * mainloop(void * o)
continue;
}
- tpm_dec(irmd.tpm);
+ tpm_begin_work(irmd.tpm);
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(free_msg, msg);
@@ -1556,12 +1554,12 @@ static void * mainloop(void * o)
}
if (ret_msg->result == -EPIPE) {
- log_dbg("Terminated command: application closed socket.");
+ log_dbg("Terminated command: remote closed socket.");
goto fail;
}
if (ret_msg->result == -EIRMD) {
- log_dbg("Terminated command: IRMd not in running state.");
+ log_dbg("Terminated command: IRMd not running.");
goto fail;
}
@@ -1596,14 +1594,14 @@ static void * mainloop(void * o)
pthread_cleanup_pop(true);
pthread_cleanup_pop(true);
- tpm_inc(irmd.tpm);
+ tpm_end_work(irmd.tpm);
continue;
fail:
irm_msg__free_unpacked(ret_msg, NULL);
fail_msg:
close(sfd);
- tpm_inc(irmd.tpm);
+ tpm_end_work(irmd.tpm);
continue;
}
diff --git a/src/irmd/reg/proc.h b/src/irmd/reg/proc.h
index 99f74fef..499ecc72 100644
--- a/src/irmd/reg/proc.h
+++ b/src/irmd/reg/proc.h
@@ -32,8 +32,8 @@ struct reg_proc {
struct proc_info info;
- struct list_head names; /* names for which process accepts flows */
- size_t n_names; /* number of names */
+ struct list_head names; /* process accepts flows for names */
+ size_t n_names; /* number of names */
struct shm_flow_set * set;
};
diff --git a/src/irmd/reg/tests/flow_test.c b/src/irmd/reg/tests/flow_test.c
index f9d23fd1..3e586341 100644
--- a/src/irmd/reg/tests/flow_test.c
+++ b/src/irmd/reg/tests/flow_test.c
@@ -28,7 +28,7 @@
#define TEST_DATA "testpiggybackdata"
-static int test_reg_flow_create(void)
+static int test_reg_flow_create_destroy(void)
{
struct reg_flow * f;
@@ -51,10 +51,10 @@ static int test_reg_flow_create(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_flow_create_no_id(void) {
@@ -67,7 +67,7 @@ static int test_reg_flow_create_no_id(void) {
reg_flow_create(&info); /* assert fail */
- return 0;
+ return TEST_RC_SUCCESS;
}
static int test_reg_flow_create_no_pid(void) {
@@ -80,7 +80,7 @@ static int test_reg_flow_create_no_pid(void) {
reg_flow_create(&info); /* assert fail */
- return 0;
+ return TEST_RC_SUCCESS;
}
static int test_reg_flow_create_has_n_1_pid(void) {
@@ -94,7 +94,7 @@ static int test_reg_flow_create_has_n_1_pid(void) {
reg_flow_create(&info); /* assert fail */
- return 0;
+ return TEST_RC_SUCCESS;
}
static int test_reg_flow_create_wrong_state(void) {
@@ -108,7 +108,7 @@ static int test_reg_flow_create_wrong_state(void) {
reg_flow_create(&info); /* assert fail */
- return 0;
+ return TEST_RC_SUCCESS;
}
static int test_reg_flow_create_has_mpl(void) {
@@ -123,7 +123,7 @@ static int test_reg_flow_create_has_mpl(void) {
reg_flow_create(&info); /* assert fail */
- return 0;
+ return TEST_RC_SUCCESS;
}
static int test_reg_flow_update(void)
@@ -163,10 +163,10 @@ static int test_reg_flow_update(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_flow_update_wrong_id(void)
@@ -199,10 +199,10 @@ static int test_reg_flow_update_wrong_id(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_flow_assert_fails(void)
@@ -210,15 +210,10 @@ static int test_reg_flow_assert_fails(void)
int ret = 0;
ret |= test_assert_fail(test_reg_flow_create_no_id);
-
ret |= test_assert_fail(test_reg_flow_create_no_pid);
-
ret |= test_assert_fail(test_reg_flow_create_has_n_1_pid);
-
ret |= test_assert_fail(test_reg_flow_create_wrong_state);
-
ret |= test_assert_fail(test_reg_flow_create_has_mpl);
-
ret |= test_assert_fail(test_reg_flow_update_wrong_id);
return ret;
@@ -267,11 +262,11 @@ static int test_flow_data(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
free(data);
TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
int flow_test(int argc,
@@ -282,12 +277,9 @@ int flow_test(int argc,
(void) argc;
(void) argv;
- ret |= test_reg_flow_create();
-
+ ret |= test_reg_flow_create_destroy();
ret |= test_reg_flow_update();
-
ret |= test_reg_flow_assert_fails();
-
ret |= test_flow_data();
return ret;
diff --git a/src/irmd/reg/tests/name_test.c b/src/irmd/reg/tests/name_test.c
index 48f132e9..64635eec 100644
--- a/src/irmd/reg/tests/name_test.c
+++ b/src/irmd/reg/tests/name_test.c
@@ -20,8 +20,11 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
+
#include "../name.c"
+#include <ouroboros/test.h>
+
#define TEST_PID 65534
#define TEST_PROG "/usr/bin/testprog"
#define TEST_NAME "testservicename"
@@ -34,6 +37,8 @@ static int test_reg_name_create(void)
.pol_lb = LB_RR,
};
+ TEST_START();
+
n = reg_name_create(&info);
if (n == NULL) {
printf("Failed to create name %s.\n", info.name);
@@ -42,9 +47,12 @@ static int test_reg_name_create(void)
reg_name_destroy(n);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
static int test_reg_name_add_proc(void)
@@ -55,6 +63,8 @@ static int test_reg_name_add_proc(void)
.pol_lb = LB_RR,
};
+ TEST_START();
+
n = reg_name_create(&info);
if (n == NULL) {
printf("Failed to create name %s.\n", info.name);
@@ -85,9 +95,12 @@ static int test_reg_name_add_proc(void)
reg_name_destroy(n);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
static int test_reg_name_add_prog(void)
@@ -100,6 +113,8 @@ static int test_reg_name_add_prog(void)
char * exec[] = { TEST_PROG, "--argswitch", "argvalue", NULL};
+ TEST_START();
+
n = reg_name_create(&info);
if (n == NULL) {
printf("Failed to create name %s.\n", info.name);
@@ -130,9 +145,12 @@ static int test_reg_name_add_prog(void)
reg_name_destroy(n);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
static int test_reg_name_add_active(enum pol_balance lb)
@@ -144,6 +162,8 @@ static int test_reg_name_add_active(enum pol_balance lb)
.pol_lb = lb,
};
+ TEST_START();
+
n = reg_name_create(&info);
if (n == NULL) {
printf("Failed to create name %s.\n", info.name);
@@ -255,9 +275,12 @@ static int test_reg_name_add_active(enum pol_balance lb)
reg_name_destroy(n);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
@@ -270,13 +293,9 @@ int name_test(int argc,
(void) argv;
res |= test_reg_name_create();
-
res |= test_reg_name_add_proc();
-
res |= test_reg_name_add_prog();
-
res |= test_reg_name_add_active(LB_RR);
-
res |= test_reg_name_add_active(LB_SPILL);
return res;
diff --git a/src/irmd/reg/tests/proc_test.c b/src/irmd/reg/tests/proc_test.c
index 5c9dd865..df0527fb 100644
--- a/src/irmd/reg/tests/proc_test.c
+++ b/src/irmd/reg/tests/proc_test.c
@@ -22,10 +22,12 @@
#include "../proc.c"
+#include <ouroboros/test.h>
+
#define TEST_PID 65534
#define TEST_PROG "usr/bin/testprog"
-static int test_reg_proc_create(void)
+static int test_reg_proc_create_destroy(void)
{
struct reg_proc * proc;
struct proc_info info = {
@@ -33,6 +35,8 @@ static int test_reg_proc_create(void)
.prog = TEST_PROG
};
+ TEST_START();
+
proc = reg_proc_create(&info);
if (proc == NULL) {
printf("Failed to create proc.\n");
@@ -41,9 +45,12 @@ static int test_reg_proc_create(void)
reg_proc_destroy(proc);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
static int test_reg_proc_add_name(void)
@@ -56,6 +63,8 @@ static int test_reg_proc_add_name(void)
char * name = "testname";
+ TEST_START();
+
proc = reg_proc_create(&info);
if (proc == NULL) {
printf("Failed to create proc.\n");
@@ -86,9 +95,12 @@ static int test_reg_proc_add_name(void)
reg_proc_destroy(proc);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
int proc_test(int argc,
@@ -99,8 +111,7 @@ int proc_test(int argc,
(void) argc;
(void) argv;
- res |= test_reg_proc_create();
-
+ res |= test_reg_proc_create_destroy();
res |= test_reg_proc_add_name();
return res;
diff --git a/src/irmd/reg/tests/prog_test.c b/src/irmd/reg/tests/prog_test.c
index 5e6931d8..c394c222 100644
--- a/src/irmd/reg/tests/prog_test.c
+++ b/src/irmd/reg/tests/prog_test.c
@@ -22,8 +22,9 @@
#include "../prog.c"
-#define TEST_PROG "usr/bin/testprog"
+#include <ouroboros/test.h>
+#define TEST_PROG "usr/bin/testprog"
static int test_reg_prog_create(void)
{
@@ -32,6 +33,8 @@ static int test_reg_prog_create(void)
.name = TEST_PROG
};
+ TEST_START();
+
prog = reg_prog_create(&info);
if (prog == NULL) {
printf("Failed to create prog.\n");
@@ -40,9 +43,12 @@ static int test_reg_prog_create(void)
reg_prog_destroy(prog);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
static int test_reg_prog_add_name(void)
@@ -54,6 +60,8 @@ static int test_reg_prog_add_name(void)
char * name = "testname";
+ TEST_START();
+
prog = reg_prog_create(&info);
if (prog == NULL) {
printf("Failed to create prog.\n");
@@ -84,9 +92,12 @@ static int test_reg_prog_add_name(void)
reg_prog_destroy(prog);
- return 0;
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
fail:
- return -1;
+ TEST_FAIL();
+ return TEST_RC_FAIL;
}
int prog_test(int argc,
@@ -98,7 +109,6 @@ int prog_test(int argc,
(void) argv;
ret |= test_reg_prog_create();
-
ret |= test_reg_prog_add_name();
return ret;
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index c341c297..80fc64d6 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -51,10 +51,10 @@ static int test_reg_init(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_create_flow(void)
@@ -105,10 +105,10 @@ static int test_reg_create_flow(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_allocate_flow_timeout(void)
@@ -179,10 +179,10 @@ static int test_reg_allocate_flow_timeout(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static void * test_flow_respond_alloc(void * o)
@@ -321,10 +321,10 @@ static int test_reg_accept_flow_success(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_accept_flow_success_no_crypt(void)
@@ -416,10 +416,10 @@ static int test_reg_accept_flow_success_no_crypt(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
@@ -486,23 +486,19 @@ static int test_reg_allocate_flow_fail(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_flow(void) {
int ret = 0;
ret |= test_reg_create_flow();
-
ret |= test_reg_allocate_flow_timeout();
-
ret |= test_reg_accept_flow_success();
-
ret |= test_reg_accept_flow_success_no_crypt();
-
ret |= test_reg_allocate_flow_fail();
return ret;
@@ -552,10 +548,10 @@ static int test_reg_create_ipcp(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_set_layer(void)
@@ -614,10 +610,10 @@ static int test_set_layer(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_ipcp(void)
@@ -625,7 +621,6 @@ static int test_reg_ipcp(void)
int ret = 0;
ret |= test_reg_create_ipcp();
-
ret |= test_set_layer();
return ret;
@@ -674,10 +669,10 @@ static int test_reg_create_name(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_name(void)
@@ -732,10 +727,10 @@ static int test_reg_create_proc(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_proc(void)
@@ -785,10 +780,10 @@ static int test_reg_spawned(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_create_prog(void)
@@ -833,10 +828,10 @@ static int test_reg_create_prog(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_reg_prog(void)
@@ -900,10 +895,10 @@ static int test_bind_proc(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_bind_prog(void)
@@ -989,10 +984,10 @@ static int test_bind_prog(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_inherit_prog(void)
@@ -1060,10 +1055,10 @@ static int test_inherit_prog(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_accepting_timeout(void)
@@ -1106,10 +1101,10 @@ static int test_wait_accepting_timeout(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_accepting_fail_name(void)
@@ -1140,10 +1135,10 @@ static int test_wait_accepting_fail_name(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static void * test_call_flow_accept(void * o)
@@ -1242,10 +1237,10 @@ static int test_wait_accepting_success(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_accepting(void)
@@ -1253,9 +1248,7 @@ static int test_wait_accepting(void)
int ret = 0;
ret |= test_wait_accepting_timeout();
-
ret |= test_wait_accepting_fail_name();
-
ret |= test_wait_accepting_success();
return ret;
@@ -1300,10 +1293,10 @@ static int test_wait_ipcp_boot_timeout(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static void * test_ipcp_respond(void * o)
@@ -1371,10 +1364,10 @@ static int test_wait_ipcp_boot_fail(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_ipcp_boot_success(void)
@@ -1433,10 +1426,10 @@ static int test_wait_ipcp_boot_success(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_ipcp_boot(void)
@@ -1444,9 +1437,7 @@ static int test_wait_ipcp_boot(void)
int ret = 0;
ret |= test_wait_ipcp_boot_timeout();
-
ret |= test_wait_ipcp_boot_fail();
-
ret |= test_wait_ipcp_boot_success();
return ret;
@@ -1477,10 +1468,10 @@ static int test_wait_proc_timeout(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static void * test_proc(void * o)
@@ -1527,10 +1518,10 @@ static int test_wait_proc_success(void)
TEST_SUCCESS();
- return 0;
+ return TEST_RC_SUCCESS;
fail:
REG_TEST_FAIL();
- return -1;
+ return TEST_RC_FAIL;
}
static int test_wait_proc(void)
@@ -1538,7 +1529,6 @@ static int test_wait_proc(void)
int ret = 0;
ret |= test_wait_proc_timeout();
-
ret |= test_wait_proc_success();
return ret;
@@ -1554,29 +1544,17 @@ int reg_test(int argc,
(void) argv;
ret |= test_reg_init();
-
ret |= test_reg_flow();
-
ret |= test_reg_ipcp();
-
ret |= test_reg_name();
-
ret |= test_reg_proc();
-
ret |= test_reg_prog();
-
ret |= test_reg_spawned();
-
ret |= test_bind_proc();
-
ret |= test_bind_prog();
-
ret |= test_inherit_prog();
-
ret |= test_wait_accepting();
-
ret |= test_wait_ipcp_boot();
-
ret |= test_wait_proc();
return ret;
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 231eb785..cc73a9fc 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -121,6 +121,7 @@ if (OPENSSL_FOUND)
unset(HAVE_OPENSSL)
endif()
endif ()
+ set(OPENSSL_SOURCES crypt/openssl.c)
else()
message(STATUS "Install openSSL version >= \"1.1.0\" to enable OpenSSL support")
unset(HAVE_OPENSSL_RNG)
@@ -128,6 +129,7 @@ else()
set(OPENSSL_INCLUDE_DIR "")
set(OPENSSL_LIBRARIES "")
set(OPENSSL_CRYPTO_LIBRARY "")
+ set(OPENSSL_SOURCES "")
endif ()
if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
@@ -284,7 +286,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
add_library(ouroboros-common SHARED ${SOURCE_FILES_COMMON} ${IRM_PROTO_SRCS}
${IPCP_PROTO_SRCS} ${IPCP_CONFIG_PROTO_SRCS} ${MODEL_PROTO_SRCS}
- ${ENROLL_PROTO_SRCS})
+ ${ENROLL_PROTO_SRCS} ${OPENSSL_SOURCES})
add_library(ouroboros-dev SHARED ${SOURCE_FILES_DEV} ${CEP_PROTO_SRCS})
diff --git a/src/lib/config.h.in b/src/lib/config.h.in
index 604038b4..21a30493 100644
--- a/src/lib/config.h.in
+++ b/src/lib/config.h.in
@@ -23,6 +23,7 @@
#cmakedefine HAVE_SYS_RANDOM
#cmakedefine HAVE_LIBGCRYPT
#cmakedefine HAVE_OPENSSL
+#cmakedefine OPENSS_VERSION_MAJOR @OPENSSL_VERSION_MAJOR@
#ifdef HAVE_OPENSSL
#define HAVE_ENCRYPTION
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index ad679501..756fcccc 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -1,8 +1,7 @@
/*
* Ouroboros - Copyright (C) 2016 - 2024
*
- * Elliptic curve Diffie-Hellman key exchange and
- * AES encryption for flows using OpenSSL
+ * Cryptographic operations
*
* Dimitri Staessens <dimitri@ouroboros.rocks>
* Sander Vrijders <sander@ouroboros.rocks>
@@ -20,436 +19,386 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
+
#include <config.h>
#include <ouroboros/crypt.h>
#include <ouroboros/errno.h>
+#ifdef HAVE_OPENSSL
+ #include "crypt/openssl.h"
+#endif /* HAVE_OPENSSL */
#include <assert.h>
#include <string.h>
-#ifdef HAVE_OPENSSL
-
-#include <ouroboros/hash.h>
-#include <ouroboros/random.h>
-
-#include <openssl/evp.h>
-#include <openssl/ec.h>
-#include <openssl/pem.h>
-
-#include <openssl/bio.h>
+struct crypt_ctx {
+ uint16_t flags;
+ void * ctx;
+ uint8_t key[SYMMKEYSZ];
+};
-#define IVSZ 16
-/* SYMMKEYSZ defined in dev.c */
+struct auth_ctx {
+ void * store;
+};
-/*
- * Derive the common secret from
- * your public key pair (kp)
- * the remote public key (pub).
- * Store it in a preallocated buffer (s).
- */
-static int __openssl_ecdh_derive_secret(EVP_PKEY * kp,
- EVP_PKEY * pub,
- uint8_t * s)
+int crypt_dh_pkp_create(void ** pkp,
+ uint8_t * pk)
{
- EVP_PKEY_CTX * ctx;
- int ret;
- uint8_t * secret;
- size_t secret_len;
-
- ctx = EVP_PKEY_CTX_new(kp, NULL);
- if (ctx == NULL)
- goto fail_new;
-
- ret = EVP_PKEY_derive_init(ctx);
- if (ret != 1)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive_set_peer(ctx, pub);
- if (ret != 1)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive(ctx, NULL, &secret_len);
- if (ret != 1)
- goto fail_ctx;
-
- if (secret_len < SYMMKEYSZ)
- goto fail_ctx;
-
- secret = OPENSSL_malloc(secret_len);
- if (secret == NULL)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive(ctx, secret, &secret_len);
- if (ret != 1)
- goto fail_derive;
-
- /* Hash the secret for use as AES key. */
- mem_hash(HASH_SHA3_256, s, secret, secret_len);
+#ifdef HAVE_OPENSSL
+ assert(pkp != NULL);
+ *pkp = NULL;
+ return openssl_ecdh_pkp_create(pkp, pk);
+#else
+ (void) pkp;
+ (void) pk;
- OPENSSL_free(secret);
- EVP_PKEY_CTX_free(ctx);
+ *pkp = NULL;
return 0;
-
- fail_derive:
- OPENSSL_free(secret);
- fail_ctx:
- EVP_PKEY_CTX_free(ctx);
- fail_new:
- return -ECRYPT;
+#endif
}
-static int __openssl_ecdh_gen_key(void ** kp)
+void crypt_dh_pkp_destroy(void * pkp)
{
- EVP_PKEY_CTX * ctx = NULL;
- EVP_PKEY_CTX * kctx = NULL;
- EVP_PKEY * params = NULL;
- int ret;
-
- ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
- if (ctx == NULL)
- goto fail_new_id;
-
- ret = EVP_PKEY_paramgen_init(ctx);
- if (ret != 1)
- goto fail_paramgen;
-
- ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1);
- if (ret != 1)
- goto fail_paramgen;
-
- ret = EVP_PKEY_paramgen(ctx, &params);
- if (ret != 1)
- goto fail_paramgen;
-
- kctx = EVP_PKEY_CTX_new(params, NULL);
- if (kctx == NULL)
- goto fail_keygen_init;
-
- ret = EVP_PKEY_keygen_init(kctx);
- if (ret != 1)
- goto fail_keygen;
-
- ret = EVP_PKEY_keygen(kctx, (EVP_PKEY **) kp);
- if (ret != 1)
- goto fail_keygen;
+#ifdef HAVE_OPENSSL
+ openssl_ecdh_pkp_destroy(pkp);
+#else
+ (void) pkp;
+ return;
+#endif
+}
- EVP_PKEY_free(params);
- EVP_PKEY_CTX_free(kctx);
- EVP_PKEY_CTX_free(ctx);
+int crypt_dh_derive(void * pkp,
+ buffer_t pk,
+ uint8_t * s)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_ecdh_derive(pkp, pk, s);
+#else
+ (void) pkp;
+ (void) pk;
- return 0;
+ memset(s, 0, SYMMKEYSZ);
- fail_keygen:
- EVP_PKEY_CTX_free(kctx);
- fail_keygen_init:
- EVP_PKEY_free(params);
- fail_paramgen:
- EVP_PKEY_CTX_free(ctx);
- fail_new_id:
return -ECRYPT;
+#endif
}
-static ssize_t openssl_ecdh_pkp_create(void ** pkp,
- uint8_t * pk)
+int crypt_encrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
{
- uint8_t * pos;
- ssize_t len;
-
- assert(pkp != NULL);
- assert(*pkp == NULL);
- assert(pk != NULL);
-
- if (__openssl_ecdh_gen_key(pkp) < 0)
- return -ECRYPT;
-
- assert(*pkp != NULL);
-
- pos = pk; /* i2d_PUBKEY increments the pointer, don't use buf! */
- len = i2d_PUBKEY(*pkp, &pos);
- if (len < 0) {
- EVP_PKEY_free(*pkp);
- return -ECRYPT;
+ if (ctx->flags == 0) {
+ clrbuf(*out);
+ return 0;
}
- return len;
-}
+#ifdef HAVE_OPENSSL
+ return openssl_encrypt(ctx->ctx, ctx->key, in, out);
+#else
+ (void) in;
+ (void) out;
-static void openssl_ecdh_pkp_destroy(void * pkp)
-{
- EVP_PKEY_free((EVP_PKEY *) pkp);
+ return -ECRYPT;
+#endif
}
-static int openssl_ecdh_derive(void * pkp,
- buffer_t pk,
- uint8_t * s)
+int crypt_decrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
{
- uint8_t * pos;
- EVP_PKEY * pub;
-
- pos = pk.data; /* d2i_PUBKEY increments the pointer, don't use key ptr! */
- pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) pk.len);
- if (pub == NULL)
- return -ECRYPT;
-
- if (__openssl_ecdh_derive_secret(pkp, pub, s) < 0) {
- EVP_PKEY_free(pub);
- return -ECRYPT;
+ if (ctx->flags == 0) {
+ clrbuf(*out);
+ return 0;
}
- EVP_PKEY_free(pub);
+#ifdef HAVE_OPENSSL
+ return openssl_decrypt(ctx->ctx, ctx->key, in, out);
+#else
+ (void) in;
+ (void) out;
- return 0;
+ return -ECRYPT;
+#endif
}
-/*
- * AES encryption calls. If FRCT is disabled, we should generate a
- * 128-bit random IV and append it to the packet. If the flow is
- * reliable, we could initialize the context once, and consider the
- * stream a single encrypted message to avoid initializing the
- * encryption context for each packet.
- */
-
-static int openssl_encrypt(void * ctx,
- uint8_t * key,
- struct shm_du_buff * sdb)
+struct crypt_ctx * crypt_create_ctx(uint16_t flags,
+ const uint8_t * key)
{
- uint8_t * out;
- uint8_t * in;
- uint8_t * head;
- uint8_t iv[IVSZ];
- int in_sz;
- int out_sz;
- int tmp_sz;
- int ret;
-
- in = shm_du_buff_head(sdb);
- in_sz = shm_du_buff_tail(sdb) - in;
-
- assert(in_sz > 0);
-
- if (random_buffer(iv, IVSZ) < 0)
- goto fail_iv;
-
- out = malloc(in_sz + EVP_MAX_BLOCK_LENGTH);
- if (out == NULL)
- goto fail_iv;
+ struct crypt_ctx * crypt;
- EVP_CIPHER_CTX_reset(ctx);
+ crypt = malloc(sizeof(*crypt));
+ if (crypt == NULL)
+ goto fail_crypt;
- ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
- if (ret != 1)
- goto fail_encrypt_init;
+ memset(crypt, 0, sizeof(*crypt));
- ret = EVP_EncryptUpdate(ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_encrypt;
-
- out_sz = tmp_sz;
- ret = EVP_EncryptFinal_ex(ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_encrypt;
-
- out_sz += tmp_sz;
-
- EVP_CIPHER_CTX_cleanup(ctx);
-
- assert(out_sz >= in_sz);
+ crypt->flags = flags;
+ if (key != NULL)
+ memcpy(crypt->key, key, SYMMKEYSZ);
+#ifdef HAVE_OPENSSL
+ crypt->ctx=openssl_crypt_create_ctx();
+ if (crypt->ctx == NULL)
+ goto fail_ctx;
+#endif
+ return crypt;
+#ifdef HAVE_OPENSSL
+ fail_ctx:
+ free(crypt);
+#endif
+ fail_crypt:
+ return NULL;
+}
- head = shm_du_buff_head_alloc(sdb, IVSZ);
- if (head == NULL)
- goto fail_encrypt;
+void crypt_destroy_ctx(struct crypt_ctx * crypt)
+{
+ if (crypt == NULL)
+ return;
- if (shm_du_buff_tail_alloc(sdb, out_sz - in_sz) == NULL)
- goto fail_tail_alloc;
+#ifdef HAVE_OPENSSL
+ assert(crypt->ctx != NULL);
+ openssl_crypt_destroy_ctx(crypt->ctx);
+#else
+ assert(crypt->ctx == NULL);
+#endif
+ free(crypt);
+}
- memcpy(head, iv, IVSZ);
- memcpy(in, out, out_sz);
+int crypt_load_privkey_file(const char * path,
+ void ** key)
+{
+ *key = NULL;
- free(out);
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_file(path, key);
+#else
+ (void) path;
return 0;
-
- fail_tail_alloc:
- shm_du_buff_head_release(sdb, IVSZ);
- fail_encrypt:
- EVP_CIPHER_CTX_cleanup(ctx);
- fail_encrypt_init:
- free(out);
- fail_iv:
- return -ECRYPT;
+#endif
}
-static int openssl_decrypt(void * ctx,
- uint8_t * key,
- struct shm_du_buff * sdb)
+int crypt_load_privkey_str(const char * str,
+ void ** key)
{
- uint8_t * in;
- uint8_t * out;
- uint8_t iv[IVSZ];
- int ret;
- int out_sz;
- int in_sz;
- int tmp_sz;
+ *key = NULL;
- in_sz = shm_du_buff_len(sdb);
- if (in_sz < IVSZ)
- return -ECRYPT;
-
- in = shm_du_buff_head_release(sdb, IVSZ);
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_str(str, key);
+#else
+ (void) str;
- memcpy(iv, in, IVSZ);
+ return 0;
+#endif
+}
- in = shm_du_buff_head(sdb);
- in_sz = shm_du_buff_tail(sdb) - in;
+int crypt_load_pubkey_str(const char * str,
+ void ** key)
+{
+ *key = NULL;
- out = malloc(in_sz);
- if (out == NULL)
- goto fail_malloc;
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_str(str, key);
+#else
+ (void) str;
- EVP_CIPHER_CTX_reset(ctx);
+ return 0;
+#endif
+}
- ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
- if (ret != 1)
- goto fail_decrypt_init;
+int crypt_cmp_key(const void * key1,
+ const void * key2)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_cmp_key(key1, key2);
+#else
+ (void) key1;
+ (void) key2;
- ret = EVP_DecryptUpdate(ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_decrypt;
+ return 0;
+#endif
+}
- out_sz = tmp_sz;
+void crypt_free_key(void * key)
+{
+ if (key == NULL)
+ return;
- ret = EVP_DecryptFinal_ex(ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_decrypt;
+#ifdef HAVE_OPENSSL
+ openssl_free_key(key);
+#endif
+}
- out_sz += tmp_sz;
+int crypt_load_crt_file(const char * path,
+ void ** crt)
+{
+ *crt = NULL;
- assert(out_sz <= in_sz);
+#ifdef HAVE_OPENSSL
+ return openssl_load_crt_file(path, crt);
+#else
+ (void) path;
- shm_du_buff_tail_release(sdb, in_sz - out_sz);
+ return 0;
+#endif
+}
- memcpy(in, out, out_sz);
+int crypt_load_crt_str(const char * str,
+ void ** crt)
+{
+ *crt = NULL;
- free(out);
+#ifdef HAVE_OPENSSL
+ return openssl_load_crt_str(str, crt);
+#else
+ (void) str;
return 0;
-
- fail_decrypt:
- EVP_CIPHER_CTX_cleanup(ctx);
- fail_decrypt_init:
- free(out);
- fail_malloc:
- return -ECRYPT;
-
+#endif
}
-static int openssl_crypt_init(void ** ctx)
+int crypt_get_pubkey_crt(void * crt,
+ void ** pk)
{
- *ctx = EVP_CIPHER_CTX_new();
- if (*ctx == NULL)
- return -ECRYPT;
+ assert(crt != NULL);
+ assert(pk != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_get_pubkey_crt(crt, pk);
+#else
+ (void) crt;
+
+ clrbuf(*pk);
return 0;
+#endif
}
-static void openssl_crypt_fini(void * ctx)
+void crypt_free_crt(void * crt)
{
- EVP_CIPHER_CTX_free(ctx);
+ if (crt == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_free_crt(crt);
+#endif
}
-#endif /* HAVE_OPENSSL */
-
-int crypt_dh_pkp_create(void ** pkp,
- uint8_t * pk)
+int crypt_crt_str(void * crt,
+ char * buf)
{
#ifdef HAVE_OPENSSL
- assert(pkp != NULL);
- *pkp = NULL;
- return openssl_ecdh_pkp_create(pkp, pk);
+ return openssl_crt_str(crt, buf);
#else
- (void) pkp;
- (void) pk;
-
- *pkp = NULL;
+ (void) crt;
+ (void) buf;
return 0;
#endif
}
-void crypt_dh_pkp_destroy(void * pkp)
+int crypt_check_crt_name(void * crt,
+ const char * name)
{
#ifdef HAVE_OPENSSL
- openssl_ecdh_pkp_destroy(pkp);
+ return openssl_check_crt_name(crt, name);
#else
- (void) pkp;
- return;
+ (void) crt;
+ (void) name;
+
+ return 0;
#endif
}
-int crypt_dh_derive(void * pkp,
- buffer_t pk,
- uint8_t * s)
+struct auth_ctx * auth_create_ctx(void)
{
-#ifdef HAVE_OPENSSL
- return openssl_ecdh_derive(pkp, pk, s);
-#else
- (void) pkp;
- (void) pk;
+ struct auth_ctx * ctx;
- memset(s, 0, SYMMKEYSZ);
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto fail_malloc;
- return -ECRYPT;
+ memset(ctx, 0, sizeof(*ctx));
+#ifdef HAVE_OPENSSL
+ ctx->store = openssl_auth_create_store();
+ if (ctx->store == NULL)
+ goto fail_store;
+#endif
+ return ctx;
+#ifdef HAVE_OPENSSL
+ fail_store:
+ free(ctx);
#endif
+ fail_malloc:
+ return NULL;
}
-int crypt_encrypt(struct crypt_info * info,
- struct shm_du_buff * sdb)
+void auth_destroy_ctx(struct auth_ctx * ctx)
{
- if (info->flags == 0)
- return 0;
+ if (ctx == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_auth_destroy_store(ctx->store);
+#endif
+ free(ctx);
+}
+
+int auth_add_crt_to_store(struct auth_ctx * ctx,
+ void * crt)
+{
+ assert(ctx != NULL);
+ assert(crt != NULL);
#ifdef HAVE_OPENSSL
- return openssl_encrypt(info->ctx, info->key, sdb);
+ return openssl_auth_add_crt_to_store(ctx->store, crt);
#else
- (void) sdb;
+ (void) ctx;
+ (void) crt;
- return 0;
+ return -1;
#endif
}
-int crypt_decrypt(struct crypt_info * info,
- struct shm_du_buff * sdb)
+int auth_verify_crt(struct auth_ctx * ctx,
+ void * crt)
{
- if (info->flags == 0)
- return 0;
-
#ifdef HAVE_OPENSSL
- return openssl_decrypt(info->ctx, info->key, sdb);
+ return openssl_verify_crt(ctx->store, crt);
#else
- (void) sdb;
+ (void) ctx;
+ (void) crt;
- return -ECRYPT;
+ return 0;
#endif
}
-int crypt_init(struct crypt_info * info)
+int auth_sign(void * pkp,
+ buffer_t msg,
+ buffer_t * sig)
{
#ifdef HAVE_OPENSSL
- return openssl_crypt_init(&info->ctx);
+ return openssl_sign(pkp, msg, sig);
#else
- info->ctx = NULL;
+ (void) pkp;
+ (void) msg;
+ (void) sig;
+
+ clrbuf(*sig);
+
return 0;
#endif
}
-void crypt_fini(struct crypt_info * info)
+int auth_verify_sig(void * pk,
+ buffer_t msg,
+ buffer_t sig)
{
#ifdef HAVE_OPENSSL
- openssl_crypt_fini(info->ctx);
+ return openssl_verify_sig(pk, msg, sig);
#else
- (void) info;
- assert(info->ctx == NULL);
+ (void) pk;
+ (void) msg;
+ (void) sig;
+
+ return 0;
#endif
}
diff --git a/src/lib/crypt/openssl.c b/src/lib/crypt/openssl.c
new file mode 100644
index 00000000..6e7a5dab
--- /dev/null
+++ b/src/lib/crypt/openssl.c
@@ -0,0 +1,744 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * OpenSSL based cryptographic operations
+ * Elliptic curve Diffie-Hellman key exchange
+ * AES encryption
+ # Authentication
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#include <ouroboros/errno.h>
+#include <ouroboros/crypt.h>
+#include <ouroboros/hash.h>
+#include <ouroboros/random.h>
+#include <ouroboros/utils.h>
+
+#include <assert.h>
+
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/ec.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509_vfy.h>
+
+/*
+ * Derive the common secret from
+ * - your public key pair (kp)
+ * - the remote public key (pub).
+ * Store it in a preallocated buffer (s).
+ */
+static int __openssl_ecdh_derive_secret(EVP_PKEY * kp,
+ EVP_PKEY * pub,
+ uint8_t * s)
+{
+ EVP_PKEY_CTX * ctx;
+ int ret;
+ uint8_t * secret;
+ size_t secret_len;
+
+ ctx = EVP_PKEY_CTX_new(kp, NULL);
+ if (ctx == NULL)
+ goto fail_new;
+
+ ret = EVP_PKEY_derive_init(ctx);
+ if (ret != 1)
+ goto fail_ctx;
+
+ ret = EVP_PKEY_derive_set_peer(ctx, pub);
+ if (ret != 1)
+ goto fail_ctx;
+
+ ret = EVP_PKEY_derive(ctx, NULL, &secret_len);
+ if (ret != 1)
+ goto fail_ctx;
+
+ if (secret_len < SYMMKEYSZ)
+ goto fail_ctx;
+
+ secret = OPENSSL_malloc(secret_len);
+ if (secret == NULL)
+ goto fail_ctx;
+
+ ret = EVP_PKEY_derive(ctx, secret, &secret_len);
+ if (ret != 1)
+ goto fail_derive;
+
+ /* Hash the secret for use as AES key. */
+ mem_hash(HASH_SHA3_256, s, secret, secret_len);
+
+ OPENSSL_free(secret);
+ EVP_PKEY_CTX_free(ctx);
+
+ return 0;
+ fail_derive:
+ OPENSSL_free(secret);
+ fail_ctx:
+ EVP_PKEY_CTX_free(ctx);
+ fail_new:
+ return -ECRYPT;
+}
+
+static int __openssl_ecdh_gen_key(void ** kp)
+{
+ EVP_PKEY_CTX * ctx = NULL;
+ EVP_PKEY_CTX * kctx = NULL;
+ EVP_PKEY * params = NULL;
+ int ret;
+
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+ if (ctx == NULL)
+ goto fail_new_id;
+
+ ret = EVP_PKEY_paramgen_init(ctx);
+ if (ret != 1)
+ goto fail_paramgen;
+
+ ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1);
+ if (ret != 1)
+ goto fail_paramgen;
+
+ ret = EVP_PKEY_paramgen(ctx, &params);
+ if (ret != 1)
+ goto fail_paramgen;
+
+ kctx = EVP_PKEY_CTX_new(params, NULL);
+ if (kctx == NULL)
+ goto fail_keygen_init;
+
+ ret = EVP_PKEY_keygen_init(kctx);
+ if (ret != 1)
+ goto fail_keygen;
+
+ ret = EVP_PKEY_keygen(kctx, (EVP_PKEY **) kp);
+ if (ret != 1)
+ goto fail_keygen;
+
+ EVP_PKEY_free(params);
+ EVP_PKEY_CTX_free(kctx);
+ EVP_PKEY_CTX_free(ctx);
+
+ return 0;
+ fail_keygen:
+ EVP_PKEY_CTX_free(kctx);
+ fail_keygen_init:
+ EVP_PKEY_free(params);
+ fail_paramgen:
+ EVP_PKEY_CTX_free(ctx);
+ fail_new_id:
+ return -ECRYPT;
+}
+
+ssize_t openssl_ecdh_pkp_create(void ** pkp,
+ uint8_t * pk)
+{
+ uint8_t * pos;
+ ssize_t len;
+
+ assert(pkp != NULL);
+ assert(*pkp == NULL);
+ assert(pk != NULL);
+
+ if (__openssl_ecdh_gen_key(pkp) < 0)
+ goto fail_key;
+
+ pos = pk; /* i2d_PUBKEY increments the pointer, don't use buf! */
+ len = i2d_PUBKEY(*pkp, &pos);
+ if (len < 0)
+ goto fail_pubkey;
+
+ return len;
+ fail_pubkey:
+ EVP_PKEY_free(*pkp);
+ fail_key:
+ return -ECRYPT;
+}
+
+void openssl_ecdh_pkp_destroy(void * pkp)
+{
+ EVP_PKEY_free((EVP_PKEY *) pkp);
+}
+
+int openssl_ecdh_derive(void * pkp,
+ buffer_t pk,
+ uint8_t * s)
+{
+ uint8_t * pos;
+ EVP_PKEY * pub;
+
+ pos = pk.data; /* d2i_PUBKEY increments pos, don't use key ptr! */
+ pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) pk.len);
+ if (pub == NULL)
+ goto fail_pubkey;
+
+ if (__openssl_ecdh_derive_secret(pkp, pub, s) < 0)
+ goto fail_key;
+
+ EVP_PKEY_free(pub);
+
+ return 0;
+ fail_pubkey:
+ EVP_PKEY_free(pub);
+ fail_key:
+ return -ECRYPT;
+}
+
+/*
+ * AES encryption calls. If FRCT is disabled, we should generate a
+ * 128-bit random IV and append it to the packet. If the flow is
+ * reliable, we could initialize the context once, and consider the
+ * stream a single encrypted message to avoid initializing the
+ * encryption context for each packet.
+ */
+
+int openssl_encrypt(void * ctx,
+ uint8_t * key,
+ buffer_t in,
+ buffer_t * out)
+{
+ uint8_t * ptr;
+ uint8_t * iv;
+ int in_sz;
+ int out_sz;
+ int tmp_sz;
+ int ret;
+
+ in_sz = (int) in.len;
+
+ out->data = malloc(in.len + EVP_MAX_BLOCK_LENGTH + IVSZ);
+ if (out->data == NULL)
+ goto fail_malloc;
+
+ iv = out->data;
+ ptr = out->data + IVSZ;
+
+ if (random_buffer(iv, IVSZ) < 0)
+ goto fail_iv;
+
+ EVP_CIPHER_CTX_reset(ctx);
+
+ ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
+ if (ret != 1)
+ goto fail_iv;
+
+ ret = EVP_EncryptUpdate(ctx, ptr, &tmp_sz, in.data, in_sz);
+ if (ret != 1)
+ goto fail_encrypt;
+
+ out_sz = tmp_sz;
+ ret = EVP_EncryptFinal_ex(ctx, ptr + tmp_sz, &tmp_sz);
+ if (ret != 1)
+ goto fail_encrypt;
+
+ out_sz += tmp_sz;
+
+ EVP_CIPHER_CTX_cleanup(ctx);
+
+ assert(out_sz >= in_sz);
+
+ out->len = (size_t) out_sz + IVSZ;
+
+ return 0;
+ fail_encrypt:
+ EVP_CIPHER_CTX_cleanup(ctx);
+ fail_iv:
+ free(out->data);
+ fail_malloc:
+ clrbuf(*out);
+ return -ECRYPT;
+}
+
+int openssl_decrypt(void * ctx,
+ uint8_t * key,
+ buffer_t in,
+ buffer_t * out)
+{
+ uint8_t * ptr;
+ uint8_t * iv;
+ uint8_t * input;
+ int ret;
+ int out_sz;
+ int in_sz;
+ int tmp_sz;
+
+ in_sz = (int) in.len - IVSZ;
+ if (in_sz < 0)
+ return -ECRYPT;
+
+ out->data = malloc(in_sz);
+ if (out->data == NULL)
+ goto fail_malloc;
+
+ iv = in.data;
+ ptr = out->data;
+ input = in.data + IVSZ;
+
+ EVP_CIPHER_CTX_reset(ctx);
+
+ ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
+ if (ret != 1)
+ goto fail_decrypt_init;
+
+ ret = EVP_DecryptUpdate(ctx, ptr, &tmp_sz, input, in_sz);
+ if (ret != 1)
+ goto fail_decrypt;
+
+ out_sz = tmp_sz;
+ ret = EVP_DecryptFinal_ex(ctx, ptr + tmp_sz, &tmp_sz);
+ if (ret != 1)
+ goto fail_decrypt;
+
+ out_sz += tmp_sz;
+
+ assert(out_sz <= in_sz);
+
+ out->len = (size_t) out_sz;
+
+ return 0;
+ fail_decrypt:
+ EVP_CIPHER_CTX_cleanup(ctx);
+ fail_decrypt_init:
+ free(out->data);
+ fail_malloc:
+ clrbuf(*out);
+ return -ECRYPT;
+}
+
+void * openssl_crypt_create_ctx(void)
+{
+ return (void *) EVP_CIPHER_CTX_new();
+}
+
+void openssl_crypt_destroy_ctx(void * ctx)
+{
+ EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *) ctx);
+}
+
+/* AUTHENTICATION */
+
+int openssl_load_crt_file(const char * path,
+ void ** crt)
+{
+ FILE * fp;
+ X509 * xcrt;
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ goto fail_file;
+
+ xcrt = PEM_read_X509(fp, NULL, NULL, NULL);
+ if (xcrt == NULL)
+ goto fail_crt;
+
+ fclose(fp);
+
+ *crt = (void *) xcrt;
+
+ return 0;
+ fail_crt:
+ fclose(fp);
+ fail_file:
+ *crt = NULL;
+ return -1;
+}
+
+int openssl_load_crt_str(const char * str,
+ void ** crt)
+{
+ BIO * bio;
+ X509 * xcrt;
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto fail_bio;
+
+ if (BIO_write(bio, str, strlen(str)) < 0)
+ goto fail_crt;
+
+ xcrt = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ if (xcrt == NULL)
+ goto fail_crt;
+
+ BIO_free(bio);
+
+ *crt = (void *) xcrt;
+
+ return 0;
+ fail_crt:
+ BIO_free(bio);
+ fail_bio:
+ *crt = NULL;
+ return -1;
+}
+
+int openssl_get_pubkey_crt(void * crt,
+ void ** key)
+{
+ EVP_PKEY * pk;
+ X509 * xcrt;
+
+ assert(crt != NULL);
+ assert(key != NULL);
+
+ xcrt = (X509 *) crt;
+
+ pk = X509_get_pubkey(xcrt);
+ if (pk == NULL)
+ goto fail_key;
+
+ *key = (void *) pk;
+
+ return 0;
+ fail_key:
+ return -1;
+}
+
+void openssl_free_crt(void * crt)
+{
+ X509_free((X509 *) crt);
+}
+
+int openssl_load_privkey_file(const char * path,
+ void ** key)
+{
+ FILE * fp;
+ EVP_PKEY * pkey;
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ goto fail_file;
+
+ pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+ if (pkey == NULL)
+ goto fail_key;
+
+ fclose(fp);
+
+ *key = (void *) pkey;
+
+ return 0;
+ fail_key:
+ fclose(fp);
+ fail_file:
+ *key = NULL;
+ return -1;
+}
+
+int openssl_load_privkey_str(const char * str,
+ void ** key)
+{
+ BIO * bio;
+ EVP_PKEY * pkey;
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto fail_bio;
+
+ if (BIO_write(bio, str, strlen(str)) < 0)
+ goto fail_key;
+
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ if (pkey == NULL)
+ goto fail_key;
+
+ BIO_free(bio);
+
+ *key = (void *) pkey;
+
+ return 0;
+ fail_key:
+ BIO_free(bio);
+ fail_bio:
+ *key = NULL;
+ return -1;
+}
+
+int openssl_load_pubkey_file(const char * path,
+ void ** key)
+{
+ FILE * fp;
+ EVP_PKEY * pkey;
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ goto fail_file;
+
+ pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
+ if (pkey == NULL)
+ goto fail_key;
+
+ fclose(fp);
+
+ *key = (void *) pkey;
+
+ return 0;
+ fail_key:
+ fclose(fp);
+ fail_file:
+ *key = NULL;
+ return -1;
+}
+
+int openssl_load_pubkey_str(const char * str,
+ void ** key)
+{
+ BIO * bio;
+ EVP_PKEY * pkey;
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto fail_bio;
+
+ if (BIO_write(bio, str, strlen(str)) < 0)
+ goto fail_key;
+
+ pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
+ if (pkey == NULL)
+ goto fail_key;
+
+ BIO_free(bio);
+
+ *key = (void *) pkey;
+
+ return 0;
+ fail_key:
+ BIO_free(bio);
+ fail_bio:
+ *key = NULL;
+ return -1;
+}
+
+int openssl_cmp_key(const void * key1,
+ const void * key2)
+{
+ EVP_PKEY * pkey1;
+ EVP_PKEY * pkey2;
+
+ assert(key1 != NULL);
+ assert(key2 != NULL);
+
+ pkey1 = (EVP_PKEY *) key1;
+ pkey2 = (EVP_PKEY *) key2;
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ return EVP_PKEY_eq(pkey1, pkey2) == 1 ? 0 : -1;
+#else
+ return EVP_PKEY_cmp(pkey1, pkey2) == 1 ? 0 : -1;
+#endif
+}
+
+void openssl_free_key(void * key)
+{
+ EVP_PKEY_free((EVP_PKEY *) key);
+}
+
+int openssl_check_crt_name(void * crt,
+ const char * name)
+{
+ char * subj;
+ char * cn;
+ X509 * xcrt;
+
+ xcrt = (X509 *) crt;
+
+ subj = X509_NAME_oneline(X509_get_subject_name(xcrt), NULL, 0);
+ if (subj == NULL)
+ goto fail_subj;
+
+ cn = strstr(subj, "CN=");
+ if (cn == NULL)
+ goto fail_cn;
+
+ if (strcmp(cn + 3, name) != 0)
+ goto fail_cn;
+
+ free(subj);
+
+ return 0;
+ fail_cn:
+ free(subj);
+ fail_subj:
+ return -1;
+}
+
+int openssl_crt_str(void * crt,
+ char * str)
+{
+ BIO * bio;
+ X509 * xcrt;
+ char * p;
+
+ xcrt = (X509 *) crt;
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL)
+ goto fail_bio;
+
+ X509_print(bio, xcrt);
+
+ BIO_get_mem_data(bio, &p);
+ if (p == NULL)
+ goto fail_p;
+
+ sprintf(str, "%s", p);
+
+ BIO_free(bio);
+
+ return 0;
+ fail_p:
+ BIO_free(bio);
+ fail_bio:
+ return -1;
+}
+
+void * openssl_auth_create_store(void)
+{
+ return X509_STORE_new();
+}
+
+void openssl_auth_destroy_store(void * ctx)
+{
+ X509_STORE_free((X509_STORE *) ctx);
+}
+
+int openssl_auth_add_crt_to_store(void * store,
+ void * crt)
+{
+ int ret;
+
+ ret = X509_STORE_add_cert((X509_STORE *) store, (X509 *) crt);
+
+ return ret == 1 ? 0 : -1;
+}
+
+int openssl_verify_crt(void * store,
+ void * crt)
+{
+ X509_STORE_CTX * ctx;
+ X509_STORE * _store;
+ X509* _crt;
+ int ret;
+
+ _store = (X509_STORE *) store;
+ _crt = (X509 *) crt;
+
+ ctx = X509_STORE_CTX_new();
+ if (ctx == NULL)
+ goto fail_store_ctx;
+
+ ret = X509_STORE_CTX_init(ctx, _store, _crt, NULL);
+ if (ret != 1)
+ goto fail_ca;
+
+ ret = X509_verify_cert(ctx);
+ if (ret != 1)
+ goto fail_ca;
+
+ X509_STORE_CTX_free(ctx);
+
+ return 0;
+ fail_ca:
+ X509_STORE_CTX_free(ctx);
+ fail_store_ctx:
+ return -1;
+}
+
+int openssl_sign(void * pkp,
+ buffer_t msg,
+ buffer_t * sig)
+{
+ EVP_PKEY * pkey;
+ EVP_MD_CTX * mdctx;
+ size_t required;
+
+ assert(pkp != NULL);
+ assert(sig != NULL);
+
+ pkey = (EVP_PKEY *) pkp;
+
+ mdctx = EVP_MD_CTX_new();
+ if (!mdctx)
+ goto fail_ctx;
+
+ if (EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1)
+ goto fail_digest;
+
+ if (EVP_DigestSignUpdate(mdctx, msg.data, msg.len) != 1)
+ goto fail_digest;
+
+ if (EVP_DigestSignFinal(mdctx, NULL, &required) != 1)
+ goto fail_digest;
+
+ sig->data = malloc(required);
+ if (sig->data == NULL)
+ goto fail_digest;
+
+ if (EVP_DigestSignFinal(mdctx, sig->data, &required) != 1)
+ goto fail_sign;
+
+ sig->len = required;
+
+ EVP_MD_CTX_free(mdctx);
+
+ return 0;
+ fail_sign:
+ freebuf(*sig);
+ fail_digest:
+ EVP_MD_CTX_free(mdctx);
+ fail_ctx:
+ clrbuf(*sig);
+ return -1;
+}
+
+int openssl_verify_sig(void * pk,
+ buffer_t msg,
+ buffer_t sig)
+{
+ EVP_PKEY * pkey;
+ EVP_MD_CTX * mdctx;
+ int ret;
+
+ assert(pk != NULL);
+
+ pkey = (EVP_PKEY *) pk;
+
+ mdctx = EVP_MD_CTX_new();
+ if (!mdctx)
+ goto fail_ctx;
+
+ if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1)
+ goto fail_digest;
+
+ if (EVP_DigestVerifyUpdate(mdctx, msg.data, msg.len) != 1)
+ goto fail_digest;
+
+ ret = EVP_DigestVerifyFinal(mdctx, sig.data, sig.len);
+ if (ret != 1)
+ goto fail_digest;
+
+ EVP_MD_CTX_free(mdctx);
+
+ return 0;
+ fail_digest:
+ EVP_MD_CTX_free(mdctx);
+ fail_ctx:
+ clrbuf(sig);
+ return -1;
+}
diff --git a/src/lib/crypt/openssl.h b/src/lib/crypt/openssl.h
new file mode 100644
index 00000000..5d6f50dd
--- /dev/null
+++ b/src/lib/crypt/openssl.h
@@ -0,0 +1,106 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * OpenSSL based cryptographic operations
+ * Elliptic curve Diffie-Hellman key exchange
+ * AES encryption
+ # Authentication
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#ifndef OUROBOROS_LIB_CRYPT_OPENSSL_H
+#define OUROBOROS_LIB_CRYPT_OPENSSL_H
+
+ssize_t openssl_ecdh_pkp_create(void ** pkp,
+ uint8_t * pk);
+
+void openssl_ecdh_pkp_destroy(void * pkp);
+
+int openssl_ecdh_derive(void * pkp,
+ buffer_t pk,
+ uint8_t * s);
+
+int openssl_encrypt(void * ctx,
+ uint8_t * key,
+ buffer_t in,
+ buffer_t * out);
+
+int openssl_decrypt(void * ctx,
+ uint8_t * key,
+ buffer_t in,
+ buffer_t * out);
+
+void * openssl_crypt_create_ctx(void);
+
+void openssl_crypt_destroy_ctx(void * ctx);
+
+/* AUTHENTICATION */
+
+int openssl_load_crt_file(const char * path,
+ void ** crt);
+
+int openssl_load_crt_str(const char * str,
+ void ** crt);
+
+int openssl_get_pubkey_crt(void * crt,
+ void ** pk);
+
+void openssl_free_crt(void * crt);
+
+int openssl_load_privkey_file(const char * path,
+ void ** key);
+
+int openssl_load_privkey_str(const char * str,
+ void ** key);
+
+int openssl_load_pubkey_file(const char * path,
+ void ** key);
+
+int openssl_load_pubkey_str(const char * str,
+ void ** key);
+
+int openssl_cmp_key(const void * key1,
+ const void * key2);
+
+void openssl_free_key(void * key);
+
+int openssl_check_crt_name(void * crt,
+ const char * name);
+
+int openssl_crt_str(void * crt,
+ char * str);
+
+void * openssl_auth_create_store(void);
+
+void openssl_auth_destroy_store(void * store);
+
+int openssl_auth_add_crt_to_store(void * store,
+ void * crt);
+
+int openssl_verify_crt(void * store,
+ void * crt);
+
+int openssl_sign(void * pkp,
+ buffer_t msg,
+ buffer_t * sig);
+
+int openssl_verify_sig(void * pk,
+ buffer_t msg,
+ buffer_t sig);
+
+#endif /* OUROBOROS_LIB_CRYPT_OPENSSL_H */
diff --git a/src/lib/dev.c b/src/lib/dev.c
index 92310b9e..cb35f3f9 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -99,7 +99,7 @@ struct flow {
uint16_t oflags;
ssize_t part_idx;
- struct crypt_info crypt;
+ struct crypt_ctx * crypt;
struct timespec snd_act;
struct timespec rcv_act;
@@ -252,6 +252,69 @@ static void proc_exit(void)
send_recv_msg(&msg);
}
+static int sdb_encrypt(struct flow * flow,
+ struct shm_du_buff * sdb)
+{
+ buffer_t in;
+ buffer_t out;
+ uint8_t * head;
+ uint8_t * tail;
+
+ if (flow->crypt == NULL)
+ return 0; /* No encryption */
+
+ in.data = shm_du_buff_head(sdb);
+ in.len = shm_du_buff_len(sdb);
+
+ if (crypt_encrypt(flow->crypt, in, &out) < 0)
+ goto fail_encrypt;
+
+ head = shm_du_buff_head_alloc(sdb, IVSZ);
+ if (head == NULL)
+ goto fail_alloc;
+
+ tail = shm_du_buff_tail_alloc(sdb, (out.len - in.len) - IVSZ);
+ if (tail == NULL)
+ goto fail_alloc;
+
+ memcpy(head, out.data, out.len);
+
+ freebuf(out);
+
+ return 0;
+ fail_alloc:
+ freebuf(out);
+ fail_encrypt:
+ return -ECRYPT;
+}
+
+static int sdb_decrypt(struct flow * flow,
+ struct shm_du_buff * sdb)
+{
+ buffer_t in;
+ buffer_t out;
+ uint8_t * head;
+
+ if (flow->crypt == NULL)
+ return 0; /* No decryption */
+
+ in.data = shm_du_buff_head(sdb);
+ in.len = shm_du_buff_len(sdb);
+
+ if (crypt_decrypt(flow->crypt, in, &out) < 0)
+ return -ENOMEM;
+
+
+ head = shm_du_buff_head_release(sdb, IVSZ) + IVSZ;
+ shm_du_buff_tail_release(sdb, (in.len - out.len) - IVSZ);
+
+ memcpy(head, out.data, out.len);
+
+ freebuf(out);
+
+ return 0;
+}
+
#include "frct.c"
void * flow_tx(void * o)
@@ -423,7 +486,7 @@ static void __flow_fini(int fd)
shm_flow_set_close(ai.flows[fd].set);
}
- crypt_fini(&ai.flows[fd].crypt);
+ crypt_destroy_ctx(ai.flows[fd].crypt);
list_del(&ai.flows[fd].next);
@@ -477,16 +540,15 @@ static int flow_init(struct flow_info * info,
flow->part_idx = NO_PART;
flow->snd_act = now;
flow->rcv_act = now;
-
- flow->crypt.flags = info->qs.cypher_s; /* TODO: move cypher_s */
-
- memset(flow->crypt.key, 0, SYMMKEYSZ);
-
- if (flow->crypt.flags > 0 && sk!= NULL && sk->data != NULL)
- memcpy(flow->crypt.key, sk->data , sk->len);
-
- if (crypt_init(&flow->crypt) < 0)
- goto fail_crypt;
+ flow->crypt = NULL;
+
+ if (sk!= NULL && sk->data != NULL) {
+ assert(sk->len == SYMMKEYSZ);
+ /* TODO: remove cypher_s from QoS */
+ flow->crypt = crypt_create_ctx(info->qs.cypher_s, sk->data);
+ if (flow->crypt == NULL)
+ goto fail_crypt;
+ }
assert(flow->frcti == NULL);
@@ -519,7 +581,7 @@ static int flow_init(struct flow_info * info,
fail_flow_set_add:
frcti_destroy(flow->frcti);
fail_frcti:
- crypt_fini(&flow->crypt);
+ crypt_destroy_ctx(flow->crypt);
fail_crypt:
shm_flow_set_close(flow->set);
fail_set:
@@ -1200,7 +1262,7 @@ static int flow_tx_sdb(struct flow * flow,
if (frcti_snd(flow->frcti, sdb) < 0)
goto enomem;
- if (crypt_encrypt(&flow->crypt, sdb) < 0)
+ if (sdb_encrypt(flow, sdb) < 0)
goto enomem;
if (flow->info.qs.ber == 0 && add_crc(sdb) != 0)
@@ -1302,7 +1364,7 @@ static bool invalid_pkt(struct flow * flow,
if (flow->info.qs.ber == 0 && chk_crc(sdb) != 0)
return true;
- if (crypt_decrypt(&flow->crypt, sdb) < 0)
+ if (sdb_decrypt(flow, sdb) < 0)
return true;
return false;
@@ -1330,6 +1392,7 @@ static ssize_t flow_rx_sdb(struct flow * flow,
pthread_rwlock_unlock(&ai.lock);
*sdb = shm_rdrbuff_get(ai.rdrb, idx);
+
if (invalid_pkt(flow, *sdb)) {
shm_rdrbuff_remove(ai.rdrb, idx);
return -EAGAIN;
diff --git a/src/lib/frct.c b/src/lib/frct.c
index c6fef35c..d51cf006 100644
--- a/src/lib/frct.c
+++ b/src/lib/frct.c
@@ -261,7 +261,7 @@ static void __send_frct_pkt(int fd,
f = &ai.flows[fd];
- if (crypt_encrypt(&f->crypt, sdb) < 0)
+ if (sdb_encrypt(f, sdb) < 0)
goto fail;
#ifdef RXM_BLOCKING
diff --git a/src/lib/random.c b/src/lib/random.c
index 09e0b844..2dc5f02f 100644
--- a/src/lib/random.c
+++ b/src/lib/random.c
@@ -24,22 +24,12 @@
#include <ouroboros/random.h>
-#if defined(__APPLE__) /* Barf */
-#undef __OSX_AVAILABLE
-#define __OSX_AVAILABLE(arg)
-#undef __IOS_AVAILABLE
-#define __IOS_AVAILABLE(arg)
-#undef __TVOS_AVAILABLE
-#define __TVOS_AVAILABLE(arg)
-#undef __WATCHOS_AVAILABLE
-#define __WATCHOS_AVAILABLE(arg)
-#include <sys/random.h>
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#include <stdlib.h>
#elif defined(HAVE_SYS_RANDOM)
#include <sys/random.h>
#elif defined(HAVE_LIBGCRYPT)
#include <gcrypt.h>
-#elif defined(__FreeBSD__)
-#include <stdlib.h>
#elif defined(HAVE_OPENSSL_RNG)
#include <openssl/rand.h>
#include <limits.h>
@@ -48,13 +38,11 @@
int random_buffer(void * buf,
size_t len)
{
-#if defined(__APPLE__)
- return getentropy(buf, len);
-#elif defined(__FreeBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__)
arc4random_buf(buf, len);
return 0;
#elif defined(HAVE_SYS_RANDOM)
- return getrandom(buf, len, GRND_NONBLOCK); /* glibc 2.25 */
+ return getrandom(buf, len, GRND_NONBLOCK);
#elif defined(HAVE_LIBGCRYPT)
gcry_randomize(buf, len, GCRY_STRONG_RANDOM);
return 0;
diff --git a/src/lib/sockets.c b/src/lib/sockets.c
index 13219db0..5dfbcb5c 100644
--- a/src/lib/sockets.c
+++ b/src/lib/sockets.c
@@ -154,12 +154,13 @@ int send_recv_msg(buffer_t * msg)
return len < 0 ? -1 : 0;
}
-char * ipcp_sock_path(pid_t pid)
+static char * __sock_path(pid_t pid,
+ const char * prefix,
+ const char * suffix)
{
char * full_name = NULL;
char * pid_string = NULL;
size_t len = 0;
- char * delim = "_";
len = n_digits(pid);
pid_string = malloc(len + 1);
@@ -168,9 +169,9 @@ char * ipcp_sock_path(pid_t pid)
sprintf(pid_string, "%d", pid);
- len += strlen(IPCP_SOCK_PATH_PREFIX);
- len += strlen(delim);
- len += strlen(SOCK_PATH_SUFFIX);
+ len += strlen(prefix);
+ len += strlen(pid_string);
+ len += strlen(suffix);
full_name = malloc(len + 1);
if (full_name == NULL) {
@@ -178,12 +179,17 @@ char * ipcp_sock_path(pid_t pid)
return NULL;
}
- strcpy(full_name, IPCP_SOCK_PATH_PREFIX);
- strcat(full_name, delim);
+ strcpy(full_name, prefix);
strcat(full_name, pid_string);
- strcat(full_name, SOCK_PATH_SUFFIX);
+ strcat(full_name, suffix);
free(pid_string);
return full_name;
}
+
+char * sock_path(pid_t pid,
+ const char * prefix)
+{
+ return __sock_path(pid, prefix, SOCK_PATH_SUFFIX);
+}
diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt
index dc90671b..2791dd0d 100644
--- a/src/lib/tests/CMakeLists.txt
+++ b/src/lib/tests/CMakeLists.txt
@@ -3,14 +3,18 @@ get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
# Add new tests here
+ auth_test.c
bitmap_test.c
btree_test.c
crc32_test.c
+ crypt_test.c
hash_test.c
md5_test.c
sha3_test.c
shm_rbuff_test.c
+ sockets_test.c
time_test.c
+ tpm_test.c
)
add_executable(${PARENT_DIR}_test EXCLUDE_FROM_ALL ${${PARENT_DIR}_tests})
@@ -30,3 +34,6 @@ foreach (test ${tests_to_run})
get_filename_component(test_name ${test} NAME_WE)
add_test(${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name})
endforeach (test)
+
+set_property(TEST auth_test PROPERTY SKIP_RETURN_CODE 1)
+set_property(TEST crypt_test PROPERTY SKIP_RETURN_CODE 1)
diff --git a/src/lib/tests/auth_test.c b/src/lib/tests/auth_test.c
new file mode 100644
index 00000000..5fabfbd4
--- /dev/null
+++ b/src/lib/tests/auth_test.c
@@ -0,0 +1,571 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Test of the authentication functions
+ *
+ * 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 <ouroboros/test.h>
+#include <ouroboros/crypt.h>
+#include <ouroboros/random.h>
+#include <ouroboros/utils.h>
+
+#define TEST_MSG_SIZE 1500
+
+/*
+* Certificates created following the guide
+* Building an openssl certificate authority
+* on
+* https://community.f5.com/kb/technicalarticles/
+*/
+
+/* Root certificate for CA ca.unittest.o7s */
+static const char * root_ca_crt = \
+"-----BEGIN CERTIFICATE-----\n"
+"MIICiTCCAi6gAwIBAgIUbTYRdvvGJpI99I3ag0Epj8PzOHwwCwYJYIZIAWUDBAMK\n"
+"MIGQMQswCQYDVQQGEwJCRTEMMAoGA1UECAwDT1ZMMQ4wDAYDVQQHDAVHaGVudDEM\n"
+"MAoGA1UECgwDbzdzMRUwEwYDVQQLDAx1bml0dGVzdC5vN3MxGDAWBgNVBAMMD2Nh\n"
+"LnVuaXR0ZXN0Lm83czEkMCIGCSqGSIb3DQEJARYVZHVtbXlAb3Vyb2Jvcm9zLnJv\n"
+"Y2tzMB4XDTI1MDYyMjEzNDcwOVoXDTI1MDcyMjEzNDcwOVowgZAxCzAJBgNVBAYT\n"
+"AkJFMQwwCgYDVQQIDANPVkwxDjAMBgNVBAcMBUdoZW50MQwwCgYDVQQKDANvN3Mx\n"
+"FTATBgNVBAsMDHVuaXR0ZXN0Lm83czEYMBYGA1UEAwwPY2EudW5pdHRlc3Qubzdz\n"
+"MSQwIgYJKoZIhvcNAQkBFhVkdW1teUBvdXJvYm9yb3Mucm9ja3MwWTATBgcqhkjO\n"
+"PQIBBggqhkjOPQMBBwNCAATsvzzYnXYQuZVMA7ckGEb8KISyHhXCBmc/kVcRyAje\n"
+"hVq+F6nuWEEJVy/zNyMdxC5Qm+hVQDwhmu1JkiGAIF1Jo2MwYTAdBgNVHQ4EFgQU\n"
+"sbj19vaWoWYfY5IP901oDYN94tcwHwYDVR0jBBgwFoAUsbj19vaWoWYfY5IP901o\n"
+"DYN94tcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwCwYJYIZIAWUD\n"
+"BAMKA0gAMEUCIQCniTsnEYel6HscrUO7JWs+VnvyqGV5CkRIwgGCN5neQwIgCco6\n"
+"aVh8ZrDsPkjclhFBXF70Qoh9T56f2LdYFvjybdc=\n"
+"-----END CERTIFICATE-----\n";
+
+/* Certificate for intermediary im.unittest.o7s used for signing */
+static const char * intermediate_ca_crt = \
+"-----BEGIN CERTIFICATE-----\n"
+"MIICgzCCAimgAwIBAgICEAAwCwYJYIZIAWUDBAMKMIGQMQswCQYDVQQGEwJCRTEM\n"
+"MAoGA1UECAwDT1ZMMQ4wDAYDVQQHDAVHaGVudDEMMAoGA1UECgwDbzdzMRUwEwYD\n"
+"VQQLDAx1bml0dGVzdC5vN3MxGDAWBgNVBAMMD2NhLnVuaXR0ZXN0Lm83czEkMCIG\n"
+"CSqGSIb3DQEJARYVZHVtbXlAb3Vyb2Jvcm9zLnJvY2tzMB4XDTI1MDYyMjE0MTU0\n"
+"M1oXDTM1MDYyMDE0MTU0M1owWjELMAkGA1UEBhMCQkUxDDAKBgNVBAgMA09WTDEM\n"
+"MAoGA1UECgwDbzdzMRUwEwYDVQQLDAx1bml0dGVzdC5vN3MxGDAWBgNVBAMMD2lt\n"
+"LnVuaXR0ZXN0Lm83czBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABC1/rn6yG22c\n"
+"38lxYGym4VcEZ6+lET5AfcaBsRKpvQj4NwfPG5BCoWwl/rwqKEGmcuwzubiGS1K9\n"
+"hZaxZWp6WfejgaYwgaMwHQYDVR0OBBYEFBfSiMt8k7TKMp2lVsdlunBLGJQhMB8G\n"
+"A1UdIwQYMBaAFLG49fb2lqFmH2OSD/dNaA2DfeLXMBIGA1UdEwEB/wQIMAYBAf8C\n"
+"AQAwDgYDVR0PAQH/BAQDAgGGMBEGA1UdHwQKMAgwBqAEoAKGADAqBggrBgEFBQcB\n"
+"AQQeMBwwDAYIKwYBBQUHMAKGADAMBggrBgEFBQcwAYYAMAsGCWCGSAFlAwQDCgNH\n"
+"ADBEAiBjgMvCgnPz+xy4I1Msb6EwfwdIHr4eHqEfsGQjWf9M8gIgJyy6Bkg6Nkb4\n"
+"uLdf/8CFP5yKKP1H26F8gx1VrGtr+PM=\n"
+"-----END CERTIFICATE-----\n";
+
+/* Server server-1.unittest.o7s private-public key pair */
+static const char * server_ec_pkp = \
+"-----BEGIN EC PRIVATE KEY-----\n"
+"MHcCAQEEIOLEoARQqt9oQkZhdqYrrDltVtcX7TIOYTQqE+GWCIwEoAoGCCqGSM49\n"
+"AwEHoUQDQgAEzHlm1xTYnWncOymJ29ubJ3cHShG67JE+floT7L8ipqRNW4/FUwPN\n"
+"zR/49iM0+A3Nq0ImjzkA6B7E3LvlrwokYQ==\n"
+"-----END EC PRIVATE KEY-----\n";
+
+/* Public key for the Private key */
+static const char * server_ec_pk = \
+"-----BEGIN PUBLIC KEY-----\n"
+"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzHlm1xTYnWncOymJ29ubJ3cHShG6\n"
+"7JE+floT7L8ipqRNW4/FUwPNzR/49iM0+A3Nq0ImjzkA6B7E3LvlrwokYQ==\n"
+"-----END PUBLIC KEY-----\n";
+
+/* Valid signed server certificate for server-1.unittest.o7s */
+static const char * signed_server_crt = \
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDgzCCAyegAwIBAgICEAAwCwYJYIZIAWUDBAMKMFoxCzAJBgNVBAYTAkJFMQww\n"
+"CgYDVQQIDANPVkwxDDAKBgNVBAoMA283czEVMBMGA1UECwwMdW5pdHRlc3Qubzdz\n"
+"MRgwFgYDVQQDDA9pbS51bml0dGVzdC5vN3MwHhcNMjUwNjIyMTQzODMxWhcNMjcw\n"
+"NjIyMTQzODMxWjBwMQswCQYDVQQGEwJCRTEMMAoGA1UECAwDT1ZMMQ4wDAYDVQQH\n"
+"DAVHaGVudDEMMAoGA1UECgwDbzdzMRUwEwYDVQQLDAx1bml0dGVzdC5vN3MxHjAc\n"
+"BgNVBAMMFXNlcnZlci0xLnVuaXR0ZXN0Lm83czBZMBMGByqGSM49AgEGCCqGSM49\n"
+"AwEHA0IABMx5ZtcU2J1p3Dspidvbmyd3B0oRuuyRPn5aE+y/IqakTVuPxVMDzc0f\n"
+"+PYjNPgNzatCJo85AOgexNy75a8KJGGjggHEMIIBwDAJBgNVHRMEAjAAMBEGCWCG\n"
+"SAGG+EIBAQQEAwIGQDA6BglghkgBhvhCAQ0ELRYrR3JpbGxlZCBDaGVlc2UgR2Vu\n"
+"ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIKmznLlTbfKaP78E\n"
+"uSNauQ/4Mcwwgb4GA1UdIwSBtjCBs4AUF9KIy3yTtMoynaVWx2W6cEsYlCGhgZak\n"
+"gZMwgZAxCzAJBgNVBAYTAkJFMQwwCgYDVQQIDANPVkwxDjAMBgNVBAcMBUdoZW50\n"
+"MQwwCgYDVQQKDANvN3MxFTATBgNVBAsMDHVuaXR0ZXN0Lm83czEYMBYGA1UEAwwP\n"
+"Y2EudW5pdHRlc3QubzdzMSQwIgYJKoZIhvcNAQkBFhVkdW1teUBvdXJvYm9yb3Mu\n"
+"cm9ja3OCAhAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAR\n"
+"BgNVHR8ECjAIMAagBKAChgAwKgYIKwYBBQUHAQEEHjAcMAwGCCsGAQUFBzAChgAw\n"
+"DAYIKwYBBQUHMAGGADAgBgNVHREEGTAXghVzZXJ2ZXItMS51bml0dGVzdC5vN3Mw\n"
+"CwYJYIZIAWUDBAMKA0kAMEYCIQDVoRxvr9j4mbX/CpxsQr5HhjxLnjYzI2SVM+0l\n"
+"z2dxVgIhALwq2q6d8WDHPq59trrlNlnYO+kDqDLS3smnS6LOQYiq\n"
+"-----END CERTIFICATE-----\n";
+
+/* Self-signed by server server-1.unittest.o7s using its key */
+static const char * server_crt = \
+"-----BEGIN CERTIFICATE-----\n"
+"MIICNzCCAdygAwIBAgIUaKYySFvp8nmd7LcJjdCyyHrgv0owCwYJYIZIAWUDBAMK\n"
+"MHAxCzAJBgNVBAYTAkJFMQwwCgYDVQQIDANPVkwxDjAMBgNVBAcMBUdoZW50MQww\n"
+"CgYDVQQKDANvN3MxFTATBgNVBAsMDHVuaXR0ZXN0Lm83czEeMBwGA1UEAwwVc2Vy\n"
+"dmVyLTEudW5pdHRlc3QubzdzMB4XDTI1MDYyMjE0NTU1MFoXDTM1MDYyMDE0NTU1\n"
+"MFowcDELMAkGA1UEBhMCQkUxDDAKBgNVBAgMA09WTDEOMAwGA1UEBwwFR2hlbnQx\n"
+"DDAKBgNVBAoMA283czEVMBMGA1UECwwMdW5pdHRlc3QubzdzMR4wHAYDVQQDDBVz\n"
+"ZXJ2ZXItMS51bml0dGVzdC5vN3MwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATM\n"
+"eWbXFNidadw7KYnb25sndwdKEbrskT5+WhPsvyKmpE1bj8VTA83NH/j2IzT4Dc2r\n"
+"QiaPOQDoHsTcu+WvCiRho1MwUTAdBgNVHQ4EFgQUIKmznLlTbfKaP78EuSNauQ/4\n"
+"McwwHwYDVR0jBBgwFoAUIKmznLlTbfKaP78EuSNauQ/4McwwDwYDVR0TAQH/BAUw\n"
+"AwEB/zALBglghkgBZQMEAwoDSAAwRQIhAMrhCV+4QY4Pzcn11qY8AW24xSYE77jN\n"
+"oWkJQKoLEhSdAiBCFzCBItjChcDavsuy++HDo3e6VdpmAh0PlTlQTR6Wog==\n"
+"-----END CERTIFICATE-----\n";
+
+static int test_auth_create_destroy_ctx(void)
+{
+ struct auth_ctx * ctx;
+
+ TEST_START();
+
+ ctx = auth_create_ctx();
+ if (ctx == NULL) {
+ printf("Failed to create auth context.\n");
+ goto fail_create;
+ }
+
+ auth_destroy_ctx(ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_create:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_load_free_crt(void)
+{
+ void * crt;
+
+ TEST_START();
+
+ if (crypt_load_crt_str(root_ca_crt, &crt) < 0) {
+ printf("Failed to load certificate string.\n");
+ goto fail_load;
+ }
+
+ crypt_free_crt(crt);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_load:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_crypt_get_pubkey_crt(void)
+{
+ void * pk;
+ void * crt;
+
+ TEST_START();
+
+ if (crypt_load_crt_str(signed_server_crt, &crt) < 0) {
+ printf("Failed to load server certificate from string.\n");
+ goto fail_load;
+ }
+
+ if (crypt_get_pubkey_crt(crt, &pk) < 0) {
+ printf("Failed to get public key from certificate.\n");
+ goto fail_get_pubkey;
+ }
+
+ crypt_free_key(pk);
+ crypt_free_crt(crt);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+
+ fail_get_pubkey:
+ crypt_free_crt(crt);
+ fail_load:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_check_crt_name(void)
+{
+ void * crt;
+
+ TEST_START();
+
+ if (crypt_load_crt_str(signed_server_crt, &crt) < 0) {
+ printf("Failed to load certificate from string.\n");
+ goto fail_load;
+ }
+
+ if (crypt_check_crt_name(crt, "server-1.unittest.o7s") < 0) {
+ printf("Failed to verify correct name.\n");
+ goto fail_check;
+ }
+
+ if (crypt_check_crt_name(crt, "bogus.name") == 0) {
+ printf("Failed to detect incorrect name.\n");
+ goto fail_check;
+ }
+
+ crypt_free_crt(crt);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_check:
+ crypt_free_crt(crt);
+ fail_load:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_load_free_privkey(void)
+{
+ void * key;
+
+ TEST_START();
+
+ if (crypt_load_privkey_str(server_ec_pkp, &key) < 0) {
+ printf("Failed to load server key pair from string.\n");
+ goto fail_load;
+ }
+
+ crypt_free_key(key);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_load:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_load_free_pubkey(void)
+{
+ void * key;
+
+ TEST_START();
+
+ if (crypt_load_pubkey_str(server_ec_pk, &key) < 0) {
+ printf("Failed to load server public key from string.\n");
+ goto fail_load;
+ }
+
+ crypt_free_key(key);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_load:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_crypt_check_pubkey_crt(void)
+{
+ void * pk;
+ void * crt_pk;
+ void * crt;
+
+ TEST_START();
+
+ if (crypt_load_crt_str(signed_server_crt, &crt) < 0) {
+ printf("Failed to load public certificate from string.\n");
+ goto fail_crt;
+ }
+
+ if (crypt_load_pubkey_str(server_ec_pk, &pk) < 0) {
+ printf("Failed to load public key from string.\n");
+ goto fail_pubkey;
+ }
+
+ if (crypt_get_pubkey_crt(crt, &crt_pk) < 0) {
+ printf("Failed to get public key from certificate.\n");
+ goto fail_get_pubkey;
+ }
+
+ if (crypt_cmp_key(pk, crt_pk) != 0) {
+ printf("Public keys do not match .\n");
+ goto fail_check;
+ }
+
+
+ crypt_free_key(crt_pk);
+ crypt_free_key(pk);
+ crypt_free_crt(crt);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_check:
+ crypt_free_key(crt_pk);
+ fail_get_pubkey:
+ crypt_free_key(pk);
+ fail_pubkey:
+ crypt_free_crt(crt);
+ fail_crt:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_verify_crt(void)
+{
+ struct auth_ctx * auth;
+ void * _server_crt;
+ void * _signed_server_crt;
+ void * _root_ca_crt;
+ void * _intermediate_ca_crt;
+
+ TEST_START();
+
+
+ auth = auth_create_ctx();
+ if (auth == NULL) {
+ printf("Failed to create auth context.\n");
+ goto fail_create_ctx;
+ }
+
+ if (crypt_load_crt_str(server_crt, &_server_crt) < 0) {
+ printf("Failed to load self-signed crt from string.\n");
+ goto fail_load_server_crt;
+ }
+
+ if (crypt_load_crt_str(signed_server_crt, &_signed_server_crt) < 0) {
+ printf("Failed to load signed crt from string.\n");
+ goto fail_load_signed_server_crt;
+ }
+
+ if (crypt_load_crt_str(root_ca_crt, &_root_ca_crt) < 0) {
+ printf("Failed to load root crt from string.\n");
+ goto fail_load_root_ca_crt;
+ }
+
+ if (crypt_load_crt_str(intermediate_ca_crt, &_intermediate_ca_crt) < 0) {
+ printf("Failed to load intermediate crt from string.\n");
+ goto fail_load_intermediate_ca_crt;
+ }
+
+ if (auth_add_crt_to_store(auth, _root_ca_crt) < 0) {
+ printf("Failed to add root ca crt to auth store.\n");
+ goto fail_verify;
+ }
+
+ if (auth_add_crt_to_store(auth, _intermediate_ca_crt) < 0) {
+ printf("Failed to add intermediate ca crt to auth store.\n");
+ goto fail_verify;
+ }
+
+ if (auth_verify_crt(auth, _signed_server_crt) < 0) {
+ printf("Failed to verify signed crt with ca crt.\n");
+ goto fail_verify;
+ }
+
+ if (auth_verify_crt(auth, _server_crt) == 0) {
+ printf("Failed to detect untrusted crt.\n");
+ goto fail_verify;
+ }
+
+ crypt_free_crt(_intermediate_ca_crt);
+ crypt_free_crt(_root_ca_crt);
+ crypt_free_crt(_signed_server_crt);
+ crypt_free_crt(_server_crt);
+
+ auth_destroy_ctx(auth);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_verify:
+ crypt_free_crt(_intermediate_ca_crt);
+ fail_load_intermediate_ca_crt:
+ crypt_free_crt(_root_ca_crt);
+ fail_load_root_ca_crt:
+ crypt_free_crt(_signed_server_crt);
+ fail_load_signed_server_crt:
+ crypt_free_crt(_server_crt);
+ fail_load_server_crt:
+ auth_destroy_ctx(auth);
+ fail_create_ctx:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int test_auth_sign(void)
+{
+ uint8_t buf[TEST_MSG_SIZE];
+ void * pkp;
+ void * pk;
+ buffer_t msg;
+ buffer_t sig;
+
+ TEST_START();
+
+ msg.data = buf;
+ msg.len = sizeof(buf);
+
+ if (random_buffer(msg.data, msg.len) < 0) {
+ printf("Failed to generate random message.\n");
+ goto fail_init;
+ }
+
+ if (crypt_load_privkey_str(server_ec_pkp, &pkp) < 0) {
+ printf("Failed to load server key pair from string.\n");
+ goto fail_init;
+ }
+
+ if (crypt_load_pubkey_str(server_ec_pk, &pk) < 0) {
+ printf("Failed to load public key.\n");
+ goto fail_pubkey;
+ }
+
+ if (auth_sign(pkp, msg, &sig) < 0) {
+ printf("Failed to sign message.\n");
+ goto fail_sign;
+ }
+
+ if (auth_verify_sig(pk, msg, sig) < 0) {
+ printf("Failed to verify signature.\n");
+ goto fail_verify;
+ }
+
+ freebuf(sig);
+
+ crypt_free_key(pk);
+ crypt_free_key(pkp);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_verify:
+ freebuf(sig);
+ fail_sign:
+ crypt_free_key(pk);
+ fail_pubkey:
+ crypt_free_key(pkp);
+ fail_init:
+ return TEST_RC_FAIL;
+}
+
+int test_auth_bad_signature(void)
+{
+ uint8_t buf[TEST_MSG_SIZE];
+ void * pkp;
+ void * pk;
+ buffer_t msg;
+ buffer_t sig;
+ buffer_t fake_sig;
+
+ TEST_START();
+
+ msg.data = buf;
+ msg.len = sizeof(buf);
+
+ if (random_buffer(msg.data, msg.len) < 0) {
+ printf("Failed to generate random message.\n");
+ goto fail_init;
+ }
+
+ if (crypt_load_privkey_str(server_ec_pkp, &pkp) < 0) {
+ printf("Failed to load server key pair from string.\n");
+ goto fail_init;
+ }
+
+ if (crypt_load_pubkey_str(server_ec_pk, &pk) < 0) {
+ printf("Failed to load public key.\n");
+ goto fail_pubkey;
+ }
+
+ if (auth_sign(pkp, msg, &sig) < 0) {
+ printf("Failed to sign message.\n");
+ goto fail_sign;
+ }
+
+ fake_sig.data = malloc(sig.len);
+ if (fake_sig.data == NULL) {
+ printf("Failed to allocate memory for fake signature.\n");
+ goto fail_malloc;
+ }
+
+ fake_sig.len = sig.len;
+ if (random_buffer(fake_sig.data, fake_sig.len) < 0) {
+ printf("Failed to generate random fake signature.\n");
+ goto fail_malloc;
+ }
+
+ if (auth_verify_sig(pk, msg, fake_sig) == 0) {
+ printf("Failed to detect bad signature.\n");
+ goto fail_verify;
+ }
+
+ freebuf(sig);
+
+ crypt_free_key(pk);
+ crypt_free_key(pkp);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_verify:
+ freebuf(fake_sig);
+ fail_malloc:
+ freebuf(sig);
+ fail_sign:
+ crypt_free_key(pk);
+ fail_pubkey:
+ crypt_free_key(pkp);
+ fail_init:
+ return TEST_RC_FAIL;
+}
+
+int auth_test(int argc,
+ char ** argv)
+{
+ int ret = 0;
+
+ (void) argc;
+ (void) argv;
+
+ ret |= test_auth_create_destroy_ctx();
+#ifdef HAVE_OPENSSL
+ ret |= test_load_free_crt();
+ ret |= test_check_crt_name();
+ ret |= test_crypt_get_pubkey_crt();
+ ret |= test_load_free_privkey();
+ ret |= test_load_free_pubkey();
+ ret |= test_crypt_check_pubkey_crt();
+ ret |= test_verify_crt();
+ ret |= test_auth_sign();
+ ret |= test_auth_bad_signature();
+#else
+ (void) test_load_free_crt;
+ (void) test_check_crt_name;
+ (void) test_crypt_get_pubkey_crt;
+ (void) test_load_free_privkey;
+ (void) test_load_free_pubkey;
+ (void) test_crypt_check_pubkey_crt;
+ (void) test_verify_crt;
+ (void) test_auth_sign;
+ (void) test_auth_bad_signature;
+
+ ret = TEST_RC_SKIP;
+#endif
+ return ret;
+}
diff --git a/src/lib/tests/crypt_test.c b/src/lib/tests/crypt_test.c
new file mode 100644
index 00000000..7f011e5c
--- /dev/null
+++ b/src/lib/tests/crypt_test.c
@@ -0,0 +1,256 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Test of the cryptography functions
+ *
+ * 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 <ouroboros/test.h>
+#include <ouroboros/crypt.h>
+#include <ouroboros/random.h>
+#include <ouroboros/utils.h>
+
+#define TEST_PACKET_SIZE 1500
+
+static int test_crypt_create_destroy(void)
+{
+ struct crypt_ctx * ctx;
+
+ TEST_START();
+
+ ctx = crypt_create_ctx(0, NULL);
+ if (ctx == NULL) {
+ printf("Failed to initialize cryptography.\n");
+ goto fail;
+ }
+
+ crypt_destroy_ctx(ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_crypt_create_destroy_with_key(void)
+{
+ struct crypt_ctx * ctx;
+ uint8_t key[SYMMKEYSZ];
+
+ TEST_START();
+
+ memset(key, 0, sizeof(key));
+
+ ctx = crypt_create_ctx(1, key);
+ if (ctx == NULL) {
+ printf("Failed to initialize cryptography.\n");
+ goto fail;
+ }
+
+ crypt_destroy_ctx(ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_crypt_dh_pkp_create_destroy(void)
+{
+ void * pkp;
+ uint8_t buf[MSGBUFSZ];
+
+ TEST_START();
+
+ if (crypt_dh_pkp_create(&pkp, buf) < 0) {
+ printf("Failed to create DH PKP.");
+ goto fail;
+ }
+
+ crypt_dh_pkp_destroy(pkp);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_crypt_dh_derive(void)
+{
+ void * pkp1;
+ void * pkp2;
+ buffer_t pk1;
+ buffer_t pk2;
+ ssize_t len;
+ uint8_t buf1[MSGBUFSZ];
+ uint8_t buf2[MSGBUFSZ];
+ uint8_t s1[SYMMKEYSZ];
+ uint8_t s2[SYMMKEYSZ];
+
+ TEST_START();
+
+ len = crypt_dh_pkp_create(&pkp1, buf1);
+ if (len < 0) {
+ printf("Failed to create first key pair.");
+ goto fail_pkp1;
+ }
+
+ pk1.len = (size_t) len;
+ pk1.data = buf1;
+
+ len = crypt_dh_pkp_create(&pkp2, buf2);
+ if (len < 0) {
+ printf("Failed to create second key pair.");
+ goto fail_pkp2;
+ }
+
+ pk2.len = (size_t) len;
+ pk2.data = buf2;
+
+ if (crypt_dh_derive(pkp1, pk2, s1) < 0) {
+ printf("Failed to derive first key.");
+ goto fail;
+ }
+
+ if (crypt_dh_derive(pkp2, pk1, s2) < 0) {
+ printf("Failed to derive second key.");
+ goto fail;
+ }
+
+ if (memcmp(s1, s2, SYMMKEYSZ) != 0) {
+ printf("Derived keys do not match.");
+ goto fail;
+ }
+
+ crypt_dh_pkp_destroy(pkp2);
+ crypt_dh_pkp_destroy(pkp1);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ crypt_dh_pkp_destroy(pkp2);
+ fail_pkp2:
+ crypt_dh_pkp_destroy(pkp1);
+ fail_pkp1:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int test_crypt_encrypt_decrypt(void)
+{
+ uint8_t pkt[TEST_PACKET_SIZE];
+ uint8_t key[SYMMKEYSZ];
+ struct crypt_ctx * ctx;
+ buffer_t in;
+ buffer_t out;
+ buffer_t out2;
+
+ TEST_START();
+
+ if (random_buffer(key, sizeof(key)) < 0) {
+ printf("Failed to generate random key.\n");
+ goto fail_init;
+ }
+
+ if (random_buffer(pkt, sizeof(pkt)) < 0) {
+ printf("Failed to generate random data.\n");
+ goto fail_init;
+ }
+
+ ctx = crypt_create_ctx(1, key);
+ if (ctx == NULL) {
+ printf("Failed to initialize cryptography.\n");
+ goto fail_init;
+ }
+
+ in.len = sizeof(pkt);
+ in.data = pkt;
+
+ if (crypt_encrypt(ctx, in, &out) < 0) {
+ printf("Encryption failed.\n");
+ goto fail_encrypt;
+ }
+
+ if (out.len < in.len) {
+ printf("Encryption returned too little data.\n");
+ goto fail_encrypt;
+ }
+
+ if (crypt_decrypt(ctx, out, &out2) < 0) {
+ printf("Decryption failed.\n");
+ goto fail_decrypt;
+ }
+
+ if (out2.len != in.len) {
+ printf("Decrypted data length does not match original.\n");
+ goto fail_chk;
+ }
+
+ if (memcmp(in.data, out2.data, in.len) != 0) {
+ printf("Decrypted data does not match original.\n");
+ goto fail_chk;
+ }
+
+ crypt_destroy_ctx(ctx);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_chk:
+ freebuf(out2);
+ fail_decrypt:
+ freebuf(out);
+ fail_encrypt:
+ crypt_destroy_ctx(ctx);
+ fail_init:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int crypt_test(int argc,
+ char ** argv)
+{
+ int ret = 0;
+
+ (void) argc;
+ (void) argv;
+
+ ret |= test_crypt_create_destroy();
+ ret |= test_crypt_create_destroy_with_key();
+#ifdef HAVE_OPENSSL
+ ret |= test_crypt_dh_pkp_create_destroy();
+ ret |= test_crypt_dh_derive();
+ ret |= test_crypt_encrypt_decrypt();
+#else
+ (void) test_crypt_dh_pkp_create_destroy;
+ (void) test_crypt_dh_derive;
+ (void) test_crypt_encrypt_decrypt;
+
+ ret = TEST_RC_SKIP;
+#endif
+ return ret;
+}
diff --git a/src/lib/tests/sockets_test.c b/src/lib/tests/sockets_test.c
new file mode 100644
index 00000000..bbf2323b
--- /dev/null
+++ b/src/lib/tests/sockets_test.c
@@ -0,0 +1,98 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Tests for socket.c
+ *
+ * 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/.
+ */
+
+#define _POSIX_C_SOURCE 200112L
+
+#include <ouroboros/sockets.h>
+#include <ouroboros/test.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TEST_PID 1234
+#define TEST_PID_STR "1234"
+#define TEST_SERVER_PATH "/tmp/test.sock"
+#define TEST_SERVER_PREFIX "/tmp/ouroboros/test."
+#define TEST_SOCK_PATH_PREFIX "var/run/ouroboros/test."
+
+static int test_sock_path(void)
+{
+ char * path;
+ char * exp = TEST_SOCK_PATH_PREFIX TEST_PID_STR SOCK_PATH_SUFFIX;
+
+ TEST_START();
+
+ path = sock_path(TEST_PID, TEST_SOCK_PATH_PREFIX);
+ if (path == NULL) {
+ printf("Path is NULL.\n");
+ goto fail_path;
+ }
+
+ if (strcmp(path, exp) != 0) {
+ printf("Expected path '%s', got '%s'.\n", exp, path);
+ goto fail_cmp;
+ }
+
+ free(path);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+ fail_cmp:
+ free(path);
+ fail_path:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_server_socket_open(void)
+{
+ int sockfd;
+
+ TEST_START();
+
+ sockfd = server_socket_open(TEST_SERVER_PATH);
+ if (sockfd < 0) {
+ printf("Failed to open server socket.\n");
+ goto fail_sock;
+ }
+
+ close(sockfd);
+
+ unlink(TEST_SERVER_PATH);
+
+ TEST_SUCCESS();
+ return TEST_RC_SUCCESS;
+ fail_sock:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int sockets_test(void)
+{
+ int ret = 0;
+
+ ret |= test_sock_path();
+ ret |= test_server_socket_open();
+
+ return ret;
+}
diff --git a/src/lib/tests/time_test.c b/src/lib/tests/time_test.c
index 65f896bb..77fecdac 100644
--- a/src/lib/tests/time_test.c
+++ b/src/lib/tests/time_test.c
@@ -28,12 +28,14 @@
static void ts_print(struct timespec * s)
{
- printf("timespec is %zd:%ld.\n", (ssize_t) s->tv_sec, s->tv_nsec);
+ printf("timespec is %zd:%ld.\n",
+ (ssize_t) s->tv_sec, s->tv_nsec);
}
static void tv_print(struct timeval * v)
{
- printf("timeval is %zd:%zu.\n", (ssize_t) v->tv_sec, (size_t) v->tv_usec);
+ printf("timeval is %zd:%zu.\n",
+ (ssize_t) v->tv_sec, (size_t) v->tv_usec);
}
static void ts_init(struct timespec * s,
diff --git a/src/lib/tests/tpm_test.c b/src/lib/tests/tpm_test.c
new file mode 100644
index 00000000..98d4fab3
--- /dev/null
+++ b/src/lib/tests/tpm_test.c
@@ -0,0 +1,104 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * Tests for the threadpool manager
+ *
+ * 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 "tpm.c"
+
+#include <ouroboros/test.h>
+
+static void * test_func(void * o)
+{
+ (void) o;
+
+ while(1)
+ sleep(1);
+
+ return NULL;
+}
+
+static int test_tpm_create_destroy(void)
+{
+ struct tpm *tpm;
+
+ TEST_START();
+
+ tpm = tpm_create(2, 2, &test_func, NULL);
+ if (tpm == NULL) {
+ printf("Failed to initialize TPM.\n");
+ goto fail;
+ }
+
+ tpm_destroy(tpm);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+static int test_tpm_start_stop(void * (* fn)(void *),
+ void * o)
+{
+ struct tpm *tpm;
+
+ TEST_START();
+
+ tpm = tpm_create(2, 2, fn, o);
+ if (tpm == NULL) {
+ printf("Failed to initialize TPM.\n");
+ goto fail_create;
+ }
+
+ if (tpm_start(tpm) < 0) {
+ printf("Failed to start TPM.\n");
+ goto fail_start;
+ }
+
+ tpm_stop(tpm);
+
+ tpm_destroy(tpm);
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail_start:
+ tpm_destroy(tpm);
+ fail_create:
+ TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
+int tpm_test(int argc,
+ char ** argv)
+{
+ int ret = 0;
+
+ (void) argc;
+ (void) argv;
+
+ ret |= test_tpm_create_destroy();
+ ret |= test_tpm_start_stop(&test_func, NULL);
+
+ return ret;
+}
diff --git a/src/lib/tpm.c b/src/lib/tpm.c
index 0ef1fda8..64777815 100644
--- a/src/lib/tpm.c
+++ b/src/lib/tpm.c
@@ -63,7 +63,7 @@ struct tpm {
enum tpm_state state;
pthread_cond_t cond;
- pthread_mutex_t lock;
+ pthread_mutex_t mtx;
pthread_t mgr;
};
@@ -90,11 +90,11 @@ static void tpm_join(struct tpm * tpm)
pthread_t thr = e->thr;
list_del(&e->next);
free(e);
- pthread_mutex_unlock(&tpm->lock);
+ pthread_mutex_unlock(&tpm->mtx);
pthread_join(thr, NULL);
- pthread_mutex_lock(&tpm->lock);
+ pthread_mutex_lock(&tpm->mtx);
}
}
}
@@ -114,56 +114,59 @@ static void tpm_kill(struct tpm * tpm)
}
}
-static void * tpmgr(void * o)
+static int __tpm(struct tpm * tpm)
{
struct timespec dl;
struct timespec to = TIMESPEC_INIT_MS(TPM_TIMEOUT);
- struct tpm * tpm = (struct tpm *) o;
-
- while (true) {
- clock_gettime(PTHREAD_COND_CLOCK, &dl);
- ts_add(&dl, &to, &dl);
- pthread_mutex_lock(&tpm->lock);
+ clock_gettime(PTHREAD_COND_CLOCK, &dl);
+ ts_add(&dl, &to, &dl);
- if (tpm->state != TPM_RUNNING) {
- tpm_join(tpm);
- pthread_mutex_unlock(&tpm->lock);
- break;
- }
+ pthread_mutex_lock(&tpm->mtx);
+ if (tpm->state != TPM_RUNNING) {
tpm_join(tpm);
+ pthread_mutex_unlock(&tpm->mtx);
+ return -1;
+ }
- if (tpm->cur - tpm->wrk < tpm->min) {
- size_t i;
- for (i = 0; i < tpm->inc; ++i) {
- struct pthr_el * e = malloc(sizeof(*e));
- if (e == NULL)
- break;
+ tpm_join(tpm);
- e->kill = false;
- e->busy = false;
+ if (tpm->cur - tpm->wrk < tpm->min) {
+ size_t i;
+ for (i = 0; i < tpm->inc; ++i) {
+ struct pthr_el * e = malloc(sizeof(*e));
+ if (e == NULL)
+ break;
- if (pthread_create(&e->thr, NULL,
- tpm->func, tpm->o)) {
- free(e);
- break;
- }
+ e->kill = false;
+ e->busy = false;
- list_add(&e->next, &tpm->pool);
+ if (pthread_create(&e->thr, NULL,
+ tpm->func, tpm->o)) {
+ free(e);
+ break;
}
- tpm->cur += i;
+ list_add(&e->next, &tpm->pool);
}
- if (pthread_cond_timedwait(&tpm->cond, &tpm->lock, &dl)
- == ETIMEDOUT)
- if (tpm->cur - tpm->wrk > tpm->min)
- tpm_kill(tpm);
-
- pthread_mutex_unlock(&tpm->lock);
+ tpm->cur += i;
}
+ if (pthread_cond_timedwait(&tpm->cond, &tpm->mtx, &dl) == ETIMEDOUT)
+ if (tpm->cur - tpm->wrk > tpm->min)
+ tpm_kill(tpm);
+
+ pthread_mutex_unlock(&tpm->mtx);
+
+ return 0;
+}
+
+static void * tpmgr(void * o)
+{
+ while (__tpm((struct tpm *) o) == 0);
+
return (void *) 0;
}
@@ -175,11 +178,14 @@ struct tpm * tpm_create(size_t min,
struct tpm * tpm;
pthread_condattr_t cattr;
+ assert(func != NULL);
+ assert(inc > 0);
+
tpm = malloc(sizeof(*tpm));
if (tpm == NULL)
goto fail_malloc;
- if (pthread_mutex_init(&tpm->lock, NULL))
+ if (pthread_mutex_init(&tpm->mtx, NULL))
goto fail_lock;
if (pthread_condattr_init(&cattr))
@@ -208,7 +214,7 @@ struct tpm * tpm_create(size_t min,
fail_cond:
pthread_condattr_destroy(&cattr);
fail_cattr:
- pthread_mutex_destroy(&tpm->lock);
+ pthread_mutex_destroy(&tpm->mtx);
fail_lock:
free(tpm);
fail_malloc:
@@ -217,34 +223,39 @@ struct tpm * tpm_create(size_t min,
int tpm_start(struct tpm * tpm)
{
- pthread_mutex_lock(&tpm->lock);
+ pthread_mutex_lock(&tpm->mtx);
if (pthread_create(&tpm->mgr, NULL, tpmgr, tpm)) {
- pthread_mutex_unlock(&tpm->lock);
+ pthread_mutex_unlock(&tpm->mtx);
return -1;
}
tpm->state = TPM_RUNNING;
- pthread_mutex_unlock(&tpm->lock);
+ pthread_mutex_unlock(&tpm->mtx);
return 0;
}
void tpm_stop(struct tpm * tpm)
{
- pthread_mutex_lock(&tpm->lock);
+ pthread_mutex_lock(&tpm->mtx);
+
+ if (tpm->state != TPM_RUNNING) {
+ pthread_mutex_unlock(&tpm->mtx);
+ return;
+ }
tpm->state = TPM_NULL;
- pthread_mutex_unlock(&tpm->lock);
+ pthread_mutex_unlock(&tpm->mtx);
pthread_join(tpm->mgr, NULL);
}
void tpm_destroy(struct tpm * tpm)
{
- pthread_mutex_destroy(&tpm->lock);
+ pthread_mutex_destroy(&tpm->mtx);
pthread_cond_destroy(&tpm->cond);
free(tpm);
@@ -260,40 +271,39 @@ static struct pthr_el * tpm_pthr_el(struct tpm * tpm,
e = list_entry(p, struct pthr_el, next);
if (e->thr == thr)
return e;
-
}
return NULL;
}
-void tpm_inc(struct tpm * tpm)
+void tpm_begin_work(struct tpm * tpm)
{
struct pthr_el * e;
- pthread_mutex_lock(&tpm->lock);
+ pthread_mutex_lock(&tpm->mtx);
e = tpm_pthr_el(tpm, pthread_self());
if (e != NULL) {
- e->busy = false;
- --tpm->wrk;
+ e->busy = true;
+ ++tpm->wrk;
}
- pthread_mutex_unlock(&tpm->lock);
+ pthread_cond_signal(&tpm->cond);
+
+ pthread_mutex_unlock(&tpm->mtx);
}
-void tpm_dec(struct tpm * tpm)
+void tpm_end_work(struct tpm * tpm)
{
struct pthr_el * e;
- pthread_mutex_lock(&tpm->lock);
+ pthread_mutex_lock(&tpm->mtx);
e = tpm_pthr_el(tpm, pthread_self());
if (e != NULL) {
- e->busy = true;
- ++tpm->wrk;
+ e->busy = false;
+ --tpm->wrk;
}
- pthread_cond_signal(&tpm->cond);
-
- pthread_mutex_unlock(&tpm->lock);
+ pthread_mutex_unlock(&tpm->mtx);
}
diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c
index 6f76869c..11e10a77 100644
--- a/src/tools/oping/oping_server.c
+++ b/src/tools/oping/oping_server.c
@@ -36,6 +36,8 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+ #include <ouroboros/hash.h>
+
void shutdown_server(int signo, siginfo_t * info, void * c)
{
(void) info;
@@ -100,14 +102,15 @@ void * server_thread(void *o)
if (msg_len < 0)
continue;
+ if (!server.quiet)
+ printf("Received %d bytes on fd %d.\n",
+ msg_len, fd);
+
if (ntohl(msg->type) != ECHO_REQUEST) {
printf("Invalid message on fd %d.\n", fd);
continue;
}
- if (!server.quiet)
- printf("Received %d bytes on fd %d.\n", msg_len, fd);
-
clock_gettime(CLOCK_REALTIME, &now);
pthread_mutex_lock(&server.lock);