From 16eec5cb96dbbe530692b6ffa73bebe5bbf95e6c Mon Sep 17 00:00:00 2001 From: edvard Date: Thu, 20 Nov 2025 14:25:32 +0100 Subject: [PATCH 1/7] initial sodium impl, using meson extern prj mod --- .gitmodules | 3 +++ meson.build | 66 ++++++++++++++++++++++++++++++++++++++++++--- meson_options.txt | 6 +++++ src/crypto/crypto.c | 18 +++++-------- src/crypto/sodium | 1 + 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 meson_options.txt create mode 160000 src/crypto/sodium diff --git a/.gitmodules b/.gitmodules index f631480..e29a298 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "subprojects/csp"] path = subprojects/csp url = https://github.com/spaceinventor/libcsp +[submodule "src/crypto/sodium"] + path = src/crypto/sodium + url = https://github.com/jedisct1/libsodium.git diff --git a/meson.build b/meson.build index 155d98f..5978a32 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,8 @@ project('cblk', ['c', 'cpp']) +cblk_deps = [] +cblk_args = [] + if not meson.is_subproject() csp_dep = dependency('csp', fallback : ['csp', 'csp_dep'], required: true).partial_dependency(links: true, includes: true) param_dep = dependency('param', fallback: ['param', 'param_dep'], required: true).partial_dependency(links: true, includes: true) @@ -8,21 +11,78 @@ else param_dep = dependency('param', fallback: ['param', 'param_dep'], required: true).partial_dependency(links: false, includes: true) endif +cblk_deps += [csp_dep, param_dep] + cblk_src = files([ 'src/csp_if_cblk.c', 'src/crypto/crypto.c', 'src/crypto/crypto_param.c', - 'src/crypto/tweetnacl.c', ]) +nacl_impl = get_option('nacl_impl') + +if nacl_impl == 'tweetnacl' + cblk_src += 'src/crypto/tweetnacl.c' + cblk_args += '-DUSE_TWEETNACL' +elif nacl_impl == 'sodium' + mod = import('unstable-external_project') + + configure_opts = [ + '--enable-minimal', + '--disable-ssp', + '--disable-pie', + '--enable-static', + '--disable-shared', + '--without-pthreads', + '--prefix=@PREFIX@', + '--libdir=@PREFIX@/@LIBDIR@', + '--includedir=@PREFIX@/@INCLUDEDIR@', + ] + + # we only support cross compiling to arm-none-eabi targets + if meson.is_cross_build() == true + sodium_env = environment() + target_c_args = get_option('c_args') + + c_flags_str = '-O3 ' + foreach arg : target_c_args + c_flags_str += arg + ' ' + endforeach + + sodium_env.set('CFLAGS', c_flags_str) + sodium_env.set('LDFLAGS', '-specs=nosys.specs') + + cross_configure_opt = [ + '--host=arm-none-eabi', + ] + endif + + libsodium_proj = mod.add_project('src/crypto/sodium/configure', + configure_options : configure_opts, + verbose : false, + cross_configure_options : cross_configure_opt, + env : sodium_env, + ) + + sodium_dep = libsodium_proj.dependency('sodium') + + cblk_deps += sodium_dep + cblk_args += '-DUSE_SODIUM' +endif + cblk_inc = include_directories('src') api = include_directories('include') cblk_lib = static_library('cblk', sources: [cblk_src], include_directories : [cblk_inc, api], - dependencies : [csp_dep, param_dep], + dependencies : cblk_deps, + c_args : cblk_args, install : false ) -cblk_dep = declare_dependency(include_directories : api, link_with : cblk_lib, dependencies: [csp_dep, param_dep]) +cblk_dep = declare_dependency( + include_directories : api, + link_with : cblk_lib, + dependencies: cblk_deps, +) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..bbcaa81 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,6 @@ +option('nacl_impl', + type: 'combo', + choices: ['tweetnacl', 'sodium'], + value: 'tweetnacl', + description: 'Which NaCl implementation to use' +) diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c index a5a3c08..497ab3c 100644 --- a/src/crypto/crypto.c +++ b/src/crypto/crypto.c @@ -4,7 +4,14 @@ #include #include +#ifdef USE_TWEETNACL #include "tweetnacl.h" +#endif + +#ifdef USE_SODIUM +#include +#endif + #include "crypto/crypto_param.h" #define NONCE_SIZE (sizeof(uint64_t) + sizeof(uint8_t)) @@ -18,17 +25,6 @@ void crypto_key_generate(param_t * param, int idx) { param_get_data(&crypto_key3, _crypto_beforenm[2], sizeof(_crypto_beforenm[2])); } -/* Required tweetnacl.c */ -void randombytes(unsigned char * a, unsigned long long c) { - // Note: Pseudo random since we are not initializing random! - unsigned int seed = csp_get_ms(); - while(c > 0) { - *a = rand_r(&seed) & 0xFF; - a++; - c--; - } -} - /* There is a 32-octet padding requirement on the plaintext buffer that you pass to crypto_box. Internally, the NaCl implementation uses this space to avoid having to allocate memory or diff --git a/src/crypto/sodium b/src/crypto/sodium new file mode 160000 index 0000000..e98f210 --- /dev/null +++ b/src/crypto/sodium @@ -0,0 +1 @@ +Subproject commit e98f2103da0253ffa4b959f319541ba645baca4d From 9f27ed7bac609e6ebb256da192ebd2b6127d6666 Mon Sep 17 00:00:00 2001 From: edvard Date: Fri, 21 Nov 2025 13:47:33 +0100 Subject: [PATCH 2/7] moveing debug prints verbosity, idx counter dont use signed --- src/csp_if_cblk.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 0594dc0..48136db 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -112,7 +112,7 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 uint16_t frame_length = be16toh(frame->hdr.data_length); - if (_cblk_rx_debug >= 1) { + if (_cblk_rx_debug >= 3) { printf("RX %p chain %u CCSDS header: %u %u %u\n", frame, group, frame->hdr.csp_packet_idx, frame->hdr.ccsds_frame_idx, frame_length); } @@ -126,7 +126,7 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 } else if (ifdata->rx_packet_idx == frame->hdr.csp_packet_idx && ifdata->rx_frame_idx == frame->hdr.ccsds_frame_idx) { /* We already handled this frame */ - if (_cblk_rx_debug >= 1) printf("Discarding dublicated frame\n"); + if (_cblk_rx_debug >= 2) printf("Discarding dublicated frame\n"); return CSP_ERR_NONE; } else if (frame->hdr.ccsds_frame_idx == 0) { @@ -139,7 +139,7 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 /* We are missing part of the received CSP frame */ if (_cblk_rx_debug >= 1) { - printf("Part of CSP frame is missing: Received part %d of %d, expected part %d of %d\n", + printf("Part of CSP frame is missing: Received part %"PRIu8" of %"PRIu8", expected part %"PRIu8" of %"PRIu8"\n", frame->hdr.ccsds_frame_idx, frame->hdr.csp_packet_idx, ifdata->rx_frame_idx+1, ifdata->rx_packet_idx); } iface->frame++; @@ -192,7 +192,7 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 rx_packet->frame_length = frame_length; } - if (_cblk_rx_debug >= 3) { + if (_cblk_rx_debug >= 5) { csp_hex_dump("-rx_dec", rx_packet->frame_begin, rx_packet->frame_length); } @@ -203,15 +203,13 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 return CSP_ERR_INVAL; } - if (_cblk_rx_debug >= 2) { + if (_cblk_rx_debug >= 4) { csp_hex_dump("packet", rx_packet->data, rx_packet->length); } csp_qfifo_write(rx_packet, iface, NULL); /* We have succesfully transmitted a full packet, reset our internal index counters for the next ones */ - ifdata->rx_packet_idx = -1; - ifdata->rx_frame_idx = -1; return CSP_ERR_NONE; } @@ -219,8 +217,8 @@ void csp_if_cblk_init(csp_iface_t * iface) { csp_cblk_interface_data_t * ifdata = iface->interface_data; - ifdata->rx_frame_idx = -1; - ifdata->rx_packet_idx = -1; + ifdata->rx_frame_idx = UINT8_MAX; + ifdata->rx_packet_idx = UINT8_MAX; iface->nexthop = csp_if_cblk_tx; } From f8a7c2dddae851186249a87f66f672b958e335ab Mon Sep 17 00:00:00 2001 From: edvard Date: Tue, 25 Nov 2025 10:11:23 +0100 Subject: [PATCH 3/7] add mutex around TX --- include/cblk/csp_if_cblk.h | 3 +++ meson.build | 47 +++++++++++++++++++++----------------- src/csp_if_cblk.c | 7 +++++- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/include/cblk/csp_if_cblk.h b/include/cblk/csp_if_cblk.h index 7499022..5030bad 100644 --- a/include/cblk/csp_if_cblk.h +++ b/include/cblk/csp_if_cblk.h @@ -46,6 +46,9 @@ typedef struct { /* Function provided by implementation to send a CCSDS frame */ int (*cblk_tx_send)(csp_iface_t* iface, cblk_frame_t* frame); + void (*cblk_tx_lock)(csp_iface_t* iface); + void (*cblk_tx_unlock)(csp_iface_t* iface); + /* Variables for internal use */ uint8_t rx_packet_idx; uint8_t rx_frame_idx; diff --git a/meson.build b/meson.build index 5978a32..2bd7745 100644 --- a/meson.build +++ b/meson.build @@ -25,22 +25,23 @@ if nacl_impl == 'tweetnacl' cblk_src += 'src/crypto/tweetnacl.c' cblk_args += '-DUSE_TWEETNACL' elif nacl_impl == 'sodium' - mod = import('unstable-external_project') - - configure_opts = [ - '--enable-minimal', - '--disable-ssp', - '--disable-pie', - '--enable-static', - '--disable-shared', - '--without-pthreads', - '--prefix=@PREFIX@', - '--libdir=@PREFIX@/@LIBDIR@', - '--includedir=@PREFIX@/@INCLUDEDIR@', - ] # we only support cross compiling to arm-none-eabi targets if meson.is_cross_build() == true + + mod = import('unstable-external_project') + + configure_opts = [ + '--enable-minimal', + '--disable-ssp', + '--disable-pie', + '--enable-static', + '--disable-shared', + '--without-pthreads', + '--prefix=@PREFIX@', + '--libdir=@PREFIX@/@LIBDIR@', + '--includedir=@PREFIX@/@INCLUDEDIR@', + ] sodium_env = environment() target_c_args = get_option('c_args') @@ -55,16 +56,20 @@ elif nacl_impl == 'sodium' cross_configure_opt = [ '--host=arm-none-eabi', ] - endif - libsodium_proj = mod.add_project('src/crypto/sodium/configure', - configure_options : configure_opts, - verbose : false, - cross_configure_options : cross_configure_opt, - env : sodium_env, - ) + libsodium_proj = mod.add_project('src/crypto/sodium/configure', + configure_options : configure_opts, + verbose : false, + cross_configure_options : cross_configure_opt, + env : sodium_env, + ) + + sodium_dep = libsodium_proj.dependency('sodium') + + else + sodium_dep = dependency('sodium', required: true) + endif - sodium_dep = libsodium_proj.dependency('sodium') cblk_deps += sodium_dep cblk_args += '-DUSE_SODIUM' diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 48136db..cbf0833 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -62,6 +62,8 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int uint16_t frame_length = packet->frame_length; uint8_t* frame_begin = packet->frame_begin; + ifdata->cblk_tx_lock(iface); + if (param_get_uint8(&tx_encrypt)) { frame_length = crypto_encrypt(ifdata->packet_enc, packet->frame_begin, packet->frame_length); frame_begin = &ifdata->packet_enc[CRYPTO_PREAMP]; @@ -77,6 +79,7 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int cblk_frame_t * tx_ccsds_buf = ifdata->cblk_tx_buffer_get(iface); if (tx_ccsds_buf == NULL) { csp_buffer_free(packet); + ifdata->cblk_tx_unlock(iface); return CSP_ERR_NOBUFS; } @@ -97,11 +100,13 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int if (ifdata->cblk_tx_send(iface, tx_ccsds_buf) < 0) { csp_buffer_free(packet); + ifdata->cblk_tx_unlock(iface); return CSP_ERR_NOBUFS; } } csp_buffer_free(packet); + ifdata->cblk_tx_unlock(iface); return CSP_ERR_NONE; } @@ -166,7 +171,7 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 if (frame->hdr.nacl_crypto_key > 0) { - if (_cblk_rx_debug >= 3) { + if (_cblk_rx_debug >= 4) { csp_hex_dump("-rx_enc", &ifdata->packet_dec[CRYPTO_PREAMP], frame_length); } From 16a55ec5a2aa6cd376354083499cd8976cbf8129 Mon Sep 17 00:00:00 2001 From: edvard Date: Tue, 25 Nov 2025 11:17:46 +0100 Subject: [PATCH 4/7] remove old prints --- src/csp_if_cblk.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index cbf0833..9989708 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -213,8 +213,6 @@ int csp_if_cblk_rx(csp_iface_t * iface, cblk_frame_t *frame, uint32_t len, uint8 } csp_qfifo_write(rx_packet, iface, NULL); - /* We have succesfully transmitted a full packet, - reset our internal index counters for the next ones */ return CSP_ERR_NONE; } From 67d598bf49f1eaa015bc920e1f38c85c740a41b7 Mon Sep 17 00:00:00 2001 From: edvard Date: Tue, 25 Nov 2025 16:09:21 +0100 Subject: [PATCH 5/7] unlock before packet free to avoid context switch --- src/csp_if_cblk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 9989708..45b8ae5 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -78,8 +78,8 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int cblk_frame_t * tx_ccsds_buf = ifdata->cblk_tx_buffer_get(iface); if (tx_ccsds_buf == NULL) { - csp_buffer_free(packet); ifdata->cblk_tx_unlock(iface); + csp_buffer_free(packet); return CSP_ERR_NOBUFS; } @@ -99,14 +99,14 @@ int csp_if_cblk_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet, int bytes_remain -= segment_len; if (ifdata->cblk_tx_send(iface, tx_ccsds_buf) < 0) { - csp_buffer_free(packet); ifdata->cblk_tx_unlock(iface); + csp_buffer_free(packet); return CSP_ERR_NOBUFS; } } - csp_buffer_free(packet); ifdata->cblk_tx_unlock(iface); + csp_buffer_free(packet); return CSP_ERR_NONE; } From facf2f1b355db4d61a9471499e12766723d1a333 Mon Sep 17 00:00:00 2001 From: edvard Date: Tue, 25 Nov 2025 16:21:26 +0100 Subject: [PATCH 6/7] enforce lock implemented --- src/csp_if_cblk.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 45b8ae5..c96fe87 100644 --- a/src/csp_if_cblk.c +++ b/src/csp_if_cblk.c @@ -223,5 +223,10 @@ void csp_if_cblk_init(csp_iface_t * iface) { ifdata->rx_frame_idx = UINT8_MAX; ifdata->rx_packet_idx = UINT8_MAX; + if(ifdata->cblk_tx_lock == NULL || ifdata->cblk_tx_unlock == NULL) { + printf("csp_if_cblk_init: lock function pointers must be set!\n"); + return; + } + iface->nexthop = csp_if_cblk_tx; } From 8c02b917462b1201388385483de79b8917e59f94 Mon Sep 17 00:00:00 2001 From: edvard Date: Tue, 25 Nov 2025 16:25:12 +0100 Subject: [PATCH 7/7] fix missing strlcpy for test --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4fec53b..3054135 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Setup build system packages on Linux run: | - sudo apt-get install ninja-build meson tree gcc-arm-none-eabi python3-pip + sudo apt-get install ninja-build meson tree gcc-arm-none-eabi python3-pip libbsd-dev - name: Checkout uses: actions/checkout@v4 with: