diff options
Diffstat (limited to 'src')
39 files changed, 1221 insertions, 243 deletions
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c index 4be7775e..8293ac15 100644 --- a/src/ipcpd/eth/eth.c +++ b/src/ipcpd/eth/eth.c @@ -43,6 +43,7 @@ #include <ouroboros/list.h> #include <ouroboros/utils.h> #include <ouroboros/bitmap.h> +#include <ouroboros/crc8.h> #include <ouroboros/dev.h> #include <ouroboros/ipcp-dev.h> #include <ouroboros/fqueue.h> @@ -122,7 +123,8 @@ #define MGMT_EID 0 #define DIX_EID_SIZE sizeof(uint16_t) #define DIX_LENGTH_SIZE sizeof(uint16_t) -#define DIX_HEADER_SIZE (DIX_EID_SIZE + DIX_LENGTH_SIZE) +#define DIX_HCS_SIZE CRC8_HASH_LEN +#define DIX_HEADER_SIZE (DIX_EID_SIZE + DIX_LENGTH_SIZE + DIX_HCS_SIZE) #define ETH_HEADER_TOT_SIZE (ETH_HEADER_SIZE + DIX_HEADER_SIZE) #define MAX_EIDS (1 << (8 * DIX_EID_SIZE)) #define ETH_MAX_PACKET_SIZE (ETH_MTU - DIX_HEADER_SIZE) @@ -130,7 +132,9 @@ #elif defined(BUILD_ETH_LLC) #define THIS_TYPE IPCP_ETH_LLC #define MGMT_SAP 0x01 -#define LLC_HEADER_SIZE 3 +#define LLC_FIELDS_SIZE 3 +#define LLC_HCS_SIZE CRC8_HASH_LEN +#define LLC_HEADER_SIZE (LLC_FIELDS_SIZE + LLC_HCS_SIZE) #define ETH_HEADER_TOT_SIZE (ETH_HEADER_SIZE + LLC_HEADER_SIZE) #define MAX_SAPS 64 #define ETH_MAX_PACKET_SIZE (ETH_MTU - LLC_HEADER_SIZE) @@ -185,6 +189,7 @@ struct eth_frame { uint8_t ssap; uint8_t cf; #endif + uint8_t hcs; uint8_t payload; } __attribute__((packed)); @@ -409,12 +414,18 @@ static int eth_ipcp_send_frame(const uint8_t * dst_addr, e_frame->ethertype = eth_data.ethertype; e_frame->eid = htons(deid); e_frame->length = htons(len); + mem_hash(HASH_CRC8, &e_frame->hcs, + (uint8_t *) &e_frame->eid, + DIX_EID_SIZE + DIX_LENGTH_SIZE); frame_len = ETH_HEADER_TOT_SIZE + len; #elif defined(BUILD_ETH_LLC) e_frame->length = htons(LLC_HEADER_SIZE + len); e_frame->dsap = dsap; e_frame->ssap = ssap; e_frame->cf = cf; + mem_hash(HASH_CRC8, &e_frame->hcs, + (uint8_t *) &e_frame->dsap, + LLC_FIELDS_SIZE); frame_len = ETH_HEADER_TOT_SIZE + len; #endif @@ -718,13 +729,17 @@ static int eth_ipcp_mgmt_frame(const uint8_t * buf, qosspec_t qs; buffer_t data; + if (len < sizeof(*msg)) + return -1; + msg = (struct mgmt_msg *) buf; switch (msg->code) { case FLOW_REQ: msg_len = sizeof(*msg) + ipcp_dir_hash_len(); - assert(len >= msg_len); + if (len < msg_len) + return -1; qs.delay = ntoh32(msg->delay); qs.bandwidth = ntoh64(msg->bandwidth); @@ -752,8 +767,6 @@ static int eth_ipcp_mgmt_frame(const uint8_t * buf, } break; case FLOW_REPLY: - assert(len >= sizeof(*msg)); - data.data = (uint8_t *) buf + sizeof(*msg); data.len = len - sizeof(*msg); @@ -769,9 +782,13 @@ static int eth_ipcp_mgmt_frame(const uint8_t * buf, &data); break; case NAME_QUERY_REQ: + if (len < sizeof(*msg) + ipcp_dir_hash_len()) + return -1; eth_ipcp_name_query_req(buf + sizeof(*msg), r_addr); break; case NAME_QUERY_REPLY: + if (len < sizeof(*msg) + ipcp_dir_hash_len()) + return -1; eth_ipcp_name_query_reply(buf + sizeof(*msg), r_addr); break; default: @@ -844,6 +861,8 @@ static void * eth_ipcp_packet_reader(void * o) fd_set fds; int frame_len; #endif + size_t eth_len; + uint8_t hcs; struct eth_frame * e_frame; struct mgmt_frame * frame; @@ -923,17 +942,48 @@ static void * eth_ipcp_packet_reader(void * o) if (e_frame->ethertype != eth_data.ethertype) goto fail_frame; + if (length > ETH_MTU) + goto fail_frame; + deid = ntohs(e_frame->eid); - if (deid == MGMT_EID) { #elif defined (BUILD_ETH_LLC) if (length > 0x05FF) /* DIX */ goto fail_frame; + if (length < LLC_HEADER_SIZE || length > ETH_MTU) + goto fail_frame; + length -= LLC_HEADER_SIZE; dsap = reverse_bits(e_frame->dsap); ssap = reverse_bits(e_frame->ssap); +#endif + +#if defined(HAVE_NETMAP) + eth_len = hdr.len; +#elif defined(HAVE_BPF) + eth_len = ((struct bpf_hdr *) buf)->bh_caplen; +#else + eth_len = (size_t) frame_len; +#endif + if (eth_len < ETH_HEADER_TOT_SIZE + (size_t) length) + goto fail_frame; +#if defined(BUILD_ETH_DIX) + mem_hash(HASH_CRC8, &hcs, + (uint8_t *) &e_frame->eid, + DIX_EID_SIZE + DIX_LENGTH_SIZE); +#elif defined(BUILD_ETH_LLC) + mem_hash(HASH_CRC8, &hcs, + (uint8_t *) &e_frame->dsap, + LLC_FIELDS_SIZE); +#endif + if (hcs != e_frame->hcs) + goto fail_frame; + +#if defined(BUILD_ETH_DIX) + if (deid == MGMT_EID) { +#elif defined (BUILD_ETH_LLC) if (ssap == MGMT_SAP && dsap == MGMT_SAP) { #endif ipcp_spb_release(spb); /* No need for the N+1 buffer. */ diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 377a7df3..2c867317 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -236,15 +236,6 @@ static int local_ipcp_flow_alloc_resp(int fd, return -1; } - if (response < 0) { - pthread_rwlock_wrlock(&local_data.lock); - if (local_data.in_out[fd] != -1) - local_data.in_out[local_data.in_out[fd]] = fd; - local_data.in_out[fd] = -1; - pthread_rwlock_unlock(&local_data.lock); - return 0; - } - pthread_rwlock_rdlock(&local_data.lock); out_fd = local_data.in_out[fd]; @@ -263,6 +254,12 @@ static int local_ipcp_flow_alloc_resp(int fd, return -1; } + if (response < 0) { + ipcp_flow_alloc_reply(out_fd, response, mpl, data); + log_info("Flow allocation rejected, fds (%d, %d).", out_fd, fd); + return 0; + } + fset_add(local_data.flows, fd); if (ipcp_flow_alloc_reply(out_fd, response, mpl, data) < 0) { diff --git a/src/ipcpd/unicast/fa.c b/src/ipcpd/unicast/fa.c index ddf78e22..c157d71c 100644 --- a/src/ipcpd/unicast/fa.c +++ b/src/ipcpd/unicast/fa.c @@ -58,12 +58,12 @@ #define CLOCK_REALTIME_COARSE CLOCK_REALTIME #endif -#define TIMEOUT 10 * MILLION /* nanoseconds */ +#define TIMEOUT 10 * MILLION /* nanoseconds */ +#define MSGBUFSZ 32768 #define FLOW_REQ 0 #define FLOW_REPLY 1 #define FLOW_UPDATE 2 -#define MSGBUFSZ 2048 #define STAT_FILE_LEN 0 diff --git a/src/irmd/main.c b/src/irmd/main.c index e610a015..a85a9bf0 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -2416,6 +2416,7 @@ int main(int argc, pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); crypt_secure_malloc_fini(); + crypt_cleanup(); reg_clear(); diff --git a/src/irmd/oap.c b/src/irmd/oap.c deleted file mode 100644 index 1831f533..00000000 --- a/src/irmd/oap.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2026 - * - * OAP - Shared credential and configuration loading - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#if defined(__linux__) || defined(__CYGWIN__) - #define _DEFAULT_SOURCE -#else - #define _POSIX_C_SOURCE 200809L -#endif - -#define OUROBOROS_PREFIX "irmd/oap" - -#include <ouroboros/crypt.h> -#include <ouroboros/errno.h> -#include <ouroboros/logs.h> - -#include "config.h" - -#include <assert.h> -#include <string.h> -#include <sys/stat.h> - -/* - * Shared credential and configuration loading helpers - */ - -#ifndef OAP_TEST_MODE - -static bool file_exists(const char * path) -{ - struct stat s; - - if (stat(path, &s) < 0 && errno == ENOENT) { - log_dbg("File %s does not exist.", path); - return false; - } - - return true; -} - -int load_credentials(const char * name, - const struct name_sec_paths * paths, - void ** pkp, - void ** crt) -{ - assert(paths != NULL); - assert(pkp != NULL); - assert(crt != NULL); - - *pkp = NULL; - *crt = NULL; - - if (!file_exists(paths->crt) || !file_exists(paths->key)) { - log_info("No authentication certificates for %s.", name); - return 0; - } - - if (crypt_load_crt_file(paths->crt, crt) < 0) { - log_err("Failed to load %s for %s.", paths->crt, name); - goto fail_crt; - } - - if (crypt_load_privkey_file(paths->key, pkp) < 0) { - log_err("Failed to load %s for %s.", paths->key, name); - goto fail_key; - } - - log_info("Loaded authentication certificates for %s.", name); - - return 0; - - fail_key: - crypt_free_crt(*crt); - *crt = NULL; - fail_crt: - return -EAUTH; -} - -int load_kex_config(const char * name, - const char * path, - struct sec_config * cfg) -{ - assert(name != NULL); - assert(cfg != NULL); - - memset(cfg, 0, sizeof(*cfg)); - - /* Load encryption config */ - if (!file_exists(path)) - log_dbg("No encryption %s for %s.", path, name); - - if (load_sec_config_file(cfg, path) < 0) { - log_warn("Failed to load %s for %s.", path, name); - return -1; - } - - if (!IS_KEX_ALGO_SET(cfg)) { - log_info("Key exchange not configured for %s.", name); - return 0; - } - - if (cfg->c.nid == NID_undef || crypt_nid_to_str(cfg->c.nid) == NULL) { - log_err("Invalid cipher NID %d for %s.", cfg->c.nid, name); - return -ECRYPT; - } - - log_info("Encryption enabled for %s.", name); - - return 0; -} - -#endif /* OAP_TEST_MODE */ diff --git a/src/irmd/oap/auth.c b/src/irmd/oap/auth.c index a11ab158..4b86f055 100644 --- a/src/irmd/oap/auth.c +++ b/src/irmd/oap/auth.c @@ -183,7 +183,7 @@ int oap_auth_peer(char * name, const struct oap_hdr * peer_hdr) { void * crt; - void * pk; + void * pk = NULL; buffer_t sign; /* Signed region */ uint8_t * id = peer_hdr->id.data; @@ -244,8 +244,8 @@ int oap_auth_peer(char * name, return 0; fail_check_sig: - crypt_free_key(pk); fail_crt: + crypt_free_key(pk); crypt_free_crt(crt); fail_check: return -EAUTH; diff --git a/src/irmd/oap/cli.c b/src/irmd/oap/cli.c index 8ecd317d..7a202da7 100644 --- a/src/irmd/oap/cli.c +++ b/src/irmd/oap/cli.c @@ -50,7 +50,7 @@ struct oap_cli_ctx { uint8_t __id[OAP_ID_SIZE]; buffer_t id; - uint8_t kex_buf[MSGBUFSZ]; + uint8_t kex_buf[CRYPT_KEY_BUFSZ]; uint8_t req_hash[MAX_HASH_SIZE]; size_t req_hash_len; int req_md_nid; diff --git a/src/irmd/oap/srv.c b/src/irmd/oap/srv.c index 36391e50..afc54acc 100644 --- a/src/irmd/oap/srv.c +++ b/src/irmd/oap/srv.c @@ -384,7 +384,7 @@ int oap_srv_process(const struct name_info * info, struct oap_hdr peer_hdr; struct oap_hdr local_hdr; struct sec_config kcfg; - uint8_t kex_buf[MSGBUFSZ]; + uint8_t kex_buf[CRYPT_KEY_BUFSZ]; uint8_t hash_buf[MAX_HASH_SIZE]; buffer_t req_hash = BUF_INIT; ssize_t hash_ret; diff --git a/src/irmd/oap/tests/oap_test.c b/src/irmd/oap/tests/oap_test.c index 2f0f0b4d..a324b586 100644 --- a/src/irmd/oap/tests/oap_test.c +++ b/src/irmd/oap/tests/oap_test.c @@ -1071,6 +1071,74 @@ static int test_oap_replay_packet(void) return TEST_RC_FAIL; } +/* Server rejects client certificate when root CA is missing from store */ +static int test_oap_missing_root_ca(void) +{ + struct oap_test_ctx ctx; + void * im_ca = NULL; + + test_default_cfg(); + + TEST_START(); + + memset(&ctx, 0, sizeof(ctx)); + + strcpy(ctx.srv.info.name, "test-1.unittest.o7s"); + strcpy(ctx.cli.info.name, "test-1.unittest.o7s"); + + if (oap_auth_init() < 0) { + printf("Failed to init OAP.\n"); + goto fail; + } + + /* Load intermediate CA but intentionally omit the root CA */ + if (crypt_load_crt_str(im_ca_crt_ec, &im_ca) < 0) { + printf("Failed to load intermediate CA cert.\n"); + goto fail_fini; + } + + ctx.im_ca = im_ca; + + if (oap_auth_add_ca_crt(im_ca) < 0) { + printf("Failed to add intermediate CA cert to store.\n"); + goto fail_fini; + } + + if (oap_cli_prepare_ctx(&ctx) < 0) { + printf("Client prepare failed.\n"); + goto fail_fini; + } + + /* Server processes and signs response - succeeds without root CA */ + if (oap_srv_process_ctx(&ctx) < 0) { + printf("Server process failed.\n"); + goto fail_teardown; + } + + /* Client verifies server certificate against trust store: + * should reject because root CA is not in the store */ + if (oap_cli_complete_ctx(&ctx) == 0) { + printf("Client should reject without root CA.\n"); + goto fail_teardown; + } + + oap_test_teardown(&ctx); + + TEST_SUCCESS(); + return TEST_RC_SUCCESS; + + fail_teardown: + oap_test_teardown(&ctx); + TEST_FAIL(); + return TEST_RC_FAIL; + fail_fini: + crypt_free_crt(im_ca); + oap_auth_fini(); + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +} + /* Test that client rejects server with wrong certificate name */ static int test_oap_server_name_mismatch(void) { @@ -1149,6 +1217,7 @@ int oap_test(int argc, ret |= test_oap_outdated_packet(); ret |= test_oap_future_packet(); ret |= test_oap_replay_packet(); + ret |= test_oap_missing_root_ca(); ret |= test_oap_server_name_mismatch(); #else (void) test_oap_roundtrip_auth_only; @@ -1173,9 +1242,12 @@ int oap_test(int argc, (void) test_oap_outdated_packet; (void) test_oap_future_packet; (void) test_oap_replay_packet; + (void) test_oap_missing_root_ca; (void) test_oap_server_name_mismatch; ret = TEST_RC_SKIP; #endif + crypt_cleanup(); + return ret; } diff --git a/src/irmd/oap/tests/oap_test_ml_dsa.c b/src/irmd/oap/tests/oap_test_ml_dsa.c index f9e6bdb2..81b307ab 100644 --- a/src/irmd/oap/tests/oap_test_ml_dsa.c +++ b/src/irmd/oap/tests/oap_test_ml_dsa.c @@ -442,6 +442,7 @@ int oap_test_ml_dsa(int argc, ret = TEST_RC_SKIP; #endif + crypt_cleanup(); return ret; } diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c index b426c0dd..f4b0188b 100644 --- a/src/irmd/reg/tests/reg_test.c +++ b/src/irmd/reg/tests/reg_test.c @@ -1491,7 +1491,7 @@ static int test_wait_accepting_fail_name(void) static void * test_call_flow_accept(void * o) { struct timespec abstime; - struct timespec timeo = TIMESPEC_INIT_MS(10); + struct timespec timeo = TIMESPEC_INIT_MS(30); buffer_t pbuf = BUF_INIT; struct proc_info pinfo = TEST_PROC_INFO; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 79263924..f68d3601 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -17,7 +17,10 @@ protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS set(SOURCE_FILES_COMMON bitmap.c btree.c - crc32.c + crc/crc8.c + crc/crc16.c + crc/crc32.c + crc/crc64.c crypt.c hash.c lockfile.c @@ -155,5 +158,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ssm/ssm.h.in" if(BUILD_TESTS) add_subdirectory(tests) + add_subdirectory(crc/tests) add_subdirectory(ssm/tests) endif() diff --git a/src/lib/config.h.in b/src/lib/config.h.in index 08e9baf6..d1ae97ef 100644 --- a/src/lib/config.h.in +++ b/src/lib/config.h.in @@ -37,6 +37,8 @@ #cmakedefine QOS_DISABLE_CRC #cmakedefine HAVE_OPENSSL_RNG +#cmakedefine HAVE_PCLMUL +#cmakedefine HAVE_PMULL #define SHM_LOCKFILE_NAME "@SHM_LOCKFILE_NAME@" #define FLOW_ALLOC_TIMEOUT @FLOW_ALLOC_TIMEOUT@ diff --git a/src/lib/crc/crc16.c b/src/lib/crc/crc16.c new file mode 100644 index 00000000..9dc59429 --- /dev/null +++ b/src/lib/crc/crc16.c @@ -0,0 +1,61 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * 16-bit Cyclic Redundancy Check (CCITT-FALSE variant) + * + * 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/. + */ + +/* + * CRC-16/CCITT-FALSE (reveng catalog, alias CRC-16/IBM-3740): + * poly = 0x1021 + * init = 0xffff + * refin = false + * refout = false + * xorout = 0x0000 + * check = crc16_ccitt_false("123456789") == 0x29b1 + */ + +#include "config.h" + +#include <ouroboros/crc16.h> + +/* Bit-by-bit MSB-first CRC. */ +void crc16_ccitt_false(uint16_t * crc, + const void * buf, + size_t len) +{ + const uint8_t * p; + uint16_t c; + size_t n; + int i; + + p = (const uint8_t *) buf; + c = *crc ^ 0xffff; + + for (n = 0; n < len; n++) { + c ^= ((uint16_t) p[n]) << 8; + for (i = 0; i < 8; i++) { + if (c & 0x8000) + c = (uint16_t) ((c << 1) ^ 0x1021); + else + c = (uint16_t) (c << 1); + } + } + + *crc = c; +} diff --git a/src/lib/crc32.c b/src/lib/crc/crc32.c index 0fdb62b1..0fdb62b1 100644 --- a/src/lib/crc32.c +++ b/src/lib/crc/crc32.c diff --git a/src/lib/crc/crc64.c b/src/lib/crc/crc64.c new file mode 100644 index 00000000..1b6fb5f6 --- /dev/null +++ b/src/lib/crc/crc64.c @@ -0,0 +1,363 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * 64-bit Cyclic Redundancy Check (NVMe variant) + * + * 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/. + */ + +/* + * CRC-64/NVMe (reveng catalog): + * poly = 0xad93d23594c93659 + * init = 0xffffffffffffffff + * refin = true + * refout = true + * xorout = 0xffffffffffffffff + * check = crc64_nvme("123456789") == 0xae8b14860a799888 + */ + +#include "config.h" + +#include <ouroboros/crc64.h> + +/* + * Reflected CRC-64/NVMe table. Polynomial in reflected form: + * 0x9a6c9329ac4bc9b5 (bitrev of 0xad93d23594c93659). + */ +static const uint64_t crc64_nvme_tab[256] = { + 0x0000000000000000ULL, 0x7f6ef0c830358979ULL, + 0xfedde190606b12f2ULL, 0x81b31158505e9b8bULL, + 0xc962e5739841b68fULL, 0xb60c15bba8743ff6ULL, + 0x37bf04e3f82aa47dULL, 0x48d1f42bc81f2d04ULL, + 0xa61cecb46814fe75ULL, 0xd9721c7c5821770cULL, + 0x58c10d24087fec87ULL, 0x27affdec384a65feULL, + 0x6f7e09c7f05548faULL, 0x1010f90fc060c183ULL, + 0x91a3e857903e5a08ULL, 0xeecd189fa00bd371ULL, + 0x78e0ff3b88be6f81ULL, 0x078e0ff3b88be6f8ULL, + 0x863d1eabe8d57d73ULL, 0xf953ee63d8e0f40aULL, + 0xb1821a4810ffd90eULL, 0xceecea8020ca5077ULL, + 0x4f5ffbd87094cbfcULL, 0x30310b1040a14285ULL, + 0xdefc138fe0aa91f4ULL, 0xa192e347d09f188dULL, + 0x2021f21f80c18306ULL, 0x5f4f02d7b0f40a7fULL, + 0x179ef6fc78eb277bULL, 0x68f0063448deae02ULL, + 0xe943176c18803589ULL, 0x962de7a428b5bcf0ULL, + 0xf1c1fe77117cdf02ULL, 0x8eaf0ebf2149567bULL, + 0x0f1c1fe77117cdf0ULL, 0x7072ef2f41224489ULL, + 0x38a31b04893d698dULL, 0x47cdebccb908e0f4ULL, + 0xc67efa94e9567b7fULL, 0xb9100a5cd963f206ULL, + 0x57dd12c379682177ULL, 0x28b3e20b495da80eULL, + 0xa900f35319033385ULL, 0xd66e039b2936bafcULL, + 0x9ebff7b0e12997f8ULL, 0xe1d10778d11c1e81ULL, + 0x606216208142850aULL, 0x1f0ce6e8b1770c73ULL, + 0x8921014c99c2b083ULL, 0xf64ff184a9f739faULL, + 0x77fce0dcf9a9a271ULL, 0x08921014c99c2b08ULL, + 0x4043e43f0183060cULL, 0x3f2d14f731b68f75ULL, + 0xbe9e05af61e814feULL, 0xc1f0f56751dd9d87ULL, + 0x2f3dedf8f1d64ef6ULL, 0x50531d30c1e3c78fULL, + 0xd1e00c6891bd5c04ULL, 0xae8efca0a188d57dULL, + 0xe65f088b6997f879ULL, 0x9931f84359a27100ULL, + 0x1882e91b09fcea8bULL, 0x67ec19d339c963f2ULL, + 0xd75adabd7a6e2d6fULL, 0xa8342a754a5ba416ULL, + 0x29873b2d1a053f9dULL, 0x56e9cbe52a30b6e4ULL, + 0x1e383fcee22f9be0ULL, 0x6156cf06d21a1299ULL, + 0xe0e5de5e82448912ULL, 0x9f8b2e96b271006bULL, + 0x71463609127ad31aULL, 0x0e28c6c1224f5a63ULL, + 0x8f9bd7997211c1e8ULL, 0xf0f5275142244891ULL, + 0xb824d37a8a3b6595ULL, 0xc74a23b2ba0eececULL, + 0x46f932eaea507767ULL, 0x3997c222da65fe1eULL, + 0xafba2586f2d042eeULL, 0xd0d4d54ec2e5cb97ULL, + 0x5167c41692bb501cULL, 0x2e0934dea28ed965ULL, + 0x66d8c0f56a91f461ULL, 0x19b6303d5aa47d18ULL, + 0x980521650afae693ULL, 0xe76bd1ad3acf6feaULL, + 0x09a6c9329ac4bc9bULL, 0x76c839faaaf135e2ULL, + 0xf77b28a2faafae69ULL, 0x8815d86aca9a2710ULL, + 0xc0c42c4102850a14ULL, 0xbfaadc8932b0836dULL, + 0x3e19cdd162ee18e6ULL, 0x41773d1952db919fULL, + 0x269b24ca6b12f26dULL, 0x59f5d4025b277b14ULL, + 0xd846c55a0b79e09fULL, 0xa72835923b4c69e6ULL, + 0xeff9c1b9f35344e2ULL, 0x90973171c366cd9bULL, + 0x1124202993385610ULL, 0x6e4ad0e1a30ddf69ULL, + 0x8087c87e03060c18ULL, 0xffe938b633338561ULL, + 0x7e5a29ee636d1eeaULL, 0x0134d92653589793ULL, + 0x49e52d0d9b47ba97ULL, 0x368bddc5ab7233eeULL, + 0xb738cc9dfb2ca865ULL, 0xc8563c55cb19211cULL, + 0x5e7bdbf1e3ac9decULL, 0x21152b39d3991495ULL, + 0xa0a63a6183c78f1eULL, 0xdfc8caa9b3f20667ULL, + 0x97193e827bed2b63ULL, 0xe877ce4a4bd8a21aULL, + 0x69c4df121b863991ULL, 0x16aa2fda2bb3b0e8ULL, + 0xf86737458bb86399ULL, 0x8709c78dbb8deae0ULL, + 0x06bad6d5ebd3716bULL, 0x79d4261ddbe6f812ULL, + 0x3105d23613f9d516ULL, 0x4e6b22fe23cc5c6fULL, + 0xcfd833a67392c7e4ULL, 0xb0b6c36e43a74e9dULL, + 0x9a6c9329ac4bc9b5ULL, 0xe50263e19c7e40ccULL, + 0x64b172b9cc20db47ULL, 0x1bdf8271fc15523eULL, + 0x530e765a340a7f3aULL, 0x2c608692043ff643ULL, + 0xadd397ca54616dc8ULL, 0xd2bd67026454e4b1ULL, + 0x3c707f9dc45f37c0ULL, 0x431e8f55f46abeb9ULL, + 0xc2ad9e0da4342532ULL, 0xbdc36ec59401ac4bULL, + 0xf5129aee5c1e814fULL, 0x8a7c6a266c2b0836ULL, + 0x0bcf7b7e3c7593bdULL, 0x74a18bb60c401ac4ULL, + 0xe28c6c1224f5a634ULL, 0x9de29cda14c02f4dULL, + 0x1c518d82449eb4c6ULL, 0x633f7d4a74ab3dbfULL, + 0x2bee8961bcb410bbULL, 0x548079a98c8199c2ULL, + 0xd53368f1dcdf0249ULL, 0xaa5d9839ecea8b30ULL, + 0x449080a64ce15841ULL, 0x3bfe706e7cd4d138ULL, + 0xba4d61362c8a4ab3ULL, 0xc52391fe1cbfc3caULL, + 0x8df265d5d4a0eeceULL, 0xf29c951de49567b7ULL, + 0x732f8445b4cbfc3cULL, 0x0c41748d84fe7545ULL, + 0x6bad6d5ebd3716b7ULL, 0x14c39d968d029fceULL, + 0x95708ccedd5c0445ULL, 0xea1e7c06ed698d3cULL, + 0xa2cf882d2576a038ULL, 0xdda178e515432941ULL, + 0x5c1269bd451db2caULL, 0x237c997575283bb3ULL, + 0xcdb181ead523e8c2ULL, 0xb2df7122e51661bbULL, + 0x336c607ab548fa30ULL, 0x4c0290b2857d7349ULL, + 0x04d364994d625e4dULL, 0x7bbd94517d57d734ULL, + 0xfa0e85092d094cbfULL, 0x856075c11d3cc5c6ULL, + 0x134d926535897936ULL, 0x6c2362ad05bcf04fULL, + 0xed9073f555e26bc4ULL, 0x92fe833d65d7e2bdULL, + 0xda2f7716adc8cfb9ULL, 0xa54187de9dfd46c0ULL, + 0x24f29686cda3dd4bULL, 0x5b9c664efd965432ULL, + 0xb5517ed15d9d8743ULL, 0xca3f8e196da80e3aULL, + 0x4b8c9f413df695b1ULL, 0x34e26f890dc31cc8ULL, + 0x7c339ba2c5dc31ccULL, 0x035d6b6af5e9b8b5ULL, + 0x82ee7a32a5b7233eULL, 0xfd808afa9582aa47ULL, + 0x4d364994d625e4daULL, 0x3258b95ce6106da3ULL, + 0xb3eba804b64ef628ULL, 0xcc8558cc867b7f51ULL, + 0x8454ace74e645255ULL, 0xfb3a5c2f7e51db2cULL, + 0x7a894d772e0f40a7ULL, 0x05e7bdbf1e3ac9deULL, + 0xeb2aa520be311aafULL, 0x944455e88e0493d6ULL, + 0x15f744b0de5a085dULL, 0x6a99b478ee6f8124ULL, + 0x224840532670ac20ULL, 0x5d26b09b16452559ULL, + 0xdc95a1c3461bbed2ULL, 0xa3fb510b762e37abULL, + 0x35d6b6af5e9b8b5bULL, 0x4ab846676eae0222ULL, + 0xcb0b573f3ef099a9ULL, 0xb465a7f70ec510d0ULL, + 0xfcb453dcc6da3dd4ULL, 0x83daa314f6efb4adULL, + 0x0269b24ca6b12f26ULL, 0x7d0742849684a65fULL, + 0x93ca5a1b368f752eULL, 0xeca4aad306bafc57ULL, + 0x6d17bb8b56e467dcULL, 0x12794b4366d1eea5ULL, + 0x5aa8bf68aecec3a1ULL, 0x25c64fa09efb4ad8ULL, + 0xa4755ef8cea5d153ULL, 0xdb1bae30fe90582aULL, + 0xbcf7b7e3c7593bd8ULL, 0xc399472bf76cb2a1ULL, + 0x422a5673a732292aULL, 0x3d44a6bb9707a053ULL, + 0x759552905f188d57ULL, 0x0afba2586f2d042eULL, + 0x8b48b3003f739fa5ULL, 0xf42643c80f4616dcULL, + 0x1aeb5b57af4dc5adULL, 0x6585ab9f9f784cd4ULL, + 0xe436bac7cf26d75fULL, 0x9b584a0fff135e26ULL, + 0xd389be24370c7322ULL, 0xace74eec0739fa5bULL, + 0x2d545fb4576761d0ULL, 0x523aaf7c6752e8a9ULL, + 0xc41748d84fe75459ULL, 0xbb79b8107fd2dd20ULL, + 0x3acaa9482f8c46abULL, 0x45a459801fb9cfd2ULL, + 0x0d75adabd7a6e2d6ULL, 0x721b5d63e7936bafULL, + 0xf3a84c3bb7cdf024ULL, 0x8cc6bcf387f8795dULL, + 0x620ba46c27f3aa2cULL, 0x1d6554a417c62355ULL, + 0x9cd645fc4798b8deULL, 0xe3b8b53477ad31a7ULL, + 0xab69411fbfb21ca3ULL, 0xd407b1d78f8795daULL, + 0x55b4a08fdfd90e51ULL, 0x2ada5047efec8728ULL +}; + +static __inline__ uint64_t crc64_nvme_step(uint64_t c, + const uint8_t * p, + size_t len) +{ + size_t n; + + for (n = 0; n < len; n++) + c = crc64_nvme_tab[(c ^ p[n]) & 0xff] ^ (c >> 8); + + return c; +} + +void crc64_nvme_table(uint64_t * crc, + const void * buf, + size_t len) +{ + uint64_t c; + + c = crc64_nvme_step(*crc ^ UINT64_MAX, + (const uint8_t *) buf, len); + + *crc = c ^ UINT64_MAX; +} + +#ifdef HAVE_PCLMUL + +#include <smmintrin.h> +#include <wmmintrin.h> + +/* + * Fold-by-16 constants for reflected CRC-64/NVMe. Properties of the + * polynomial; identical between the PCLMUL and PMULL backends. + * k3 = bitrev64(x^(128+64) mod P) << 1 + * k4 = bitrev64(x^(128+0) mod P) << 1 + */ +static const uint64_t k3_clmul = 0xeadc41fd2ba3d420ULL; +static const uint64_t k4_clmul = 0x21e9761e252621acULL; + +__attribute__((target("pclmul,sse4.1"))) +static __m128i fold16(__m128i x, + __m128i k) +{ + __m128i lo; + __m128i hi; + + lo = _mm_clmulepi64_si128(x, k, 0x00); + hi = _mm_clmulepi64_si128(x, k, 0x11); + return _mm_xor_si128(lo, hi); +} + +/* + * Fold-by-16 over 16-byte chunks; the 128-bit folded state is then + * emitted as 16 little-endian bytes and run through the byte-table + * loop together with any tail (<=15 bytes). The 16-byte minimum on + * the bulk loop is why the short-input path uses the table directly. + */ +__attribute__((target("pclmul,sse4.1"))) +static void crc64_nvme_clmul(uint64_t * crc, + const void * buf, + size_t len) +{ + const uint8_t * p; + uint64_t seed; + uint64_t c; + size_t off; + __m128i x; + __m128i k; + uint8_t post[16]; + + p = (const uint8_t *) buf; + seed = *crc; + + if (len < 16) { + c = crc64_nvme_step(seed ^ UINT64_MAX, p, len); + *crc = c ^ UINT64_MAX; + return; + } + + x = _mm_loadu_si128((const __m128i *) p); + x = _mm_xor_si128(x, _mm_cvtsi64_si128((int64_t) + (seed ^ UINT64_MAX))); + + k = _mm_set_epi64x((int64_t) k4_clmul, (int64_t) k3_clmul); + + off = 16; + while (off + 16 <= len) { + __m128i d; + + d = _mm_loadu_si128((const __m128i *) (p + off)); + x = _mm_xor_si128(fold16(x, k), d); + off += 16; + } + + _mm_storeu_si128((__m128i *) post, x); + + c = crc64_nvme_step(0, post, 16); + c = crc64_nvme_step(c, p + off, len - off); + + *crc = c ^ UINT64_MAX; +} + +#endif /* HAVE_PCLMUL */ + +#ifdef HAVE_PMULL + +#include <arm_neon.h> + +/* Same fold-by-16 constants as the PCLMUL path (poly properties). */ +static const uint64_t k3_pmull = 0xeadc41fd2ba3d420ULL; +static const uint64_t k4_pmull = 0x21e9761e252621acULL; + +__attribute__((target("+crypto"))) +static uint64x2_t fold16_pmull(uint64x2_t x, + uint64x2_t k) +{ + poly64x2_t xp; + poly64x2_t kp; + uint64x2_t lo; + uint64x2_t hi; + + xp = vreinterpretq_p64_u64(x); + kp = vreinterpretq_p64_u64(k); + lo = vreinterpretq_u64_p128( + vmull_p64((poly64_t) vgetq_lane_u64(x, 0), + (poly64_t) vgetq_lane_u64(k, 0))); + hi = vreinterpretq_u64_p128(vmull_high_p64(xp, kp)); + return veorq_u64(lo, hi); +} + +__attribute__((target("+crypto"))) +static void crc64_nvme_pmull(uint64_t * crc, + const void * buf, + size_t len) +{ + const uint8_t * p; + uint64_t seed; + uint64_t c; + size_t off; + uint64x2_t x; + uint64x2_t k; + uint64_t seed_lane[2]; + uint64_t k_lanes[2]; + uint8_t post[16]; + + p = (const uint8_t *) buf; + seed = *crc; + + if (len < 16) { + c = crc64_nvme_step(seed ^ UINT64_MAX, p, len); + *crc = c ^ UINT64_MAX; + return; + } + + x = vld1q_u64((const uint64_t *) p); + seed_lane[0] = seed ^ UINT64_MAX; + seed_lane[1] = 0; + x = veorq_u64(x, vld1q_u64(seed_lane)); + + k_lanes[0] = k3_pmull; + k_lanes[1] = k4_pmull; + k = vld1q_u64(k_lanes); + + off = 16; + while (off + 16 <= len) { + uint64x2_t d; + + d = vld1q_u64((const uint64_t *) (p + off)); + x = veorq_u64(fold16_pmull(x, k), d); + off += 16; + } + + vst1q_u8(post, vreinterpretq_u8_u64(x)); + + c = crc64_nvme_step(0, post, 16); + c = crc64_nvme_step(c, p + off, len - off); + + *crc = c ^ UINT64_MAX; +} +#endif /* HAVE_PMULL */ + +void crc64_nvme(uint64_t * crc, + const void * buf, + size_t len) +{ +#ifdef HAVE_PCLMUL + crc64_nvme_clmul(crc, buf, len); +#elif defined(HAVE_PMULL) + crc64_nvme_pmull(crc, buf, len); +#else + crc64_nvme_table(crc, buf, len); +#endif +} diff --git a/src/lib/crc/crc8.c b/src/lib/crc/crc8.c new file mode 100644 index 00000000..20976b29 --- /dev/null +++ b/src/lib/crc/crc8.c @@ -0,0 +1,62 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * 8-bit Cyclic Redundancy Check (AUTOSAR variant) + * + * 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/. + */ + +/* + * CRC-8/AUTOSAR (reveng catalog): + * poly = 0x2f + * init = 0xff + * refin = false + * refout = false + * xorout = 0xff + * check = crc8_autosar("123456789") == 0xdf + */ + +#include "config.h" + +#include <ouroboros/crc8.h> + + + /* Bit-by-bit MSB-first CRC. */ +void crc8_autosar(uint8_t * crc, + const void * buf, + size_t len) +{ + const uint8_t * p; + uint8_t c; + size_t n; + int i; + + p = (const uint8_t *) buf; + c = *crc ^ 0xff; + + for (n = 0; n < len; n++) { + c ^= p[n]; + for (i = 0; i < 8; i++) { + if (c & 0x80) + c = (uint8_t) ((c << 1) ^ 0x2f); + else + c = (uint8_t) (c << 1); + } + } + + *crc = c ^ 0xff; +} diff --git a/src/lib/crc/tests/CMakeLists.txt b/src/lib/crc/tests/CMakeLists.txt new file mode 100644 index 00000000..11daca5a --- /dev/null +++ b/src/lib/crc/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) +get_filename_component(PARENT_DIR ${PARENT_PATH} NAME) + +compute_test_prefix() + +create_test_sourcelist(${PARENT_DIR}_tests test_suite.c + # Add new tests here + crc8_test.c + crc16_test.c + crc32_test.c + crc64_test.c + ) + +add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests}) + +disable_test_logging_for_target(${PARENT_DIR}_test) +target_link_libraries(${PARENT_DIR}_test ouroboros-common) + +add_dependencies(build_tests ${PARENT_DIR}_test) + +ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests}) diff --git a/src/lib/crc/tests/crc16_test.c b/src/lib/crc/tests/crc16_test.c new file mode 100644 index 00000000..03a5b504 --- /dev/null +++ b/src/lib/crc/tests/crc16_test.c @@ -0,0 +1,67 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * Test of the CRC-16/CCITT-FALSE function + * + * 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/crc16.h> + +#include <test/test.h> + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +/* reveng-catalog smoke vectors. */ +static int test_crc16_ccitt_false_basic(void) +{ + uint16_t crc; + + TEST_START(); + + crc = 0; + crc16_ccitt_false(&crc, "", 0); + if (crc != 0xffff) + goto fail; + + crc = 0; + crc16_ccitt_false(&crc, "123456789", 9); + if (crc != 0x29b1) + goto fail; + + TEST_SUCCESS(); + return TEST_RC_SUCCESS; + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +} + +int crc16_test(int argc, + char ** argv) +{ + int ret = 0; + + (void) argc; + (void) argv; + + ret |= test_crc16_ccitt_false_basic(); + return ret; +} diff --git a/src/lib/tests/crc32_test.c b/src/lib/crc/tests/crc32_test.c index 5a1ddd87..5a1ddd87 100644 --- a/src/lib/tests/crc32_test.c +++ b/src/lib/crc/tests/crc32_test.c diff --git a/src/lib/crc/tests/crc64_test.c b/src/lib/crc/tests/crc64_test.c new file mode 100644 index 00000000..cf3f5ca3 --- /dev/null +++ b/src/lib/crc/tests/crc64_test.c @@ -0,0 +1,126 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * Test of the CRC-64/NVMe function + * + * 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/crc64.h> +#include <ouroboros/random.h> + +#include <test/test.h> + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +/* Reference impl, internal to libouroboros-common. */ +extern void crc64_nvme_table(uint64_t * crc, + const void * buf, + size_t len); + +/* reveng-catalog smoke vectors plus a 16-byte fold-boundary check. */ +static int test_crc64_nvme_basic(void) +{ + uint64_t crc; + + TEST_START(); + + crc = 0; + crc64_nvme(&crc, "", 0); + if (crc != 0x0000000000000000ULL) + goto fail; + + crc = 0; + crc64_nvme(&crc, "123456789", 9); + if (crc != 0xae8b14860a799888ULL) + goto fail; + + crc = 0; + crc64_nvme(&crc, "0123456789abcdef", 16); + if (crc != 0x091485ca7018730eULL) + goto fail; + + TEST_SUCCESS(); + return TEST_RC_SUCCESS; + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +} + +#if defined(HAVE_PCLMUL) || defined(HAVE_PMULL) +/* Cross-check the accelerated dispatcher path against the byte-table. */ +static int test_crc64_nvme_random(void) +{ + static const size_t lens[] = { + 0, 1, 7, 8, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, + 129, 255, 256, 257, 1023, 1024, 1025, 4096 + }; + uint8_t buf[4096]; + size_t i; + uint64_t ref; + uint64_t got; + + TEST_START(); + + if (random_buffer(buf, sizeof(buf)) < 0) { + printf("Failed to generate random data.\n"); + goto fail; + } + + for (i = 0; i < sizeof(lens) / sizeof(lens[0]); i++) { + ref = 0; + crc64_nvme_table(&ref, buf, lens[i]); + + got = 0; + crc64_nvme(&got, buf, lens[i]); + + if (ref == got) + continue; + + printf("Mismatch at len=%zu: table=0x%016lx disp=0x%016lx\n", + lens[i], + (unsigned long) ref, + (unsigned long) got); + goto fail; + } + + TEST_SUCCESS(); + return TEST_RC_SUCCESS; + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +#endif +} + +int crc64_test(int argc, + char ** argv) +{ + int ret = 0; + + (void) argc; + (void) argv; + + ret |= test_crc64_nvme_basic(); +#if defined(HAVE_PCLMUL) || defined(HAVE_PMULL) + ret |= test_crc64_nvme_random(); +#endif + return ret; +} diff --git a/src/lib/crc/tests/crc8_test.c b/src/lib/crc/tests/crc8_test.c new file mode 100644 index 00000000..f7bb33b8 --- /dev/null +++ b/src/lib/crc/tests/crc8_test.c @@ -0,0 +1,67 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2026 + * + * Test of the CRC-8/AUTOSAR function + * + * 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/crc8.h> + +#include <test/test.h> + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +/* reveng-catalog smoke vectors. */ +static int test_crc8_autosar_basic(void) +{ + uint8_t crc; + + TEST_START(); + + crc = 0; + crc8_autosar(&crc, "", 0); + if (crc != 0x00) + goto fail; + + crc = 0; + crc8_autosar(&crc, "123456789", 9); + if (crc != 0xdf) + goto fail; + + TEST_SUCCESS(); + return TEST_RC_SUCCESS; + fail: + TEST_FAIL(); + return TEST_RC_FAIL; +} + +int crc8_test(int argc, + char ** argv) +{ + int ret = 0; + + (void) argc; + (void) argv; + + ret |= test_crc8_autosar_basic(); + return ret; +} diff --git a/src/lib/crypt.c b/src/lib/crypt.c index cd3421dd..71197f6e 100644 --- a/src/lib/crypt.c +++ b/src/lib/crypt.c @@ -1094,6 +1094,13 @@ void crypt_secure_malloc_fini(void) #endif } +void crypt_cleanup(void) +{ +#ifdef HAVE_OPENSSL + openssl_cleanup(); +#endif +} + void * crypt_secure_malloc(size_t size) { #ifdef HAVE_OPENSSL diff --git a/src/lib/crypt/openssl.c b/src/lib/crypt/openssl.c index 573bc0b3..5916e3cb 100644 --- a/src/lib/crypt/openssl.c +++ b/src/lib/crypt/openssl.c @@ -629,7 +629,7 @@ ssize_t openssl_pkp_create(const char * algo, return (ssize_t) raw.len; } else { /* DER encode standard algorithms */ - pos = pk; /* i2d_PUBKEY increments the pointer, don't use pk! */ + pos = pk; /* i2d_PUBKEY increments the ptr, don't use pk! */ len = i2d_PUBKEY(*pkp, &pos); if (len < 0) goto fail_pubkey; @@ -666,7 +666,7 @@ static ssize_t __openssl_kem_encap(EVP_PKEY * pub, /* Get required lengths */ ret = EVP_PKEY_encapsulate(ctx, NULL, &ct_len, NULL, &secret_len); - if (ret != 1 || ct_len > MSGBUFSZ) + if (ret != 1 || ct_len > CRYPT_KEY_BUFSZ) goto fail_encap; /* Allocate buffer for secret */ @@ -1283,24 +1283,14 @@ int openssl_load_privkey_file(const char * path, { FILE * fp; EVP_PKEY * pkey; - unsigned long err; - char errbuf[256]; fp = fopen(path, "r"); - if (fp == NULL) { - fprintf(stderr, "Failed to open %s\n", path); + if (fp == NULL) goto fail_file; - } pkey = PEM_read_PrivateKey(fp, NULL, NULL, ""); - if (pkey == NULL) { - err = ERR_get_error(); - ERR_error_string_n(err, errbuf, sizeof(errbuf)); - fprintf(stderr, - "OpenSSL error loading privkey from %s: %s\n", - path, errbuf); + if (pkey == NULL) goto fail_key; - } fclose(fp); @@ -1442,7 +1432,7 @@ int openssl_load_pubkey_raw_file(const char * path, buffer_t * buf) { FILE * fp; - uint8_t tmp_buf[MSGBUFSZ]; + uint8_t tmp_buf[CRYPT_KEY_BUFSZ]; size_t bytes_read; const char * algo; @@ -1453,7 +1443,7 @@ int openssl_load_pubkey_raw_file(const char * path, if (fp == NULL) goto fail_file; - bytes_read = fread(tmp_buf, 1, MSGBUFSZ, fp); + bytes_read = fread(tmp_buf, 1, CRYPT_KEY_BUFSZ, fp); if (bytes_read == 0) goto fail_read; @@ -1658,25 +1648,33 @@ int openssl_crt_str(const void * crt, int openssl_crt_der(const void * crt, buffer_t * buf) { - int len; + uint8_t * p; + int len; assert(crt != NULL); assert(buf != NULL); - len = i2d_X509((X509 *) crt, &buf->data); + /* Get the size by encoding to NULL */ + len = i2d_X509((X509 *) crt, NULL); if (len < 0) - goto fail_der; + goto fail_len; + buf->data = malloc((size_t) len); + if (buf->data == NULL) + goto fail_malloc; + + p = buf->data; /* i2d_X509 increments p */ + i2d_X509((X509 *) crt, &p); buf->len = (size_t) len; return 0; - fail_der: + fail_malloc: + fail_len: clrbuf(*buf); return -1; } - void * openssl_auth_create_store(void) { return X509_STORE_new(); @@ -1878,3 +1876,7 @@ void openssl_secure_clear(void * ptr, { OPENSSL_cleanse(ptr, size); } +void openssl_cleanup(void) +{ + OPENSSL_cleanup(); +} diff --git a/src/lib/crypt/openssl.h b/src/lib/crypt/openssl.h index b95d1b0b..af285232 100644 --- a/src/lib/crypt/openssl.h +++ b/src/lib/crypt/openssl.h @@ -169,4 +169,6 @@ void openssl_secure_free(void * ptr, void openssl_secure_clear(void * ptr, size_t size); +void openssl_cleanup(void); + #endif /* OUROBOROS_LIB_CRYPT_OPENSSL_H */ diff --git a/src/lib/dev.c b/src/lib/dev.c index 9cfc24ee..ff63b818 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -1284,7 +1284,7 @@ static int flow_tx_spb(struct flow * flow, pthread_rwlock_unlock(&proc.lock); - idx = ssm_pk_buff_get_idx(spb); + idx = ssm_pk_buff_get_off(spb); pthread_rwlock_rdlock(&proc.lock); @@ -2036,7 +2036,7 @@ int ipcp_flow_write(int fd, } static int pool_copy_spb(struct ssm_pool * src_pool, - ssize_t src_idx, + ssize_t src_off, struct ssm_pool * dst_pool, struct ssm_pk_buff ** dst_spb) { @@ -2044,16 +2044,14 @@ static int pool_copy_spb(struct ssm_pool * src_pool, uint8_t * ptr; size_t len; - src = ssm_pool_get(src_pool, src_idx); + src = ssm_pool_get(src_pool, src_off); len = ssm_pk_buff_len(src); - if (ssm_pool_alloc(dst_pool, len, &ptr, dst_spb) < 0) { - ssm_pool_remove(src_pool, src_idx); + if (ssm_pool_alloc(dst_pool, len, &ptr, dst_spb) < 0) return -ENOMEM; - } memcpy(ptr, ssm_pk_buff_head(src), len); - ssm_pool_remove(src_pool, src_idx); + ssm_pool_remove(src_pool, src_off); return 0; } @@ -2063,7 +2061,7 @@ int np1_flow_read(int fd, struct ssm_pool * pool) { struct flow * flow; - ssize_t idx = -1; + ssize_t off = -1; assert(fd >= 0 && fd < SYS_MAX_FLOWS); assert(spb); @@ -2074,20 +2072,22 @@ int np1_flow_read(int fd, pthread_rwlock_rdlock(&proc.lock); - idx = ssm_rbuff_read(flow->rx_rb); - if (idx < 0) { + off = ssm_rbuff_read(flow->rx_rb); + if (off < 0) { pthread_rwlock_unlock(&proc.lock); - return idx; + return off; } pthread_rwlock_unlock(&proc.lock); if (pool == NULL) { - *spb = ssm_pool_get(proc.pool, idx); + *spb = ssm_pool_get(proc.pool, off); } else { /* Cross-pool copy: PUP -> GSPP */ - if (pool_copy_spb(pool, idx, proc.pool, spb) < 0) + if (pool_copy_spb(pool, off, proc.pool, spb) < 0) { + ssm_pool_remove(pool, off); return -ENOMEM; + } } return 0; @@ -2100,7 +2100,8 @@ int np1_flow_write(int fd, struct flow * flow; struct ssm_pk_buff * dst; int ret; - ssize_t idx; + ssize_t src_off; + ssize_t dst_off; assert(fd >= 0 && fd < SYS_MAX_FLOWS); assert(spb); @@ -2121,27 +2122,28 @@ int np1_flow_write(int fd, pthread_rwlock_unlock(&proc.lock); - idx = ssm_pk_buff_get_idx(spb); + src_off = ssm_pk_buff_get_off(spb); if (pool == NULL) { - ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL); + ret = ssm_rbuff_write_b(flow->tx_rb, src_off, NULL); if (ret < 0) - ssm_pool_remove(proc.pool, idx); - else - ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT); + return ret; + ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT); } else { /* Cross-pool copy: GSPP -> PUP */ - if (pool_copy_spb(proc.pool, idx, pool, &dst) < 0) + if (pool_copy_spb(proc.pool, src_off, pool, &dst) < 0) return -ENOMEM; - idx = ssm_pk_buff_get_idx(dst); - ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL); - if (ret < 0) - ssm_pool_remove(pool, idx); - else - ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT); + dst_off = ssm_pk_buff_get_off(dst); + ret = ssm_rbuff_write_b(flow->tx_rb, dst_off, NULL); + if (ret < 0) { + ssm_pool_remove(pool, dst_off); + return ret; + } + ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT); + ssm_pool_remove(proc.pool, src_off); } - return ret; + return 0; } int ipcp_spb_reserve(struct ssm_pk_buff ** spb, @@ -2152,7 +2154,7 @@ int ipcp_spb_reserve(struct ssm_pk_buff ** spb, void ipcp_spb_release(struct ssm_pk_buff * spb) { - ssm_pool_remove(proc.pool, ssm_pk_buff_get_idx(spb)); + ssm_pool_remove(proc.pool, ssm_pk_buff_get_off(spb)); } int ipcp_flow_fini(int fd) @@ -2227,7 +2229,8 @@ int local_flow_transfer(int src_fd, struct ssm_pk_buff * dst_spb; struct ssm_pool * sp; struct ssm_pool * dp; - ssize_t idx; + ssize_t src_off; + ssize_t dst_off; int ret; assert(src_fd >= 0); @@ -2241,15 +2244,15 @@ int local_flow_transfer(int src_fd, pthread_rwlock_rdlock(&proc.lock); - idx = ssm_rbuff_read(src_flow->rx_rb); - if (idx < 0) { + src_off = ssm_rbuff_read(src_flow->rx_rb); + if (src_off < 0) { pthread_rwlock_unlock(&proc.lock); - return idx; + return src_off; } if (dst_flow->info.id < 0) { pthread_rwlock_unlock(&proc.lock); - ssm_pool_remove(sp, idx); + ssm_pool_remove(sp, src_off); return -ENOTALLOC; } @@ -2257,21 +2260,23 @@ int local_flow_transfer(int src_fd, if (sp == dp) { /* Same pool: zero-copy */ - ret = ssm_rbuff_write_b(dst_flow->tx_rb, idx, NULL); + ret = ssm_rbuff_write_b(dst_flow->tx_rb, src_off, NULL); if (ret < 0) - ssm_pool_remove(sp, idx); + ssm_pool_remove(sp, src_off); else ssm_flow_set_notify(dst_flow->set, dst_flow->info.id, FLOW_PKT); } else { /* Different pools: single copy */ - if (pool_copy_spb(sp, idx, dp, &dst_spb) < 0) + if (pool_copy_spb(sp, src_off, dp, &dst_spb) < 0) { + ssm_pool_remove(sp, src_off); return -ENOMEM; + } - idx = ssm_pk_buff_get_idx(dst_spb); - ret = ssm_rbuff_write_b(dst_flow->tx_rb, idx, NULL); + dst_off = ssm_pk_buff_get_off(dst_spb); + ret = ssm_rbuff_write_b(dst_flow->tx_rb, dst_off, NULL); if (ret < 0) - ssm_pool_remove(dp, idx); + ssm_pool_remove(dp, dst_off); else ssm_flow_set_notify(dst_flow->set, dst_flow->info.id, FLOW_PKT); diff --git a/src/lib/frct.c b/src/lib/frct.c index fad2cf69..4d14362e 100644 --- a/src/lib/frct.c +++ b/src/lib/frct.c @@ -815,7 +815,7 @@ static void __frcti_rcv(struct frcti * frcti, pci = (struct frct_pci *) ssm_pk_buff_head_release(spb, FRCT_PCILEN); - idx = ssm_pk_buff_get_idx(spb); + idx = ssm_pk_buff_get_off(spb); seqno = ntoh32(pci->seqno); pos = seqno & (RQ_SIZE - 1); diff --git a/src/lib/hash.c b/src/lib/hash.c index 7adee968..7ffa5bc1 100644 --- a/src/lib/hash.c +++ b/src/lib/hash.c @@ -39,6 +39,9 @@ #include <ouroboros/md5.h> #include <ouroboros/sha3.h> #endif +#include <ouroboros/crc8.h> +#include <ouroboros/crc16.h> +#include <ouroboros/crc64.h> #include <string.h> #include <assert.h> #include <stdbool.h> @@ -69,6 +72,12 @@ int hash_len_tbl [] = { uint16_t hash_len(enum hash_algo algo) { + if (algo == HASH_CRC8) + return CRC8_HASH_LEN; + if (algo == HASH_CRC16) + return CRC16_HASH_LEN; + if (algo == HASH_CRC64) + return CRC64_HASH_LEN; #ifdef HAVE_LIBGCRYPT return (uint16_t) gcry_md_get_algo_dlen(gcry_algo_tbl[algo]); #else @@ -81,6 +90,27 @@ void mem_hash(enum hash_algo algo, const uint8_t * buf, size_t len) { + if (algo == HASH_CRC8) { + uint8_t crc = 0; + + crc8_autosar(&crc, buf, len); + *(uint8_t *) dst = crc; + return; + } + if (algo == HASH_CRC16) { + uint16_t crc = 0; + + crc16_ccitt_false(&crc, buf, len); + *(uint16_t *) dst = htobe16(crc); + return; + } + if (algo == HASH_CRC64) { + uint64_t crc = 0; + + crc64_nvme(&crc, buf, len); + *(uint64_t *) dst = htobe64(crc); + return; + } #ifdef HAVE_LIBGCRYPT gcry_md_hash_buffer(gcry_algo_tbl[algo], dst, buf, len); #else diff --git a/src/lib/irm.c b/src/lib/irm.c index 594014f7..c62701aa 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -614,7 +614,7 @@ ssize_t irm_list_names(struct name_info ** names) return 0; } - *names = malloc(nr * sizeof(**names)); + *names = calloc(nr, sizeof(**names)); if (*names == NULL) { irm_msg__free_unpacked(recv_msg, NULL); return -ENOMEM; diff --git a/src/lib/protobuf.c b/src/lib/protobuf.c index d419a9f1..28b3aab2 100644 --- a/src/lib/protobuf.c +++ b/src/lib/protobuf.c @@ -137,7 +137,7 @@ name_info_msg_t * name_info_s_to_msg(const struct name_info * info) goto fail_msg; msg->ckey = strdup(info->c.key); - if (msg->skey == NULL) + if (msg->ckey == NULL) goto fail_msg; msg->ccrt = strdup(info->c.crt); @@ -161,6 +161,8 @@ struct name_info name_info_msg_to_s(const name_info_msg_t * msg) assert(msg != NULL); assert(strlen(msg->name) <= NAME_SIZE); + memset(&s, 0, sizeof(s)); + strcpy(s.name, msg->name); strcpy(s.s.key, msg->skey); strcpy(s.s.crt, msg->scrt); diff --git a/src/lib/ssm/pool.c b/src/lib/ssm/pool.c index 5c98b515..6829b217 100644 --- a/src/lib/ssm/pool.c +++ b/src/lib/ssm/pool.c @@ -107,6 +107,8 @@ static const struct ssm_size_class_cfg ssm_pup_cfg[SSM_POOL_MAX_CLASSES] = { : SSM_PUP_FILE_SIZE) #define GET_POOL_CFG(uid) (IS_GSPP(uid) ? ssm_gspp_cfg : ssm_pup_cfg) +#define NEEDS_CHOWN(uid, gid) ((uid) != geteuid() || (gid) != getegid()) + struct ssm_pool { uint8_t * shm_base; /* start of blocks */ struct _ssm_pool_hdr * hdr; /* shared memory header */ @@ -548,7 +550,7 @@ static struct ssm_pool * __pool_create(const char * name, if (flags & O_CREAT) { if (ftruncate(fd, (off_t) file_size) < 0) goto fail_truncate; - if (uid != geteuid() && fchown(fd, uid, gid) < 0) + if (NEEDS_CHOWN(uid, gid) && fchown(fd, uid, gid) < 0) goto fail_truncate; } @@ -744,7 +746,7 @@ ssize_t ssm_pool_read(uint8_t ** dst, } struct ssm_pk_buff * ssm_pool_get(struct ssm_pool * pool, - size_t off) + size_t off) { struct ssm_pk_buff * blk; @@ -823,7 +825,7 @@ int ssm_pool_remove(struct ssm_pool * pool, return 0; } -size_t ssm_pk_buff_get_idx(struct ssm_pk_buff * spb) +size_t ssm_pk_buff_get_off(struct ssm_pk_buff * spb) { assert(spb != NULL); diff --git a/src/lib/ssm/rbuff.c b/src/lib/ssm/rbuff.c index e4558c31..77e23010 100644 --- a/src/lib/ssm/rbuff.c +++ b/src/lib/ssm/rbuff.c @@ -232,7 +232,7 @@ void ssm_rbuff_close(struct ssm_rbuff * rb) } int ssm_rbuff_write(struct ssm_rbuff * rb, - size_t idx) + size_t off) { size_t acl; bool was_empty; @@ -261,7 +261,7 @@ int ssm_rbuff_write(struct ssm_rbuff * rb, was_empty = IS_EMPTY(rb); - HEAD(rb) = (ssize_t) idx; + HEAD(rb) = (ssize_t) off; ADVANCE_HEAD(rb); if (was_empty) @@ -278,7 +278,7 @@ int ssm_rbuff_write(struct ssm_rbuff * rb, } int ssm_rbuff_write_b(struct ssm_rbuff * rb, - size_t idx, + size_t off, const struct timespec * abstime) { size_t acl; @@ -316,7 +316,7 @@ int ssm_rbuff_write_b(struct ssm_rbuff * rb, if (ret != -ETIMEDOUT && ret != -EFLOWDOWN) { was_empty = IS_EMPTY(rb); - HEAD(rb) = (ssize_t) idx; + HEAD(rb) = (ssize_t) off; ADVANCE_HEAD(rb); if (was_empty) pthread_cond_broadcast(rb->add); diff --git a/src/lib/ssm/tests/pool_sharding_test.c b/src/lib/ssm/tests/pool_sharding_test.c index c53105e3..f2810c53 100644 --- a/src/lib/ssm/tests/pool_sharding_test.c +++ b/src/lib/ssm/tests/pool_sharding_test.c @@ -261,7 +261,7 @@ static int test_fallback_stealing(void) /* Free them all - they go to local_shard */ for (i = 0; i < total_blocks / 2; i++) { - size_t off = ssm_pk_buff_get_idx(spbs[i]); + size_t off = ssm_pk_buff_get_off(spbs[i]); if (ssm_pool_remove(pool, off) != 0) { printf("Remove %zu failed.\n", i); free(spbs); @@ -299,7 +299,7 @@ static int test_fallback_stealing(void) /* Now all allocated blocks are in use again */ /* Cleanup - free all allocated blocks */ for (i = 0; i < total_blocks / 2; i++) { - size_t off = ssm_pk_buff_get_idx(spbs[i]); + size_t off = ssm_pk_buff_get_off(spbs[i]); ssm_pool_remove(pool, off); } diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt index 5a2f2c52..337d85a6 100644 --- a/src/lib/tests/CMakeLists.txt +++ b/src/lib/tests/CMakeLists.txt @@ -10,7 +10,6 @@ create_test_sourcelist(${PARENT_DIR}_tests test_suite.c auth_test_slh_dsa.c bitmap_test.c btree_test.c - crc32_test.c crypt_test.c hash_test.c kex_test.c diff --git a/src/lib/tests/auth_test.c b/src/lib/tests/auth_test.c index 1a5a87af..0f3ef715 100644 --- a/src/lib/tests/auth_test.c +++ b/src/lib/tests/auth_test.c @@ -347,6 +347,59 @@ static int test_verify_crt(void) return TEST_RC_FAIL; } +static int test_verify_crt_missing_root_ca(void) +{ + struct auth_ctx * auth; + void * _signed_server_crt; + void * _im_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(signed_server_crt_ec, &_signed_server_crt) < 0) { + printf("Failed to load signed crt from string.\n"); + goto fail_load_signed; + } + + if (crypt_load_crt_str(im_ca_crt_ec, &_im_ca_crt) < 0) { + printf("Failed to load intermediate crt from string.\n"); + goto fail_load_im_ca; + } + + /* Add only the intermediate CA - root CA is missing */ + if (auth_add_crt_to_store(auth, _im_ca_crt) < 0) { + printf("Failed to add intermediate ca crt to auth store.\n"); + goto fail_add; + } + + if (auth_verify_crt(auth, _signed_server_crt) == 0) { + printf("Verification should fail without root CA.\n"); + goto fail_add; + } + + crypt_free_crt(_im_ca_crt); + crypt_free_crt(_signed_server_crt); + auth_destroy_ctx(auth); + + TEST_SUCCESS(); + + return TEST_RC_SUCCESS; + fail_add: + crypt_free_crt(_im_ca_crt); + fail_load_im_ca: + crypt_free_crt(_signed_server_crt); + fail_load_signed: + auth_destroy_ctx(auth); + fail_create_ctx: + TEST_FAIL(); + return TEST_RC_FAIL; +} + int test_auth_sign(void) { uint8_t buf[TEST_MSG_SIZE]; @@ -526,6 +579,7 @@ int auth_test(int argc, ret |= test_crypt_check_pubkey_crt(); ret |= test_store_add(); ret |= test_verify_crt(); + ret |= test_verify_crt_missing_root_ca(); ret |= test_auth_sign(); ret |= test_auth_bad_signature(); ret |= test_crt_str(); @@ -538,6 +592,7 @@ int auth_test(int argc, (void) test_crypt_check_pubkey_crt; (void) test_store_add; (void) test_verify_crt; + (void) test_verify_crt_missing_root_ca; (void) test_auth_sign; (void) test_auth_bad_signature; (void) test_crt_str; diff --git a/src/lib/tests/hash_test.c b/src/lib/tests/hash_test.c index e43847e1..451d3c25 100644 --- a/src/lib/tests/hash_test.c +++ b/src/lib/tests/hash_test.c @@ -39,6 +39,74 @@ struct vec_entry { char * out; }; +static int test_crc8(void) +{ + int ret = 0; + + struct vec_entry vec [] = { + { "", "00" }, + { "123456789", "df" }, + { NULL, NULL } + }; + + struct vec_entry * cur = vec; + + TEST_START(); + + while (cur->in != NULL) { + uint8_t crc; + char res[3]; + + str_hash(HASH_CRC8, &crc, cur->in); + + sprintf(res, "%02x", crc); + if (strcmp(res, cur->out) != 0) { + printf("Hash failed %s != %s.\n", res, cur->out); + ret |= -1; + } + + ++cur; + } + + TEST_END(ret); + + return ret; +} + +static int test_crc16(void) +{ + int ret = 0; + + struct vec_entry vec [] = { + { "", "ffff" }, + { "123456789", "29b1" }, + { NULL, NULL } + }; + + struct vec_entry * cur = vec; + + TEST_START(); + + while (cur->in != NULL) { + uint8_t crc[2]; + char res[5]; + + str_hash(HASH_CRC16, crc, cur->in); + + sprintf(res, "%02x%02x", crc[0], crc[1]); + if (strcmp(res, cur->out) != 0) { + printf("Hash failed %s != %s.\n", res, cur->out); + ret |= -1; + } + + ++cur; + } + + TEST_END(ret); + + return ret; +} + static int test_crc32(void) { int ret = 0; @@ -74,6 +142,42 @@ static int test_crc32(void) return ret; } +static int test_crc64(void) +{ + int ret = 0; + + struct vec_entry vec [] = { + { "", "0000000000000000" }, + { "123456789", "ae8b14860a799888" }, + { "0123456789abcdef", + "091485ca7018730e" }, + { NULL, NULL } + }; + + struct vec_entry * cur = vec; + + TEST_START(); + + while (cur->in != NULL) { + uint8_t crc[8]; + char res[17]; + + str_hash(HASH_CRC64, crc, cur->in); + + sprintf(res, HASH_FMT64, HASH_VAL64(crc)); + if (strcmp(res, cur->out) != 0) { + printf("Hash failed %s != %s.\n", res, cur->out); + ret |= -1; + } + + ++cur; + } + + TEST_END(ret); + + return ret; +} + static int test_md5(void) { int ret = 0; @@ -192,8 +296,14 @@ int hash_test(int argc, (void) argc; (void) argv; + ret |= test_crc8(); + + ret |= test_crc16(); + ret |= test_crc32(); + ret |= test_crc64(); + ret |= test_md5(); ret |= test_sha3(); diff --git a/src/lib/tests/kex_test.c b/src/lib/tests/kex_test.c index ced760fe..6a4f802e 100644 --- a/src/lib/tests/kex_test.c +++ b/src/lib/tests/kex_test.c @@ -106,7 +106,7 @@ static int test_kex_dh_pkp_create_destroy(void) { struct sec_config kex; void * pkp; - uint8_t buf[MSGBUFSZ]; + uint8_t buf[CRYPT_KEY_BUFSZ]; TEST_START(); @@ -134,7 +134,7 @@ static int test_kex_get_algo_from_pk(const char * algo) void * pkp; buffer_t pk; ssize_t len; - uint8_t buf[MSGBUFSZ]; + uint8_t buf[CRYPT_KEY_BUFSZ]; char extracted_algo[256]; TEST_START("(%s)", algo); @@ -204,8 +204,8 @@ static int test_kex_dhe_derive(const char * algo) buffer_t pk1; buffer_t pk2; ssize_t len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; uint8_t s1[SYMMKEYSZ]; uint8_t s2[SYMMKEYSZ]; @@ -317,7 +317,7 @@ static int test_kex_dhe_corrupted_pubkey(const char * algo) void * pkp; buffer_t pk; ssize_t len; - uint8_t buf[MSGBUFSZ]; + uint8_t buf[CRYPT_KEY_BUFSZ]; uint8_t s[SYMMKEYSZ]; TEST_START("(%s)", algo); @@ -363,8 +363,8 @@ static int test_kex_dhe_wrong_algo(void) void * pkp2; buffer_t pk2; ssize_t len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; uint8_t s[SYMMKEYSZ]; const char * algo1 = "X25519"; const char * algo2 = "X448"; diff --git a/src/lib/tests/kex_test_ml_kem.c b/src/lib/tests/kex_test_ml_kem.c index 3bb9ae7c..7761c3dc 100644 --- a/src/lib/tests/kex_test_ml_kem.c +++ b/src/lib/tests/kex_test_ml_kem.c @@ -197,8 +197,8 @@ static int test_kex_kem(const char * algo) buffer_t ct; ssize_t len; ssize_t ct_len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; uint8_t s1[SYMMKEYSZ]; uint8_t s2[SYMMKEYSZ]; int kdf; @@ -262,8 +262,8 @@ static int test_kex_kem_corrupted_ciphertext(const char * algo) buffer_t ct; ssize_t len; ssize_t ct_len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; uint8_t s1[SYMMKEYSZ]; uint8_t s2[SYMMKEYSZ]; int kdf; @@ -334,9 +334,9 @@ static int test_kex_kem_wrong_keypair(const char * algo) buffer_t ct; ssize_t len; ssize_t ct_len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; - uint8_t buf3[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; + uint8_t buf3[CRYPT_KEY_BUFSZ]; uint8_t s1[SYMMKEYSZ]; uint8_t s2[SYMMKEYSZ]; @@ -402,8 +402,8 @@ static int test_kex_kem_truncated_ciphertext(const char * algo) buffer_t ct; ssize_t len; ssize_t ct_len; - uint8_t buf1[MSGBUFSZ]; - uint8_t buf2[MSGBUFSZ]; + uint8_t buf1[CRYPT_KEY_BUFSZ]; + uint8_t buf2[CRYPT_KEY_BUFSZ]; uint8_t s1[SYMMKEYSZ]; uint8_t s2[SYMMKEYSZ]; diff --git a/src/lib/timerwheel.c b/src/lib/timerwheel.c index 2c796c96..3cfb77e8 100644 --- a/src/lib/timerwheel.c +++ b/src/lib/timerwheel.c @@ -239,7 +239,7 @@ static void timerwheel_move(void) r->pkt = pci; ssm_pk_buff_wait_ack(spb); #endif - idx = ssm_pk_buff_get_idx(spb); + idx = ssm_pk_buff_get_off(spb); /* Retransmit the copy. */ pci->ackno = hton32(rcv_lwe); |
