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: 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/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 155d98f..2bd7745 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,83 @@ 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' + + # 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') + + 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', + ] + + 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 + + + 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 diff --git a/src/csp_if_cblk.c b/src/csp_if_cblk.c index 0594dc0..c96fe87 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]; @@ -76,6 +78,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) { + ifdata->cblk_tx_unlock(iface); csp_buffer_free(packet); return CSP_ERR_NOBUFS; } @@ -96,11 +99,13 @@ 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) { + ifdata->cblk_tx_unlock(iface); csp_buffer_free(packet); return CSP_ERR_NOBUFS; } } + ifdata->cblk_tx_unlock(iface); csp_buffer_free(packet); return CSP_ERR_NONE; @@ -112,7 +117,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 +131,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 +144,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++; @@ -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); } @@ -192,7 +197,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 +208,11 @@ 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 +220,13 @@ 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; + + 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; }