diff --git a/CMakeLists.txt b/CMakeLists.txt index 97fa74039..ba90bcb80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ endif() # Build type can still be overridden by setting -DCMAKE_BUILD_TYPE= set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") -cmake_minimum_required(VERSION 2.8.12...3.29) +cmake_minimum_required(VERSION 2.8.12...3.30) project(gnss-sdr CXX C) set(GNSSSDR_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # Allows to be a sub-project @@ -349,16 +349,16 @@ set(GNSSSDR_ABSEIL_MIN_VERSION "20240116") ################################################################################ # Versions to download and build (but not to install system-wide) if not found ################################################################################ -set(GNSSSDR_ARMADILLO_LOCAL_VERSION "12.8.x") +set(GNSSSDR_ARMADILLO_LOCAL_VERSION "14.0.x") set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.2") set(GNSSSDR_GLOG_LOCAL_VERSION "0.7.1") set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.27") -set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "27.1") +set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "27.2") set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.14") set(GNSSSDR_GTEST_LOCAL_VERSION "1.14.0") set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "origin/master") set(GNSSSDR_GNSSTK_LOCAL_VERSION "14.3.0") -set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.8.4") +set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.8.5") set(GNSSSDR_MATHJAX_EXTERNAL_VERSION "2.7.7") set(GNSSSDR_ABSL_LOCAL_VERSION "origin/master") # live at head (see https://abseil.io/about/releases) @@ -756,8 +756,18 @@ set(BOOST_COMPONENTS atomic chrono date_time serialization system thread) if(NOT ${FILESYSTEM_FOUND}) set(BOOST_COMPONENTS ${BOOST_COMPONENTS} filesystem) endif() -find_package(Boost ${GNSSSDR_BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED) - +if(CMAKE_VERSION VERSION_LESS 3.30) + find_package(Boost ${GNSSSDR_BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED) +else() + find_package(Boost ${GNSSSDR_BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS}) + if(NOT Boost_FOUND) + message(STATUS "Trying deprecated FindBoost Module ...") + if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) + find_package(Boost ${GNSSSDR_BOOST_MIN_VERSION} REQUIRED COMPONENTS ${BOOST_COMPONENTS}) + endif() + endif() +endif() if(NOT Boost_FOUND) message(FATAL_ERROR "Fatal error: Boost (version >=${GNSSSDR_BOOST_MIN_VERSION}) required.") endif() @@ -2101,7 +2111,7 @@ if(NOT ARMADILLO_FOUND OR ENABLE_OWN_ARMADILLO) CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_BUILD_TYPE=$<$:Debug>$<$:Release>$<$:RelWithDebInfo>$<$:MinSizeRel>$<$:Debug>$<$:Debug>$<$:RelWithDebInfo>$<$:RelWithDebInfo>$<$:Debug> -DCMAKE_INSTALL_PREFIX=${GNSSSDR_BINARY_DIR}/armadillo-${armadillo_RELEASE} - -DBUILD_SHARED_LIBS=OFF + -DSTATIC_LIB=ON -DBUILD_SMOKE_TEST=OFF -DALLOW_BLAS_LAPACK_MACOS=ON ${ARMADILLO_CXX_VERSION} @@ -2120,7 +2130,7 @@ if(NOT ARMADILLO_FOUND OR ENABLE_OWN_ARMADILLO) CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_BUILD_TYPE=$<$:Debug>$<$:Release>$<$:RelWithDebInfo>$<$:MinSizeRel>$<$:Debug>$<$:Debug>$<$:RelWithDebInfo>$<$:RelWithDebInfo>$<$:Debug> -DCMAKE_INSTALL_PREFIX=${GNSSSDR_BINARY_DIR}/armadillo-${armadillo_RELEASE} - -DBUILD_SHARED_LIBS=OFF + -DSTATIC_LIB=ON -DBUILD_SMOKE_TEST=OFF -DALLOW_BLAS_LAPACK_MACOS=ON ${ARMADILLO_CXX_VERSION} diff --git a/README.md b/README.md index 5b7bc9dfd..557b3686c 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ information about this open-source, software-defined GNSS receiver. - [Debian / Ubuntu](#debian--ubuntu) - [AlmaLinux](#almalinux) - [Arch Linux](#arch-linux) - - [CentOS](#centos) - [Fedora](#fedora) - [openSUSE](#opensuse) - [Rocky Linux](#rocky-linux) @@ -126,7 +125,7 @@ This section describes how to set up the compilation environment in GNU/Linux or ## GNU/Linux - Tested distributions: Ubuntu 14.04 LTS and above; Debian 9.0 "stretch" and - above; Arch Linux; CentOS 7; Fedora 26 and above; OpenSUSE 42.3 and above. + above; Arch Linux; Fedora 26 and above; OpenSUSE 42.3 and above. - Supported microprocessor architectures: - i386: Intel x86 instruction set (32-bit microprocessors). - amd64: also known as x86-64, the 64-bit version of the x86 instruction set, @@ -233,25 +232,6 @@ $ pacman -S gcc make cmake pkgconf git boost boost-libs libvolk gnuradio \ Once you have installed these packages, you can jump directly to [download the source code and build GNSS-SDR](#clone-gnss-sdrs-git-repository). -#### CentOS - -If you are using CentOS 7, you can install the dependencies via Extra Packages -for Enterprise Linux ([EPEL](https://fedoraproject.org/wiki/EPEL)): - -``` -$ sudo yum install wget -$ wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -$ sudo rpm -Uvh epel-release-latest-7.noarch.rpm -$ sudo yum install make automake gcc gcc-c++ kernel-devel libtool \ - hdf5-devel cmake git boost-devel boost-date-time boost-system \ - boost-filesystem boost-thread boost-chrono boost-serialization \ - log4cpp-devel gnuradio-devel gr-osmosdr-devel blas-devel lapack-devel \ - armadillo-devel openssl-devel libpcap-devel python-mako python-six pugixml-devel -``` - -Once you have installed these packages, you can jump directly to -[download the source code and build GNSS-SDR](#clone-gnss-sdrs-git-repository). - #### Fedora If you are using Fedora 26 or above, the required software dependencies can be @@ -403,12 +383,12 @@ or manually as explained below, and then please follow instructions on how to ``` $ sudo apt-get install libblas-dev liblapack-dev # For Debian/Ubuntu/LinuxMint -$ sudo yum install lapack-devel blas-devel # For Fedora/CentOS/RHEL +$ sudo yum install lapack-devel blas-devel # For Fedora/RHEL $ sudo zypper install lapack-devel blas-devel # For OpenSUSE $ sudo pacman -S blas lapack # For Arch Linux -$ wget https://sourceforge.net/projects/arma/files/armadillo-12.8.1.tar.xz -$ tar xvfz armadillo-12.8.1.tar.xz -$ cd armadillo-12.8.1 +$ wget https://sourceforge.net/projects/arma/files/armadillo-14.0.0.tar.xz +$ tar xvfz armadillo-14.0.0.tar.xz +$ cd armadillo-14.0.0 $ cmake . $ make $ sudo make install diff --git a/cmake/Modules/FindGFORTRAN.cmake b/cmake/Modules/FindGFORTRAN.cmake index 89530518d..5a698ce89 100644 --- a/cmake/Modules/FindGFORTRAN.cmake +++ b/cmake/Modules/FindGFORTRAN.cmake @@ -55,6 +55,7 @@ find_library(GFORTRAN NAMES gfortran /usr/lib/gcc/sh4-linux-gnu /usr/lib/gcc/i686-redhat-linux # Fedora /usr/lib64/gcc/x86_64-redhat-linux + /usr/lib/gcc/x86_64-redhat-linux /usr/lib/gcc/armv7hl-redhat-linux-gnueabi /usr/lib/gcc/aarch64-redhat-linux /usr/lib/gcc/ppc64le-redhat-linux diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index 58c1c94e2..b1edb5982 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -117,6 +117,9 @@ else() if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_SIGN_ECDSA_SHA256") set(GNUTLS_SIGN_ECDSA_SHA256 TRUE) endif() + if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_SIGN_ECDSA_SHA512") + set(GNUTLS_SIGN_ECDSA_SHA512 TRUE) + endif() if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_DIG_SHA3_256") set(GNUTLS_DIG_SHA3_256 TRUE) endif() @@ -181,6 +184,9 @@ function(link_to_crypto_dependencies target) if(GNUTLS_SIGN_ECDSA_SHA256) target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_SIGN_ECDSA_SHA256=1) endif() + if(GNUTLS_SIGN_ECDSA_SHA512) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_SIGN_ECDSA_SHA512=1) + endif() if(GNUTLS_DIG_SHA3_256) target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_DIG_SHA3_256=1) endif() diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc index 5249cd115..569319d1c 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc @@ -692,12 +692,14 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count) d_gnss_synchro->Acq_delay_samples -= static_cast(d_acq_parameters.resampler_latency_samples); // account the resampler filter latency d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = rint(static_cast(samp_count) * d_acq_parameters.resampler_ratio); + d_gnss_synchro->fs = d_acq_parameters.resampled_fs; } else { d_gnss_synchro->Acq_delay_samples = static_cast(std::fmod(static_cast(indext), d_acq_parameters.samples_per_code)); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = samp_count; + d_gnss_synchro->fs = d_acq_parameters.fs_in; } } else @@ -751,6 +753,7 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count) d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = rint(static_cast(samp_count) * d_acq_parameters.resampler_ratio); d_gnss_synchro->Acq_doppler_step = d_acq_parameters.doppler_step2; + d_gnss_synchro->fs = d_acq_parameters.resampled_fs; } else { @@ -758,6 +761,7 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count) d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); d_gnss_synchro->Acq_samplestamp_samples = samp_count; d_gnss_synchro->Acq_doppler_step = d_acq_parameters.doppler_step2; + d_gnss_synchro->fs = d_acq_parameters.fs_in; } } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt index a57544a7f..e567eab94 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt @@ -8,7 +8,7 @@ ######################################################################## # Project setup ######################################################################## -cmake_minimum_required(VERSION 2.8.12...3.29) +cmake_minimum_required(VERSION 2.8.12...3.30) set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose build type: None Debug Release RelWithDebInfo MinSizeRel") project(volk_gnsssdr) enable_language(CXX) diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index 43e62a738..0688af6e9 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -3,14 +3,15 @@ * \brief GNU Radio block that processes Galileo OSNMA data received from * Galileo E1B telemetry blocks. After successful decoding, sends the content to * the PVT block. - * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * \author Carles Fernandez-Prades, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -24,12 +25,13 @@ #include "osnma_dsm_reader.h" // for OSNMA_DSM_Reader #include "osnma_helper.h" #include // for gr::io_signature::make -#include #include #include -#include +#include // for std::setfill +#include // for std::hex, std::uppercase #include -#include +#include // for std::accumulate +#include // std::stringstream #include // for typeid #include @@ -101,14 +103,14 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) const auto sat = Gnss_Satellite(std::string("Galileo"), nma_msg->PRN); // TODO remove if unneeded std::ostringstream output_message; - output_message << "Galileo OSNMA: complete OSNMA message received starting at " + output_message << "Galileo OSNMA: data received starting at " << "WN=" << nma_msg->WN_sf0 << ", TOW=" << nma_msg->TOW_sf0 << ", from satellite " << sat; - LOG(WARNING) << output_message.str(); + LOG(INFO) << output_message.str(); std::cout << output_message.str() << std::endl; process_osnma_message(nma_msg); @@ -119,33 +121,34 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) const auto inav_data = wht::any_cast>>(pmt::any_ref(msg)); uint32_t PRNa = std::get<0>(*inav_data); std::string nav_data = std::get<1>(*inav_data); - ; uint32_t TOW = std::get<2>(*inav_data); // iono data => 549 bits, utc data, 141 bits. if (nav_data.size() == 549) { -// LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " -// << "TOW_sf=" << TOW; + // LOG(INFO) << "Galileo OSNMA: received ADKD=0/12 navData, PRN_d (" << PRNa << ") " + // << "TOW_sf=" << TOW; d_satellite_nav_data[PRNa][TOW].ephemeris_iono_vector_2 = nav_data; } else if (nav_data.size() == 141) { -// LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") " -// << "TOW_sf=" << TOW; + // LOG(INFO) << "Galileo OSNMA: received ADKD=4 navData, PRN_d (" << PRNa << ") " + // << "TOW_sf=" << TOW; d_satellite_nav_data[PRNa][TOW].utc_vector_2 = nav_data; } else - LOG(WARNING) << "osnma_msg_receiver incorrect navData parsing!"; + { + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver incorrect navData parsing!"; + } } else { - LOG(WARNING) << "osnma_msg_receiver received an unknown object type!"; + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver received an unknown object type!"; } } catch (const wht::bad_any_cast& e) { - LOG(WARNING) << "osnma_msg_receiver Bad any_cast: " << e.what(); + LOG(WARNING) << "Galileo OSNMA: osnma_msg_receiver Bad any_cast: " << e.what(); } // Send the resulting decoded NMA data (if available) to PVT @@ -155,7 +158,7 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) this->message_port_pub(pmt::mp("OSNMA_to_PVT"), pmt::make_any(osnma_data_ptr)); d_new_data = false; // d_osnma_data = OSNMA_data(); - DLOG(INFO) << "NMA info sent to the PVT block through the OSNMA_to_PVT async message port"; + DLOG(INFO) << "Galileo OSNMA: NMA info sent to the PVT block through the OSNMA_to_PVT async message port"; } } @@ -172,7 +175,9 @@ void osnma_msg_receiver::process_osnma_message(const std::shared_ptr& read_dsm_block(osnma_msg); process_dsm_block(osnma_msg); // will process dsm block if received a complete one, then will call mack processing upon re-setting the dsm block to 0 if (d_osnma_data.d_dsm_kroot_message.towh_k != 0) - local_time_verification(osnma_msg); + { + local_time_verification(osnma_msg); + } read_and_process_mack_block(osnma_msg); // only process them if at least 3 available. } @@ -203,8 +208,6 @@ void osnma_msg_receiver::read_dsm_header(uint8_t dsm_header) { d_osnma_data.d_dsm_header.dsm_id = d_dsm_reader->get_dsm_id(dsm_header); d_osnma_data.d_dsm_header.dsm_block_id = d_dsm_reader->get_dsm_block_id(dsm_header); // BID -// LOG(INFO) << "OSNMA: DSM_ID=" << static_cast(d_osnma_data.d_dsm_header.dsm_id); -// LOG(INFO) << "OSNMA: DSM_BID=" << static_cast(d_osnma_data.d_dsm_header.dsm_block_id); LOG(INFO) << "Galileo OSNMA: Received block DSM_BID=" << static_cast(d_osnma_data.d_dsm_header.dsm_block_id) << " with DSM_ID " << static_cast(d_osnma_data.d_dsm_header.dsm_id); } @@ -246,7 +249,7 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = number_of_blocks; - LOG(INFO) << "OSNMA: number_of_blocks=" << static_cast(number_of_blocks); + LOG(INFO) << "Galileo OSNMA: number of blocks in this message: " << static_cast(number_of_blocks); if (number_of_blocks == 0) { // Something is wrong, start over @@ -275,7 +278,7 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } else { - for (uint8_t k = 0; k < d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id]; k++) + for (uint16_t k = 0; k < d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id]; k++) { if (d_dsm_id_received[d_osnma_data.d_dsm_header.dsm_id][k] == 0) { @@ -289,8 +292,10 @@ void osnma_msg_receiver::read_dsm_block(const std::shared_ptr& osnma_ } available_blocks << "]"; LOG(INFO) << available_blocks.str(); + std::cout << available_blocks.str() << std::endl; } + /** * @brief Function to verify the local time based on GST_SIS and GST_0 * @@ -323,7 +328,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS)<< " | < " << static_cast(d_T_L) << " ]" << std::endl; // TODO set flag to false to avoid processing dsm and MACK messages @@ -334,7 +339,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; } else { @@ -342,7 +347,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; + LOG(WARNING) << "Galileo OSNMA: ( |local_t - GST_SIS| < T_L ) [ |" << static_cast(d_receiver_time - d_GST_SIS) << " | < " << static_cast(d_T_L) << " ]"; } } @@ -391,7 +396,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg if (d_osnma_data.d_dsm_header.dsm_id < 12) { // Parse Kroot message - LOG(INFO) << "OSNMA: DSM-KROOT message received."; + LOG(INFO) << "Galileo OSNMA: DSM-KROOT message received."; d_osnma_data.d_dsm_kroot_message.nb_dk = d_dsm_reader->get_number_blocks_index(dsm_msg[0]); d_osnma_data.d_dsm_kroot_message.pkid = d_dsm_reader->get_pkid(dsm_msg); d_osnma_data.d_dsm_kroot_message.cidkr = d_dsm_reader->get_cidkr(dsm_msg); @@ -457,11 +462,11 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg std::vector hash; if (d_osnma_data.d_dsm_kroot_message.hf == 0) // Table 8. { - hash = d_crypto->computeSHA256(MSG); + hash = d_crypto->compute_SHA_256(MSG); } else if (d_osnma_data.d_dsm_kroot_message.hf == 2) { - hash = d_crypto->computeSHA3_256(MSG); + hash = d_crypto->compute_SHA3_256(MSG); } else { @@ -483,7 +488,14 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg << ", WN=" << static_cast(d_osnma_data.d_dsm_kroot_message.wn_k) << ", TOW=" << static_cast(d_osnma_data.d_dsm_kroot_message.towh_k) * 3600; local_time_verification(osnma_msg); - d_kroot_verified = d_crypto->verify_signature(message, d_osnma_data.d_dsm_kroot_message.ds); + if(l_ds_bits == 512) + { + d_kroot_verified = d_crypto->verify_signature_ecdsa_p256(message, d_osnma_data.d_dsm_kroot_message.ds); + } + else if(l_ds_bits == 1056) + { + d_kroot_verified = d_crypto->verify_signature_ecdsa_p521(message, d_osnma_data.d_dsm_kroot_message.ds); + } if (d_kroot_verified) { std::cout << "Galileo OSNMA: KROOT authentication successful!" << std::endl; @@ -495,6 +507,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg else { LOG(WARNING) << "Galileo OSNMA: KROOT authentication failed."; + std::cerr << "Galileo OSNMA: KROOT authentication failed." << std::endl; } } else @@ -506,7 +519,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg } else if (d_osnma_data.d_dsm_header.dsm_id >= 12 && d_osnma_data.d_dsm_header.dsm_id < 16) { - LOG(WARNING) << "Galileo OSNMA: DSM-PKR message received."; + LOG(INFO) << "Galileo OSNMA: DSM-PKR message received."; // Save DSM-PKR message d_osnma_data.d_dsm_pkr_message.nb_dp = d_dsm_reader->get_number_blocks_index(dsm_msg[0]); d_osnma_data.d_dsm_pkr_message.mid = d_dsm_reader->get_mid(dsm_msg); @@ -530,7 +543,7 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg uint32_t l_dp_bytes = dsm_msg.size(); if (d_osnma_data.d_dsm_pkr_message.npkt == 4) { - LOG(WARNING) << "OSNMA: OAM received"; + LOG(WARNING) << "Galileo OSNMA: OAM received"; l_npk_bytes = l_dp_bytes - 130; // bytes } @@ -576,8 +589,8 @@ void osnma_msg_receiver::process_dsm_message(const std::vector& dsm_msg else { // Reserved message? - LOG(WARNING) << "OSNMA Reserved message received"; - // d_osnma_data = OSNMA_data(); + LOG(WARNING) << "Galileo OSNMA: Reserved message received"; + std::cerr << "Galileo OSNMA: Reserved message received" << std::endl; } d_number_of_blocks[d_osnma_data.d_dsm_header.dsm_id] = 0; } @@ -883,15 +896,16 @@ void osnma_msg_receiver::process_mack_message() { if (d_kroot_verified == false && d_tesla_key_verified == false) { - LOG(WARNING) << "Galileo OSNMA: MACK cannot be processed. " - << ", " - << "No Kroot nor TESLA key available"; + LOG(WARNING) << "Galileo OSNMA: MACK cannot be processed, " + << "no Kroot nor TESLA key available."; if (!d_flag_debug) { return; // early return, cannot proceed further without one of the two verified. this equals to having Kroot but no TESLa key yet. } else - LOG(WARNING) << "But it will be processed for debugging purposes."; + { + LOG(WARNING) << "Galileo OSNMA: But it will be processed for debugging purposes."; + } } // verify tesla key and add it to the container of verified keys if successful if (d_tesla_keys.find(d_osnma_data.d_nav_data.TOW_sf0) == d_tesla_keys.end()) // check if already available => no need to verify @@ -914,10 +928,9 @@ void osnma_msg_receiver::process_mack_message() d_tags_awaiting_verify.insert(std::pair(mack->TOW, tag0)); // bool ret = verify_macseq(*mack); std::vector macseq_verified_tags = verify_macseq_new(*mack); - for (std::size_t i = 0; i < macseq_verified_tags.size(); ++i) + for (auto & tag_and_info : macseq_verified_tags) { // add tags of current mack to the verification queue - auto& tag_and_info = macseq_verified_tags[i]; Tag t(tag_and_info, mack->TOW, mack->WN, mack->PRNa, tag_and_info.counter); d_tags_awaiting_verify.insert(std::pair(mack->TOW, t)); LOG(INFO) << "Galileo OSNMA: Add Tag Id= " @@ -933,12 +946,13 @@ void osnma_msg_receiver::process_mack_message() << ", PRNd=" << static_cast(t.PRN_d); } - std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; + LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size(); mack = d_macks_awaiting_MACSEQ_verification.erase(mack); } else - { // key not yet available - keep in container until then -- might be deleted if container size exceeds max allowed + { + // key not yet available - keep in container until then -- might be deleted if container size exceeds max allowed ++mack; } } @@ -960,18 +974,24 @@ void osnma_msg_receiver::process_mack_message() if (ret) { it.second.status = Tag::SUCCESS; - LOG(WARNING) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id= " - << it.second.tag_id - << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << it.second.received_tag << std::dec - << ", TOW=" - << it.second.TOW - << ", ADKD=" - << static_cast(it.second.ADKD) - << ", PRNa=" - << static_cast(it.second.PRNa) - << ", PRNd=" - << static_cast(it.second.PRN_d); + LOG(INFO) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" + << it.second.tag_id + << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << it.second.received_tag << std::dec + << ", TOW=" + << it.second.TOW + << ", ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d); + std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d) << std::endl; } /* TODO notify PVT via pmt * have_new_data() true @@ -980,7 +1000,7 @@ void osnma_msg_receiver::process_mack_message() else { it.second.status = Tag::FAIL; - LOG(WARNING) << "Galileo OSNMA: Tag verification :: FAILURE for tag Id=" + LOG(WARNING) << "Galileo OSNMA: Tag verification :: FAILURE for tag Id=" << it.second.tag_id << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase << it.second.received_tag << std::dec @@ -992,6 +1012,12 @@ void osnma_msg_receiver::process_mack_message() << static_cast(it.second.PRNa) << ", PRNd=" << static_cast(it.second.PRN_d); + std::cerr << "Galileo OSNMA: Tag verification :: FAILURE for tag ADKD=" + << static_cast(it.second.ADKD) + << ", PRNa=" + << static_cast(it.second.PRNa) + << ", PRNd=" + << static_cast(it.second.PRN_d) << std::endl; } } else if (it.second.TOW > d_osnma_data.d_nav_data.TOW_sf0) @@ -1031,29 +1057,32 @@ void osnma_msg_receiver::process_mack_message() * \pre DSM_PKR_message correctly filled in especially the 1024 intermediate tree nodes * \returns true if computed merkle root matches received one, false otherwise */ -bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) +bool osnma_msg_receiver::verify_dsm_pkr(const DSM_PKR_message& message) const { - std::vector computed_merkle_root; // x_4_0 - std::vector base_leaf = compute_base_leaf(message); // m_i + const auto base_leaf = get_merkle_tree_leaves(message); // m_i + const auto computed_merkle_root = compute_merkle_root(message, base_leaf); // x_4_0 + const auto msg_id = static_cast(message.mid); + LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: leaf provided for Message ID " << msg_id; - LOG(INFO) << "Galileo OSNMA: DSM-PKR :: leaf provided: m_" << static_cast(message.mid); - - computed_merkle_root = compute_merke_root(message, base_leaf); - - if (computed_merkle_root == d_crypto->getMerkleRoot()) + if (computed_merkle_root == d_crypto->get_merkle_root()) { - LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: SUCCESS!." << std::endl; + LOG(INFO) << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: SUCCESS."; + std::cout << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: SUCCESS." << std::endl; return true; } else { - LOG(INFO) << "Galileo OSNMA: DSM-PKR verification :: FAILURE." << std::endl; + LOG(WARNING) << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: FAILURE."; + std::cerr << "Galileo OSNMA: DSM-PKR verification for Message ID " << msg_id << " :: FAILURE." << std::endl; return false; } } -std::vector osnma_msg_receiver::compute_merke_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const + + +std::vector osnma_msg_receiver::compute_merkle_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const { - std::vector x_next, x_current = d_crypto->computeSHA256(m_i); + std::vector x_next; + std::vector x_current = d_crypto->compute_SHA_256(m_i); for (size_t i = 0; i < 4; i++) { x_next.clear(); @@ -1073,16 +1102,20 @@ std::vector osnma_msg_receiver::compute_merke_root(const DSM_PKR_messag } // Compute the next node. - x_current = d_crypto->computeSHA256(x_next); + x_current = d_crypto->compute_SHA_256(x_next); } return x_current; } -std::vector osnma_msg_receiver::compute_base_leaf(const DSM_PKR_message& dsm_pkr_message) const -{ // build base leaf m_i + + +std::vector osnma_msg_receiver::get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const +{ + // build base leaf m_i according to OSNMA SIS ICD v1.1, section 6.2 DSM-PKR Verification std::vector m_i; - m_i.reserve(2 + dsm_pkr_message.npk.size()); + const size_t size_npk = dsm_pkr_message.npk.size(); + m_i.reserve(1 + size_npk); m_i.push_back((dsm_pkr_message.npkt << 4) + dsm_pkr_message.npktid); - for (uint8_t i = 0; i < dsm_pkr_message.npk.size(); i++) + for (size_t i = 0; i < size_npk; i++) { m_i.push_back(dsm_pkr_message.npk[i]); } @@ -1090,13 +1123,13 @@ std::vector osnma_msg_receiver::compute_base_leaf(const DSM_PKR_message } -bool osnma_msg_receiver::verify_tag(Tag& tag) +bool osnma_msg_receiver::verify_tag(const Tag& tag) const { // Debug -// LOG(INFO) << "Galileo OSNMA: Tag verification :: Start for tag Id= " -// << tag.tag_id -// << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase -// << tag.received_tag << std::dec; + // LOG(INFO) << "Galileo OSNMA: Tag verification :: Start for tag Id= " + // << tag.tag_id + // << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + // << tag.received_tag << std::dec; // build message std::vector m = build_message(tag); @@ -1104,23 +1137,38 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) std::vector applicable_key; if (tag.ADKD == 0 || tag.ADKD == 4) { - applicable_key = d_tesla_keys[tag.TOW + 30]; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 30); + const auto it = d_tesla_keys.find(tag.TOW + 30); + if(it != d_tesla_keys.cend()) + { + applicable_key = it->second; + } + else + { + return false; + } + // LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 30); + } + else // ADKD 12 + { + const auto it = d_tesla_keys.find(tag.TOW + 330); + if(it != d_tesla_keys.cend()) + { + applicable_key = it->second; + } + else + { + return false; + } + // LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 330); } - else // ADKD 12 - { - applicable_key = d_tesla_keys[tag.TOW + 330]; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<(tag.TOW + 330); - } - if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { - mac = d_crypto->computeHMAC_SHA_256(applicable_key, m); + mac = d_crypto->compute_HMAC_SHA_256(applicable_key, m); } else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES { - mac = d_crypto->computeCMAC_AES(applicable_key, m); + mac = d_crypto->compute_CMAC_AES(applicable_key, m); } // truncate the computed mac: trunc(l_t, mac(K,m)) Eq. 23 ICD @@ -1164,7 +1212,7 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) // Compare computed tag with received one truncated if (tag.received_tag == computed_mac) { - std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id= " + LOG(INFO) << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" << tag.tag_id << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase << tag.received_tag << std::dec @@ -1175,6 +1223,14 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) << ", PRNa=" << static_cast(tag.PRNa) << ", PRNd=" + << static_cast(tag.PRN_d); + std::cout << "Galileo OSNMA: Tag verification :: SUCCESS for tag Id=" + << tag.tag_id + << ", ADKD=" + << static_cast(tag.ADKD) + << ", PRNa=" + << static_cast(tag.PRNa) + << ", PRNd=" << static_cast(tag.PRN_d) << std::endl; return true; } @@ -1182,11 +1238,13 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) } -std::vector osnma_msg_receiver::build_message(const Tag& tag) +std::vector osnma_msg_receiver::build_message(const Tag& tag) const { std::vector m; if (tag.CTR != 1) - m.push_back(static_cast(tag.PRN_d)); + { + m.push_back(static_cast(tag.PRN_d)); + } m.push_back(static_cast(tag.PRNa)); // TODO: maybe here I have to use d_receiver_time instead of d_GST_SIS which is what I am computing uint32_t GST = d_helper->compute_gst(tag.WN, tag.TOW); @@ -1203,16 +1261,34 @@ std::vector osnma_msg_receiver::build_message(const Tag& tag) std::vector applicable_nav_data_bytes; if (tag.ADKD == 0 || tag.ADKD == 12) // note: for ADKD=12 still the same logic applies. Only the Key selection is shifted 10 Subframes into the future. { - applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].ephemeris_iono_vector_2; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; + const auto it = d_satellite_nav_data.find(tag.PRN_d); + if (it != d_satellite_nav_data.cend()) + { + const auto it2 = it->second.find(tag.TOW - 30); + if (it2 != it->second.cend()) + { + applicable_nav_data = it2->second.ephemeris_iono_vector_2; + } + } + // LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; } else if (tag.ADKD == 4) { - applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].utc_vector_2; -// LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; + const auto it = d_satellite_nav_data.find(tag.PRN_d); + if (it != d_satellite_nav_data.cend()) + { + const auto it2 = it->second.find(tag.TOW - 30); + if (it2 != it->second.cend()) + { + applicable_nav_data = it2->second.utc_vector_2; + } + } + // LOG(INFO) << "|---> Galileo OSNMA :: applicable NavData (PRN_d="<< static_cast(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; } else - LOG(WARNING) << "Galileo OSNMA :: Tag verification :: unknown ADKD"; + { + LOG(WARNING) << "Galileo OSNMA: Tag verification :: unknown ADKD"; + } // convert std::string to vector applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data); @@ -1283,10 +1359,10 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO uint32_t GST_SFi = d_receiver_time - 30; // GST of target key is to be used. std::vector hash; const uint8_t lk_bytes = d_dsm_reader->get_lk_bits(d_osnma_data.d_dsm_kroot_message.ks) / 8; - // std::vector validated_key; + std::vector validated_key; if (d_tesla_key_verified) { // have to go up to last verified key - d_validated_key = d_tesla_keys.rbegin()->second; + validated_key = d_tesla_keys.rbegin()->second; num_of_hashes_needed = (d_receiver_time - d_last_verified_key_GST) / 30; // Eq. 19 ICD modified LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) need to be performed up to closest verified TESLA key"; @@ -1294,7 +1370,7 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO } else { // have to go until Kroot - d_validated_key = d_osnma_data.d_dsm_kroot_message.kroot; + validated_key = d_osnma_data.d_dsm_kroot_message.kroot; num_of_hashes_needed = (d_receiver_time - d_GST_0) / 30 + 1; // Eq. 19 IC LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) need to be performed up to Kroot"; @@ -1303,20 +1379,22 @@ bool osnma_msg_receiver::verify_tesla_key(std::vector& key, uint32_t TO // truncate hash std::vector computed_key; computed_key.reserve(key.size()); - for (uint16_t i = 0; i < key.size(); i++) + for (size_t i = 0; i < key.size(); i++) { computed_key.push_back(hash[i]); } - if (computed_key == d_validated_key && num_of_hashes_needed > 0) + if (computed_key == validated_key && num_of_hashes_needed > 0) { - LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: SUCCESS!"; + LOG(INFO) << "Galileo OSNMA: TESLA key verification :: SUCCESS!"; + std::cout << "Galileo OSNMA: TESLA key verification :: SUCCESS!" << std::endl; d_tesla_keys.insert(std::pair>(TOW, key)); d_tesla_key_verified = true; d_last_verified_key_GST = d_receiver_time; } else if (num_of_hashes_needed > 0) { - LOG(WARNING) << "Galileo OSNMA:: TESLA key verification :: FAILED"; + LOG(WARNING) << "Galileo OSNMA: TESLA key verification :: FAILED"; + std::cerr << "Galileo OSNMA: TESLA key verification :: FAILED" << std::endl; if (d_flag_debug) { d_tesla_keys.insert(std::pair>(TOW, key)); @@ -1375,9 +1453,11 @@ void osnma_msg_receiver::remove_verified_tags() it = d_tags_awaiting_verify.erase(it); } else - ++it; + { + ++it; + } } - std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; + LOG(INFO) << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size(); } @@ -1394,11 +1474,11 @@ void osnma_msg_receiver::control_tags_awaiting_verify_size() while (d_tags_awaiting_verify.size() > 500) { auto it = d_tags_awaiting_verify.begin(); - LOG(WARNING) << "Galileo OSNMA: Tag verification :: DELETED tag due to exceeding buffer size. " - << "Tag Id= " << it->second.tag_id - << ", TOW=" << it->first - << ", ADKD=" << static_cast(it->second.ADKD) - << ", from satellite " << it->second.PRNa; + LOG(INFO) << "Galileo OSNMA: Tag verification :: DELETED tag due to exceeding buffer size. " + << "Tag Id= " << it->second.tag_id + << ", TOW=" << it->first + << ", ADKD=" << static_cast(it->second.ADKD) + << ", from satellite " << it->second.PRNa; d_tags_awaiting_verify.erase(it); } } @@ -1446,7 +1526,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) std::vector flxTags{}; std::string tempADKD; // MACLT verification - for (uint8_t i = 0; i < mack.tag_and_info.size(); i++) + for (size_t i = 0; i < mack.tag_and_info.size(); i++) { tempADKD = applicable_sequence[i + 1]; if (tempADKD == "FLX") @@ -1463,7 +1543,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) if (flxTags.empty()) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD matches MAC Look-up table."; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD matches MAC Look-up table."; return true; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD @@ -1474,7 +1554,7 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) m[3] = static_cast((d_GST_Sf & 0x0000FF00) >> 8); m[4] = static_cast(d_GST_Sf & 0x000000FF); // Case tags flexible - Eq. 21 ICD - for (uint8_t i = 0; i < flxTags.size(); i++) + for (size_t i = 0; i < flxTags.size(); i++) { m[2 * i + 5] = mack.tag_and_info[flxTags[i]].tag_info.PRN_d; m[2 * i + 6] = mack.tag_and_info[flxTags[i]].tag_info.ADKD << 4 | @@ -1484,11 +1564,11 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) std::vector mac; if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { - mac = d_crypto->computeHMAC_SHA_256(applicable_key, m); + mac = d_crypto->compute_HMAC_SHA_256(applicable_key, m); } else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES { - mac = d_crypto->computeCMAC_AES(applicable_key, m); + mac = d_crypto->compute_CMAC_AES(applicable_key, m); } // Truncate the twelve MSBits and compare with received MACSEQ uint16_t mac_msb = 0; @@ -1499,10 +1579,9 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) uint16_t computed_macseq = (mac_msb & 0xFFF0) >> 4; if (computed_macseq == mack.header.macseq) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; return true; } - else { LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: FLX tags verification failed"; @@ -1511,14 +1590,14 @@ bool osnma_msg_receiver::verify_macseq(const MACK_message& mack) } -bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) +bool osnma_msg_receiver::tag_has_nav_data_available(const Tag& t) const { auto prn_it = d_satellite_nav_data.find(t.PRN_d); if (prn_it != d_satellite_nav_data.end()) { // PRN was found, check if TOW exists in inner map //LOG(INFO) << "Galileo OSNMA: hasData = true " << std::endl; - std::map& tow_map = prn_it->second; + std::map tow_map = prn_it->second; auto tow_it = tow_map.find(t.TOW - 30); if (tow_it != tow_map.end()) { @@ -1540,7 +1619,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) } -bool osnma_msg_receiver::tag_has_key_available(Tag& t) +bool osnma_msg_receiver::tag_has_key_available(const Tag& t) const { // check adkd of tag // if adkd = 0 or 4 => look for d_tesla_keys[t.TOW+30] @@ -1570,9 +1649,8 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t) } -std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_needed, std::vector key, uint32_t GST_SFi, const uint8_t lk_bytes) +std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_needed, const std::vector& key, uint32_t GST_SFi, const uint8_t lk_bytes) const { - auto start = std::chrono::high_resolution_clock::now(); std::vector K_II = key; std::vector K_I; // result of the recursive hash operations std::vector msg; @@ -1598,11 +1676,11 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede std::vector hash; if (d_osnma_data.d_dsm_kroot_message.hf == 0) // Table 8. { - hash = d_crypto->computeSHA256(msg); + hash = d_crypto->compute_SHA_256(msg); } else if (d_osnma_data.d_dsm_kroot_message.hf == 2) { - hash = d_crypto->computeSHA3_256(msg); + hash = d_crypto->compute_SHA3_256(msg); } else { @@ -1624,20 +1702,26 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede // check that the final time matches the Kroot time bool check; if (!d_tesla_key_verified) - check = GST_SFi + 30 == d_GST_0 - 30; + { + check = GST_SFi + 30 == d_GST_0 - 30; + } else - check = GST_SFi + 30 == d_last_verified_key_GST; + { + check = GST_SFi + 30 == d_last_verified_key_GST; + } if (!check) - LOG(WARNING) << "Galileo OSNMA: TESLA verification error. Kroot time mismatch!"; // ICD. Eq. 18 + { + LOG(WARNING) << "Galileo OSNMA: TESLA key chain verification error: KROOT time mismatch!"; // ICD. Eq. 18 + std::cerr << "Galileo OSNMA: TESLA key chain verification error: KROOT time mismatch!" << std::endl; + } else - LOG(INFO) << "Galileo OSNMA: TESLA verification. Kroot time matches!"; // ICD. Eq. 18 - // compare computed current key against received key - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = end - start; -// LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds."; + { + LOG(INFO) << "Galileo OSNMA: TESLA key chain verification: KROOT time matches."; // ICD. Eq. 18 + } return K_II; } + /** * @brief Verifies the MAC sequence of a received MACK message. * @@ -1650,11 +1734,16 @@ std::vector osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede */ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_message& mack) { - std::vector verified_tags {}; + std::vector verified_tags{}; // MACSEQ verification - d_GST_Sf = d_receiver_time - 30; // time of the start of SF containing MACSEQ // TODO buffer with times? since out of debug not every 30 s a Sf is necessarily received.. - std::vector applicable_key = d_tesla_keys[mack.TOW + 30]; // current tesla key ie transmitted in the next subframe + d_GST_Sf = d_receiver_time - 30; // time of the start of SF containing MACSEQ // TODO buffer with times? since out of debug not every 30 s a Sf is necessarily received. + std::vector applicable_key; + const auto key_it = d_tesla_keys.find(mack.TOW + 30); // current tesla key ie transmitted in the next subframe + if (key_it != d_tesla_keys.cend()) + { + applicable_key = key_it->second; + } std::vector sq1{}; std::vector sq2{}; std::vector applicable_sequence; @@ -1682,7 +1771,7 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ std::vector flxTags{}; std::string tempADKD; // MACLT verification - for (uint8_t i = 0; i < mack.tag_and_info.size(); i++) + for (size_t i = 0; i < mack.tag_and_info.size(); i++) { tempADKD = applicable_sequence[i + 1]; if (tempADKD == "FLX") @@ -1692,23 +1781,23 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ else if (mack.tag_and_info[i].tag_info.ADKD == std::stoi(applicable_sequence[i + 1])) { // fill index of tags failed - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD match against MAC Look-up table for " - "Tag=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << mack.tag_and_info[i].tag << std::dec; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: ADKD match against MAC Look-up table for Tag=0x" + << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << mack.tag_and_info[i].tag << std::dec; verified_tags.push_back(mack.tag_and_info[i]); } else { // discard tag - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table for " - "Tag=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase - << mack.tag_and_info[i].tag << std::dec; + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: ADKD mismatch against MAC Look-up table for Tag=0x" + << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << mack.tag_and_info[i].tag << std::dec; } } if (flxTags.empty() /*TODO add check d_flag_check_mackseq_fixed_tags*/) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: No FLX tags to verify."; + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: No FLX tags to verify."; return verified_tags; } // Fixed as well as FLX Tags share first part - Eq. 22 ICD @@ -1719,7 +1808,7 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ m[3] = static_cast((d_GST_Sf & 0x0000FF00) >> 8); m[4] = static_cast(d_GST_Sf & 0x000000FF); // Case tags flexible - Eq. 21 ICD - for (uint8_t i = 0; i < flxTags.size(); i++) + for (size_t i = 0; i < flxTags.size(); i++) { m[2 * i + 5] = mack.tag_and_info[flxTags[i]].tag_info.PRN_d; m[2 * i + 6] = mack.tag_and_info[flxTags[i]].tag_info.ADKD << 4 | @@ -1729,11 +1818,11 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ std::vector mac; if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { - mac = d_crypto->computeHMAC_SHA_256(applicable_key, m); + mac = d_crypto->compute_HMAC_SHA_256(applicable_key, m); } else if (d_osnma_data.d_dsm_kroot_message.mf == 1) // C: CMAC-AES { - mac = d_crypto->computeCMAC_AES(applicable_key, m); + mac = d_crypto->compute_CMAC_AES(applicable_key, m); } // Truncate the twelve MSBits and compare with received MACSEQ uint16_t mac_msb = 0; @@ -1744,10 +1833,10 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ uint16_t computed_macseq = (mac_msb & 0xFFF0) >> 4; if (computed_macseq == mack.header.macseq) { - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; - for (uint8_t i = 0; i < flxTags.size(); i++) + LOG(INFO) << "Galileo OSNMA: MACSEQ verification :: SUCCESS :: FLX tags verification OK"; + for (uint8_t flxTag : flxTags) { - verified_tags.push_back(mack.tag_and_info[flxTags[i]]); + verified_tags.push_back(mack.tag_and_info[flxTag]); } return verified_tags; } @@ -1757,5 +1846,4 @@ std::vector osnma_msg_receiver::verify_macseq_new(const MACK_ LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: FAILURE :: FLX tags verification failed"; return verified_tags; } - } diff --git a/src/core/libs/osnma_msg_receiver.h b/src/core/libs/osnma_msg_receiver.h index ad397cc2f..7ecbe7428 100644 --- a/src/core/libs/osnma_msg_receiver.h +++ b/src/core/libs/osnma_msg_receiver.h @@ -3,14 +3,15 @@ * \brief GNU Radio block that processes Galileo OSNMA data received from * Galileo E1B telemetry blocks. After successful decoding, sends the content to * the PVT block. - * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * \author Carles Fernandez-Prades, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -18,20 +19,23 @@ #ifndef GNSS_SDR_OSNMA_MSG_RECEIVER_H #define GNSS_SDR_OSNMA_MSG_RECEIVER_H -#define FRIEND_TEST(test_case_name, test_name)\ -friend class test_case_name##_##test_name##_Test + +#define FRIEND_TEST(test_case_name, test_name) \ + friend class test_case_name##_##test_name##_Test #include "galileo_inav_message.h" // for OSNMA_msg #include "gnss_block_interface.h" // for gnss_shared_ptr #include "gnss_sdr_make_unique.h" // for std::make:unique in C++11 -#include "osnma_data.h" // for OSNMA_data -#include -#include // for gr::block -#include // for pmt::pmt_t -#include // for std::array -#include // for std::shared_ptr -#include -#include +#include "osnma_data.h" // for OSNMA_data structures +#include // for gr::block +#include // for pmt::pmt_t +#include // for std::array +#include // for uint8_t +#include // for std::time_t +#include // for std::map, std::multimap +#include // for std::shared_ptr +#include // for std::string +#include // for std::vector /** \addtogroup Core * \{ */ @@ -73,58 +77,69 @@ private: void read_mack_header(); void read_mack_body(); void process_mack_message(); - void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData &data); + void add_satellite_data(uint32_t SV_ID, uint32_t TOW, const NavData& data); void remove_verified_tags(); void control_tags_awaiting_verify_size(); - std::vector build_message(const Tag& tag); - std::vector hash_chain(uint32_t num_of_hashes_needed, std::vector key, uint32_t GST_SFi, const uint8_t lk_bytes); - std::vector compute_base_leaf(const DSM_PKR_message& dsm_pkr_message) const; - std::vector compute_merke_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const; - std::vector verify_macseq_new(const MACK_message& mack); void display_data(); - bool verify_tag(MACK_tag_and_info tag_and_info, OSNMA_data applicable_OSNMA, uint8_t tag_position, const std::vector& applicable_key, NavData applicable_NavData); + bool verify_tesla_key(std::vector& key, uint32_t TOW); - bool verify_tag(Tag& tag); - bool is_next_subframe(); - bool tag_has_nav_data_available(Tag& t); - bool tag_has_key_available(Tag& t); + bool verify_tag(const Tag& tag) const; + bool tag_has_nav_data_available(const Tag& t) const; + bool tag_has_key_available(const Tag& t) const; bool verify_macseq(const MACK_message& mack); - bool verify_dsm_pkr(DSM_PKR_message message); + bool verify_dsm_pkr(const DSM_PKR_message& message) const; - enum tags_to_verify{all,utc,slow_eph, eph, none}; - tags_to_verify d_tags_allowed{tags_to_verify::all}; - std::map> d_satellite_nav_data; // map holding NavData sorted by SVID (first key) and TOW (second key). - std::map> d_tesla_keys; // tesla keys over time, sorted by TOW + std::vector get_merkle_tree_leaves(const DSM_PKR_message& dsm_pkr_message) const; + std::vector compute_merkle_root(const DSM_PKR_message& dsm_pkr_message, const std::vector& m_i) const; + std::vector build_message(const Tag& tag) const; + std::vector hash_chain(uint32_t num_of_hashes_needed, const std::vector& key, uint32_t GST_SFi, const uint8_t lk_bytes) const; + std::vector verify_macseq_new(const MACK_message& mack); + + std::map> d_satellite_nav_data; // map holding NavData sorted by SVID (first key) and TOW (second key). + std::map> d_tesla_keys; // tesla keys over time, sorted by TOW + std::multimap d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW + + std::vector d_tags_to_verify{0, 4, 12}; std::vector d_macks_awaiting_MACSEQ_verification; - std::multimap d_tags_awaiting_verify; // container with tags to verify from arbitrary SVIDs, sorted by TOW - std::unique_ptr d_dsm_reader; // osnma parameters parser - std::unique_ptr d_crypto; // access to cryptographic functions - std::unique_ptr d_helper; - std::array, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself. + std::array, 16> d_dsm_message{}; // structure for recording DSM blocks, when filled it sends them to parse and resets itself. std::array, 16> d_dsm_id_received{}; std::array d_number_of_blocks{}; - std::array d_mack_message{}; // C: 480 b + std::array d_mack_message{}; // C: 480 b + + std::unique_ptr d_dsm_reader; // osnma parameters parser + std::unique_ptr d_crypto; // access to cryptographic functions + std::unique_ptr d_helper; OSNMA_data d_osnma_data{}; + + enum tags_to_verify + { + all, + utc, + slow_eph, + eph, + none + }; + tags_to_verify d_tags_allowed{tags_to_verify::all}; + std::time_t d_receiver_time{0}; + + uint32_t d_GST_Sf{}; // C: used for MACSEQ and Tesla Key verification TODO need really to be global var? + uint32_t d_last_verified_key_GST{0}; + uint32_t d_GST_0{}; + uint32_t d_GST_SIS{}; + + uint8_t d_Lt_min{}; // minimum equivalent tag length + uint8_t d_Lt_verified_eph{0}; // verified tag bits - ephemeris + uint8_t d_Lt_verified_utc{0}; // verified tag bits - timing + uint8_t const d_T_L{30}; // s RG Section 2.1 + uint8_t const d_delta_COP{30}; // s SIS ICD Table 14 + bool d_new_data{false}; bool d_public_key_verified{false}; bool d_kroot_verified{false}; bool d_tesla_key_verified{false}; bool d_flag_debug{false}; - uint32_t d_GST_Sf {}; // C: used for MACSEQ and Tesla Key verification TODO need really to be global var? - uint32_t d_last_verified_key_GST{0}; - uint32_t d_GST_0 {}; - uint32_t d_GST_SIS {}; - std::time_t d_receiver_time {0}; - uint8_t d_Lt_min {}; // minimum equivalent tag length - uint8_t d_Lt_verified_eph {0}; // verified tag bits - ephemeris - uint8_t d_Lt_verified_utc {0}; // verified tag bits - timing - uint8_t const d_T_L{30}; // s RG Section 2.1 - uint8_t const d_delta_COP{30}; // s SIS ICD Table 14 - - std::vector d_tags_to_verify{0,4,12}; - std::vector d_validated_key{}; // Provide access to inner functions to Gtest FRIEND_TEST(OsnmaMsgReceiverTest, TeslaKeyVerification); diff --git a/src/core/system_parameters/beidou_dnav_navigation_message.cc b/src/core/system_parameters/beidou_dnav_navigation_message.cc index 0444a3555..76a621de9 100644 --- a/src/core/system_parameters/beidou_dnav_navigation_message.cc +++ b/src/core/system_parameters/beidou_dnav_navigation_message.cc @@ -353,7 +353,7 @@ int32_t Beidou_Dnav_Navigation_Message::d1_subframe_decoder(std::string const& s d_DeltaT_LSF = static_cast(read_navigation_signed(subframe_bits, D1_DELTA_T_LSF)); i_WN_LSF = static_cast(read_navigation_signed(subframe_bits, D1_WN_LSF)); d_A0UTC = static_cast(read_navigation_signed(subframe_bits, D1_A0UTC)); - d_A0UTC = d_A0GPS * D1_A0GPS_LSB; + d_A0UTC = d_A0UTC * D1_A0UTC_LSB; d_A1UTC = static_cast(read_navigation_signed(subframe_bits, D1_A1UTC)); d_A1UTC = d_A1UTC * D1_A1UTC_LSB; diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index fba8d643e..9ff183ed3 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -133,137 +133,342 @@ bool Gnss_Crypto::have_public_key() const } -std::vector Gnss_Crypto::convert_from_hex_str(const std::string& input) const +bool Gnss_Crypto::store_public_key(const std::string& pubKeyFilePath) const { - std::vector result; - - // Iterate over the input string in pairs - for (size_t i = 0; i < input.length(); i += 2) + if (!have_public_key()) { - // Extract two hexadecimal characters from the input string - std::string hexByte = input.substr(i, 2); - - // Convert the hexadecimal string to an integer value - auto value = static_cast(std::stoul(hexByte, nullptr, 16)); - - // Append the value to the result vector - result.push_back(value); + return false; + } + std::ofstream pubKeyFile(pubKeyFilePath, std::ios::binary); + if (!pubKeyFile.is_open()) + { + LOG(WARNING) << "Unable to open file for storing the Public Key: " << pubKeyFilePath; + return false; + } +#if USE_GNUTLS_FALLBACK + gnutls_datum_t pem_data; +#if HAVE_GNUTLS_PUBKEY_EXPORT2 + int ret = gnutls_pubkey_export2(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data); +#else + size_t output_stata_size; + int ret = gnutls_pubkey_export(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data, &output_stata_size); +#endif + if (ret != GNUTLS_E_SUCCESS) + { + LOG(WARNING) << "GnuTLS: Failed to export public key: " << gnutls_strerror(ret); + return false; } - return result; + pubKeyFile.write((const char*)pem_data.data, pem_data.size); + pubKeyFile.close(); + gnutls_free(pem_data.data); +#else // OpenSSL + BIO* bio = BIO_new(BIO_s_mem()); + if (!bio) + { + LOG(WARNING) << "OpenSSL: Failed to create BIO"; + return false; + } +#if USE_OPENSSL_3 + if (!PEM_write_bio_PUBKEY(bio, d_PublicKey)) +#else // OpenSSL 1.x + if (!PEM_write_bio_EC_PUBKEY(bio, d_PublicKey)) +#endif + { + LOG(WARNING) << "OpenSSL: Failed to write public key to BIO"; + BIO_free(bio); + return false; + } + + char* bio_data; + auto bio_len = BIO_get_mem_data(bio, &bio_data); + if (bio_len <= 0) + { + LOG(WARNING) << "OpenSSL: Failed to get BIO data"; + BIO_free(bio); + return false; + } + + pubKeyFile.write(bio_data, bio_len); + pubKeyFile.close(); + BIO_free(bio); +#endif + return true; } -void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) +bool Gnss_Crypto::verify_signature_ecdsa_p256(const std::vector& message, const std::vector& signature) const { - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(merkleFilePath.c_str()); - if (!result) + std::vector digest = this->compute_SHA_256(message); + if (!have_public_key()) { - // XML file not found - // If it was not the default, maybe it is a configuration error, warn user - if (merkleFilePath != MERKLEFILE_DEFAULT) - { - LOG(INFO) << "File " << merkleFilePath << " not found"; - } - // fill default values - d_x_4_0 = convert_from_hex_str("832E15EDE55655EAC6E399A539477B7C034CCE24C3C93FFC904ACD9BF842F04E"); - d_x_3_1 = convert_from_hex_str("84DE3669E6DA551292979E5B8D045787FA967C57CC23638A30237614EDD9171A"); - d_x_2_1 = convert_from_hex_str("DE73D209E4C5BCDC34CD117F2FE40FD08B110009997AD2B3291D3A2CF29943F9"); - d_x_1_1 = convert_from_hex_str("6AAFDE28017BF0744D42819CE40E3A0CDA1ECA3F7A4EA67E134E7AA714C1E843"); - d_x_0_1 = convert_from_hex_str("941BD34EA7DF668B6FC5BE75C1D93464D109BC615CB52C8124847FAFB09CBB2B"); - return; + LOG(WARNING) << "Galileo OSNMA KROOT verification error: Public key is not available"; + return false; } - try + bool success = false; +#if USE_GNUTLS_FALLBACK +#if HAVE_GNUTLS_SIGN_ECDSA_SHA256 + // Convert signature to DER format + std::vector der_sig; + if (!convert_raw_to_der_ecdsa(signature, der_sig)) { - pugi::xml_node root = doc.child("signalData"); - pugi::xml_node header = root.child("header"); - pugi::xml_node body = root.child("body"); - - // Accessing data from the header - pugi::xml_node galHeader = header.child("GAL-header"); - pugi::xml_node source = galHeader.child("source").child("GAL-EXT-GOC-SC-GLAd"); - pugi::xml_node destination = galHeader.child("destination").child("GAL-EXT-GOC-SC-GLAd"); - std::string issueDate = galHeader.child("issueDate").text().get(); - std::string signalVersion = galHeader.child("signalVersion").text().get(); - std::string dataVersion = galHeader.child("dataVersion").text().get(); - - LOG(INFO) << "OSNMA Merkletree - Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element"); - LOG(INFO) << "OSNMA Merkletree - Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element"); - LOG(INFO) << "OSNMA Merkletree - Issue Date: " << issueDate; - LOG(INFO) << "OSNMA Merkletree - Signal Version: " << signalVersion; - LOG(INFO) << "OSNMA Merkletree - Data Version: " << dataVersion; - - // Accessing data from the body - pugi::xml_node merkleTree = body.child("MerkleTree"); - - int n = std::stoi(merkleTree.child_value("N")); - std::string hashFunction = merkleTree.child_value("HashFunction"); - - LOG(INFO) << "OSNMA Merkletree - N: " << n; - LOG(INFO) << "OSNMA Merkletree - Hash Function: " << hashFunction; - - for (pugi::xml_node publicKey : merkleTree.children("PublicKey")) - { - int i = std::stoi(publicKey.child_value("i")); - std::string pkid = publicKey.child_value("PKID"); - int lengthInBits = std::stoi(publicKey.child_value("lengthInBits")); - std::string point = publicKey.child_value("point"); - std::string pkType = publicKey.child_value("PKType"); - - LOG(INFO) << "OSNMA Merkletree - Public Key: " << i; - LOG(INFO) << "OSNMA Merkletree - PKID: " << pkid; - LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits; - LOG(INFO) << "OSNMA Merkletree - Point: " << point; - LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType; - } - for (pugi::xml_node treeNode : merkleTree.children("TreeNode")) - { - int j = std::stoi(treeNode.child_value("j")); - int i = std::stoi(treeNode.child_value("i")); - int lengthInBits = std::stoi(treeNode.child_value("lengthInBits")); - LOG(INFO) << "OSNMA Merkletree - Node length (bits): " << lengthInBits; - std::string x_ji = treeNode.child_value("x_ji"); - LOG(INFO) << "OSNMA Merkletree - Size string (bytes): " << x_ji.size(); - LOG(INFO) << "OSNMA Merkletree - m_" << j << "_" << i << " = " << x_ji; - if (j == 4 && i == 0) - { - d_x_4_0 = convert_from_hex_str(x_ji); - } - if (j == 3 && i == 1) - { - d_x_3_1 = convert_from_hex_str(x_ji); - } - if (j == 2 && i == 1) - { - d_x_2_1 = convert_from_hex_str(x_ji); - } - if (j == 1 && i == 1) - { - d_x_1_1 = convert_from_hex_str(x_ji); - } - if (j == 0 && i == 1) - { - d_x_0_1 = convert_from_hex_str(x_ji); - } - } + LOG(WARNING) << "Failed to convert raw ECDSA signature to DER format"; + return false; } - catch (const std::exception& e) + + // Prepare the digest datum + gnutls_datum_t digest_data = {const_cast(digest.data()), static_cast(digest.size())}; + gnutls_datum_t der_sig_data = {der_sig.data(), static_cast(der_sig.size())}; + + // Verify the DER-encoded signature + int ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &digest_data, &der_sig_data); + success = (ret >= 0); + if (success) { - std::cerr << "Exception raised reading the " << merkleFilePath << " file: " << e.what() << '\n'; - d_x_4_0 = convert_from_hex_str("832E15EDE55655EAC6E399A539477B7C034CCE24C3C93FFC904ACD9BF842F04E"); - d_x_3_1 = convert_from_hex_str("84DE3669E6DA551292979E5B8D045787FA967C57CC23638A30237614EDD9171A"); - d_x_2_1 = convert_from_hex_str("DE73D209E4C5BCDC34CD117F2FE40FD08B110009997AD2B3291D3A2CF29943F9"); - d_x_1_1 = convert_from_hex_str("6AAFDE28017BF0744D42819CE40E3A0CDA1ECA3F7A4EA67E134E7AA714C1E843"); - d_x_0_1 = convert_from_hex_str("941BD34EA7DF668B6FC5BE75C1D93464D109BC615CB52C8124847FAFB09CBB2B"); - return; + LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully"; } - std::cout << "OSNMA Merkle Tree successfully read from file " << merkleFilePath << std::endl; - LOG(INFO) << "OSNMA Merkle Tree successfully read from file " << merkleFilePath; + else + { + LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret); + } +#else + if (signature.empty()) + { + // do nothing + } +#endif +#else // OpenSSL +#if USE_OPENSSL_3 + EVP_PKEY_CTX* ctx; + ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); + bool do_operation = true; + + if (!ctx) + { + do_operation = false; + } + // convert raw signature into DER format + size_t half_size = signature.size() / 2; + std::vector raw_r(signature.begin(), signature.begin() + half_size); + std::vector raw_s(signature.begin() + half_size, signature.end()); + + // Convert raw R and S to BIGNUMs + BIGNUM* r = BN_bin2bn(raw_r.data(), raw_r.size(), nullptr); + BIGNUM* s = BN_bin2bn(raw_s.data(), raw_s.size(), nullptr); + + ECDSA_SIG* sig = ECDSA_SIG_new(); + if (r == nullptr || s == nullptr || sig == nullptr) + { + LOG(WARNING) << "OpenSSL: Failed to allocate memory for BIGNUMs or ECDSA_SIG"; + return false; + } + + if (ECDSA_SIG_set0(sig, r, s) != 1) + { + LOG(WARNING) << "OpenSSL: Failed to set R and S values in ECDSA_SIG"; + ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it is no longer needed + return false; + } + + std::vector derSignature; + unsigned char* derSig = nullptr; + int derSigLength = i2d_ECDSA_SIG(sig, &derSig); + + if (derSigLength <= 0) + { + LOG(WARNING) << "OpenSSL: Failed to convert ECDSA_SIG to DER format"; + return false; + } + + derSignature.assign(derSig, derSig + derSigLength); + + if (EVP_PKEY_verify_init(ctx) <= 0) + { + do_operation = false; + } + if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) + { + do_operation = false; + } + int verification = 0; + if (do_operation) + { + verification = EVP_PKEY_verify(ctx, derSignature.data(), derSignature.size(), digest.data(), digest.size()); + } + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(derSig); + ECDSA_SIG_free(sig); + if (verification == 1) + { + success = true; + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; + } + else + { + uint64_t errCode = ERR_get_error(); + char* err = ERR_error_string(errCode, nullptr); + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err; + } +#else // OpenSSL 1.x + std::vector der_sig; + if (!convert_raw_to_der_ecdsa(signature, der_sig)) + { + LOG(WARNING) << "OpenSSL: Failed to convert raw ECDSA signature to DER format"; + return false; + } + int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, der_sig.data(), static_cast(der_sig.size()), d_PublicKey); + if (verification == 1) + { + success = true; + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; + } + else if (verification == 0) + { + LOG(WARNING) << "OpenSSL: invalid signature found when verifying message"; + } + else + { + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; + } +#endif +#endif + return success; } -std::vector Gnss_Crypto::computeSHA256(const std::vector& input) const +bool Gnss_Crypto::verify_signature_ecdsa_p521(const std::vector& message, const std::vector& signature) const +{ + if (!have_public_key()) + { + LOG(WARNING) << "Galileo OSNMA KROOT verification error: Public key is not available"; + return false; + } + + if (signature.size() != 132) + { + LOG(WARNING) << "Invalid signature length for P-521. Expected 132 bytes, got " << signature.size(); + return false; + } + + std::vector der_sig; + if (!convert_raw_to_der_ecdsa(signature, der_sig)) + { + LOG(WARNING) << "Failed to convert raw ECDSA signature to DER format"; + return false; + } + bool success = false; +#if USE_GNUTLS_FALLBACK +#if HAVE_GNUTLS_SIGN_ECDSA_SHA512 + std::vector digest(64); + gnutls_hash_hd_t hash; + int ret = gnutls_hash_init(&hash, GNUTLS_DIG_SHA512); + if (ret != GNUTLS_E_SUCCESS) + { + LOG(WARNING) << "GnuTLS: gnutls_hash_init failed: " << gnutls_strerror(ret); + return false; + } + + gnutls_hash(hash, message.data(), message.size()); + gnutls_hash_deinit(hash, digest.data()); + + gnutls_datum_t digest_data = {digest.data(), static_cast(digest.size())}; + gnutls_datum_t signature_data = {der_sig.data(), static_cast(der_sig.size())}; + + // Verify the ECDSA signature + ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA512, 0, &digest_data, &signature_data); + + if (ret >= 0) + { + LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully"; + success = true; + } + else + { + LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret); + } +#else + if (message.empty()) + { + // do nothing + } +#endif +#else // OpenSSL + // Compute SHA-512 hash of the message + std::vector digest(SHA512_DIGEST_LENGTH); + if (!EVP_Digest(message.data(), message.size(), digest.data(), nullptr, EVP_sha512(), nullptr)) + { + LOG(WARNING) << "OpenSSL: EVP_Digest failed"; + return false; + } +#if USE_OPENSSL_3 + // Verify the signature + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); + if (pctx == nullptr) + { + LOG(WARNING) << "OpenSSL: EVP_PKEY_CTX_new failed"; + return false; + } + + if (EVP_PKEY_verify_init(pctx) <= 0) + { + LOG(WARNING) << "OpenSSL: EVP_PKEY_verify_init failed"; + EVP_PKEY_CTX_free(pctx); + return false; + } + + if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha512()) <= 0) + { + LOG(WARNING) << "OpenSSL: EVP_PKEY_CTX_set_signature_md failed"; + EVP_PKEY_CTX_free(pctx); + return false; + } + + int verification = EVP_PKEY_verify(pctx, der_sig.data(), der_sig.size(), digest.data(), digest.size()); + EVP_PKEY_CTX_free(pctx); + + if (verification == 1) + { + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; + success = true; + } + else if (verification == 0) + { + LOG(WARNING) << "OpenSSL: invalid signature found when verifying message"; + } + else + { + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; + } +#else // OpenSSL 1.x + const unsigned char* sig_ptr = der_sig.data(); + ECDSA_SIG* ecdsa_sig = d2i_ECDSA_SIG(nullptr, &sig_ptr, der_sig.size()); + if (ecdsa_sig == nullptr) + { + LOG(WARNING) << "OpenSSL: d2i_ECDSA_SIG failed"; + return false; + } + int verification = ECDSA_do_verify(digest.data(), digest.size(), ecdsa_sig, d_PublicKey); + ECDSA_SIG_free(ecdsa_sig); + if (verification == 1) + { + LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; + success = true; + } + else if (verification == 0) + { + LOG(WARNING) << "OpenSSL: invalid signature found when verifying message"; + } + else + { + LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; + } +#endif +#endif + return success; +} + + +std::vector Gnss_Crypto::compute_SHA_256(const std::vector& input) const { std::vector output(32); // SHA256 hash size #if USE_GNUTLS_FALLBACK @@ -308,7 +513,7 @@ std::vector Gnss_Crypto::computeSHA256(const std::vector& inpu } -std::vector Gnss_Crypto::computeSHA3_256(const std::vector& input) const +std::vector Gnss_Crypto::compute_SHA3_256(const std::vector& input) const { std::vector output(32); // SHA256 hash size #if USE_GNUTLS_FALLBACK @@ -320,6 +525,11 @@ std::vector Gnss_Crypto::computeSHA3_256(const std::vector& in gnutls_hash_output(hashHandle, output_aux.data()); output = output_aux; gnutls_hash_deinit(hashHandle, output_aux.data()); +#else + if (input.empty()) + { + // do nothing + } #endif #else // OpenSSL #if USE_OPENSSL_3 || USE_OPENSSL_111 @@ -342,7 +552,7 @@ std::vector Gnss_Crypto::computeSHA3_256(const std::vector& in } -std::vector Gnss_Crypto::computeHMAC_SHA_256(const std::vector& key, const std::vector& input) const +std::vector Gnss_Crypto::compute_HMAC_SHA_256(const std::vector& key, const std::vector& input) const { std::vector output(32); #if USE_GNUTLS_FALLBACK @@ -430,7 +640,7 @@ std::vector Gnss_Crypto::computeHMAC_SHA_256(const std::vector } -std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& key, const std::vector& input) const +std::vector Gnss_Crypto::compute_CMAC_AES(const std::vector& key, const std::vector& input) const { std::vector output(16); #if USE_GNUTLS_FALLBACK @@ -441,7 +651,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke int ret = gnutls_hmac_init(&hmac, GNUTLS_MAC_AES_CMAC_128, key.data(), key.size()); if (ret != GNUTLS_E_SUCCESS) { - LOG(INFO) << "OSNMA CMAC-AES: gnutls_hmac_init failed: " << gnutls_strerror(ret); + LOG(WARNING) << "OSNMA CMAC-AES: gnutls_hmac_init failed: " << gnutls_strerror(ret); return output; } @@ -449,7 +659,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke ret = gnutls_hmac(hmac, input.data(), input.size()); if (ret != GNUTLS_E_SUCCESS) { - LOG(INFO) << "OSNMA CMAC-AES: gnutls_hmac failed: " << gnutls_strerror(ret); + LOG(WARNING) << "OSNMA CMAC-AES: gnutls_hmac failed: " << gnutls_strerror(ret); gnutls_hmac_deinit(hmac, nullptr); return output; } @@ -478,14 +688,14 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke EVP_MAC* mac = EVP_MAC_fetch(nullptr, "CMAC", nullptr); if (!mac) { - LOG(INFO) << "OSNMA CMAC-AES: Failed to fetch CMAC"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to fetch CMAC"; return output; } EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); if (!ctx) { - LOG(INFO) << "OSNMA CMAC-AES: Failed to create CMAC context"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to create CMAC context"; return output; } @@ -499,7 +709,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke { EVP_MAC_CTX_free(ctx); EVP_MAC_free(mac); - LOG(INFO) << "OSNMA CMAC-AES: Failed to initialize CMAC context"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to initialize CMAC context"; return output; } @@ -508,7 +718,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke { EVP_MAC_CTX_free(ctx); EVP_MAC_free(mac); - LOG(INFO) << "OSNMA CMAC-AES: Failed to update CMAC context"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to update CMAC context"; return output; } @@ -517,7 +727,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke { EVP_MAC_CTX_free(ctx); EVP_MAC_free(mac); - LOG(INFO) << "OSNMA CMAC-AES: Failed to finalize CMAC"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to finalize CMAC"; return output; } @@ -534,14 +744,14 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke CMAC_CTX* cmacCtx = CMAC_CTX_new(); if (!cmacCtx) { - LOG(INFO) << "OSNMA CMAC-AES: Failed to create CMAC context"; + LOG(WARNING) << "OSNMA CMAC-AES: Failed to create CMAC context"; return output; } // Initialize the CMAC context with the key and cipher if (CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr) != 1) { - LOG(INFO) << "OSNMA CMAC-AES: MAC_Init failed"; + LOG(WARNING) << "OSNMA CMAC-AES: MAC_Init failed"; CMAC_CTX_free(cmacCtx); return output; } @@ -549,7 +759,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke // Compute the CMAC if (CMAC_Update(cmacCtx, input.data(), input.size()) != 1) { - LOG(INFO) << "OSNMA CMAC-AES: CMAC_Update failed"; + LOG(WARNING) << "OSNMA CMAC-AES: CMAC_Update failed"; CMAC_CTX_free(cmacCtx); return output; } @@ -557,7 +767,7 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke // Finalize the CMAC computation and retrieve the output if (CMAC_Final(cmacCtx, output.data(), &mac_length) != 1) { - LOG(INFO) << "OSNMA CMAC-AES: CMAC_Final failed"; + LOG(WARNING) << "OSNMA CMAC-AES: CMAC_Final failed"; CMAC_CTX_free(cmacCtx); return output; } @@ -573,6 +783,214 @@ std::vector Gnss_Crypto::computeCMAC_AES(const std::vector& ke } +std::vector Gnss_Crypto::get_public_key() const +{ + if (!have_public_key()) + { + return {}; + } +#if USE_GNUTLS_FALLBACK + gnutls_datum_t pem_data = {nullptr, 0}; +#if HAVE_GNUTLS_PUBKEY_EXPORT2 + int ret = gnutls_pubkey_export2(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data); +#else + size_t output_stata_size; + int ret = gnutls_pubkey_export(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data, &output_stata_size); +#endif + if (ret != GNUTLS_E_SUCCESS) + { + LOG(WARNING) << "GnuTLS: Failed to export public key to PEM format."; + return {}; + } + std::vector output(pem_data.data, pem_data.data + pem_data.size); + + // Free the allocated memory by gnutls_pubkey_export2 + gnutls_free(pem_data.data); +#else // OpenSSL + // Create a BIO for the memory buffer + BIO* mem = BIO_new(BIO_s_mem()); + if (!mem) + { + LOG(WARNING) << "OpenSSL: Failed to create BIO."; + return {}; + } +#if USE_OPENSSL_3 + if (!PEM_write_bio_PUBKEY(mem, d_PublicKey)) +#else // OpenSSL 1.x + if (!PEM_write_bio_EC_PUBKEY(mem, d_PublicKey)) +#endif + { + BIO_free(mem); + LOG(WARNING) << "OpenSSL: Failed to write public key to PEM format."; + return {}; + } + + // Get the length of the data in the BIO + BUF_MEM* mem_ptr; + BIO_get_mem_ptr(mem, &mem_ptr); + + // Copy the data from the BIO to a std::vector + std::vector output(mem_ptr->length); + memcpy(output.data(), mem_ptr->data, mem_ptr->length); + + // Clean up the BIO + BIO_free(mem); +#endif + return output; +} + + +std::vector Gnss_Crypto::get_merkle_root() const +{ + return d_x_4_0; +} + + +void Gnss_Crypto::set_public_key(const std::vector& publicKey) +{ +#if USE_GNUTLS_FALLBACK + gnutls_pubkey_t pubkey{}; + gnutls_datum_t pemDatum = {const_cast(publicKey.data()), static_cast(publicKey.size())}; + gnutls_pubkey_init(&pubkey); + int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM); + if (ret != GNUTLS_E_SUCCESS) + { + gnutls_pubkey_deinit(pubkey); + std::cerr << "GnuTLS: error setting the public key" << std::endl; + std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; + LOG(WARNING) << "GnuTLS: error setting the OSNMA public key: " << gnutls_strerror(ret); + return; + } + pubkey_copy(pubkey, &d_PublicKey); + gnutls_pubkey_deinit(pubkey); +#else // OpenSSL + BIO* bio = nullptr; + EVP_PKEY* pkey = nullptr; + bio = BIO_new_mem_buf(const_cast(publicKey.data()), publicKey.size()); + if (!bio) + { + LOG(WARNING) << "OpenSSL: Failed to create BIO for key."; + return; + } + + pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); + BIO_free(bio); + + if (!pkey) + { + LOG(WARNING) << "OpenSSL: error setting the OSNMA public key."; + return; + } +#if USE_OPENSSL_3 + if (!pubkey_copy(pkey, &d_PublicKey)) + { + return; + } +#else + EC_KEY* ec_pkey = EVP_PKEY_get1_EC_KEY(pkey); + if (!pubkey_copy(ec_pkey, &d_PublicKey)) + { + return; + } + EC_KEY_free(ec_pkey); +#endif // OpenSSL 1.x + EVP_PKEY_free(pkey); +#endif + LOG(INFO) << "OSNMA Public Key successfully set up."; +} + + +void Gnss_Crypto::set_merkle_root(const std::vector& v) +{ + d_x_4_0 = v; +} + + +void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) +{ + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(merkleFilePath.c_str()); + if (!result) + { + // XML file not found + // If it was not the default, maybe it is a configuration error, warn user + if (merkleFilePath != MERKLEFILE_DEFAULT && !merkleFilePath.empty()) + { + LOG(WARNING) << "File " << merkleFilePath << " not found"; + } + // fill default values + d_x_4_0 = convert_from_hex_str("832E15EDE55655EAC6E399A539477B7C034CCE24C3C93FFC904ACD9BF842F04E"); + return; + } + try + { + pugi::xml_node root = doc.child("signalData"); + pugi::xml_node header = root.child("header"); + pugi::xml_node body = root.child("body"); + + // Accessing data from the header + pugi::xml_node galHeader = header.child("GAL-header"); + pugi::xml_node source = galHeader.child("source").child("GAL-EXT-GOC-SC-GLAd"); + pugi::xml_node destination = galHeader.child("destination").child("GAL-EXT-GOC-SC-GLAd"); + std::string issueDate = galHeader.child("issueDate").text().get(); + std::string signalVersion = galHeader.child("signalVersion").text().get(); + std::string dataVersion = galHeader.child("dataVersion").text().get(); + + LOG(INFO) << "OSNMA Merkletree - Source: " << source.child_value("mission") << " - " << source.child_value("segment") << " - " << source.child_value("element"); + LOG(INFO) << "OSNMA Merkletree - Destination: " << destination.child_value("mission") << " - " << destination.child_value("segment") << " - " << destination.child_value("element"); + LOG(INFO) << "OSNMA Merkletree - Issue Date: " << issueDate; + LOG(INFO) << "OSNMA Merkletree - Signal Version: " << signalVersion; + LOG(INFO) << "OSNMA Merkletree - Data Version: " << dataVersion; + + // Accessing data from the body + pugi::xml_node merkleTree = body.child("MerkleTree"); + + int n = std::stoi(merkleTree.child_value("N")); + std::string hashFunction = merkleTree.child_value("HashFunction"); + + LOG(INFO) << "OSNMA Merkletree - N: " << n; + LOG(INFO) << "OSNMA Merkletree - Hash Function: " << hashFunction; + + for (pugi::xml_node publicKey : merkleTree.children("PublicKey")) + { + int i = std::stoi(publicKey.child_value("i")); + std::string pkid = publicKey.child_value("PKID"); + int lengthInBits = std::stoi(publicKey.child_value("lengthInBits")); + std::string point = publicKey.child_value("point"); + std::string pkType = publicKey.child_value("PKType"); + + LOG(INFO) << "OSNMA Merkletree - Public Key: " << i; + LOG(INFO) << "OSNMA Merkletree - PKID: " << pkid; + LOG(INFO) << "OSNMA Merkletree - Length in Bits: " << lengthInBits; + LOG(INFO) << "OSNMA Merkletree - Point: " << point; + LOG(INFO) << "OSNMA Merkletree - PK Type: " << pkType; + } + for (pugi::xml_node treeNode : merkleTree.children("TreeNode")) + { + int j = std::stoi(treeNode.child_value("j")); + int i = std::stoi(treeNode.child_value("i")); + int lengthInBits = std::stoi(treeNode.child_value("lengthInBits")); + LOG(INFO) << "OSNMA Merkletree - Node length (bits): " << lengthInBits; + std::string x_ji = treeNode.child_value("x_ji"); + LOG(INFO) << "OSNMA Merkletree - Size string (bytes): " << x_ji.size(); + LOG(INFO) << "OSNMA Merkletree - m_" << j << "_" << i << " = " << x_ji; + if (j == 4 && i == 0) + { + d_x_4_0 = convert_from_hex_str(x_ji); + } + } + } + catch (const std::exception& e) + { + LOG(INFO) << "Exception raised reading the " << merkleFilePath << " file: " << e.what(); + d_x_4_0 = convert_from_hex_str("832E15EDE55655EAC6E399A539477B7C034CCE24C3C93FFC904ACD9BF842F04E"); + return; + } + std::cout << "OSNMA Merkle Tree successfully read from file " << merkleFilePath << std::endl; + LOG(INFO) << "OSNMA Merkle Tree successfully read from file " << merkleFilePath; +} + + void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) { // Open the .pem file @@ -595,8 +1013,8 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) std::cerr << "GnuTLS: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl; - std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; - LOG(INFO) << "GnuTLS: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import"; + LOG(WARNING) << "GnuTLS: error reading the OSNMA Public Key from file " + << pemFilePath << ". Aborting import. Error " << gnutls_strerror(ret); return; } @@ -607,7 +1025,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) BIO* bio = BIO_new_mem_buf(const_cast(pemContent.c_str()), pemContent.length()); if (!bio) { - std::cerr << "OpenSSL: error creating a BIO object with data read from file " << pemFilePath << ". Aborting import" << std::endl; + LOG(WARNING) << "OpenSSL: error creating a BIO object with data read from file " << pemFilePath << ". Aborting import."; return; } #if USE_OPENSSL_3 @@ -619,7 +1037,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) if (d_PublicKey == nullptr) { std::cerr << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import" << std::endl; - LOG(INFO) << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import"; + LOG(WARNING) << "OpenSSL: error reading the OSNMA Public Key from file " << pemFilePath << ". Aborting import."; return; } #endif @@ -637,7 +1055,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { // CRT file not found // If it was not the default, maybe it is a configuration error - if (crtFilePath != CRTFILE_DEFAULT) + if (crtFilePath != CRTFILE_DEFAULT && !crtFilePath.empty()) { std::cerr << "File " << crtFilePath << " not found" << std::endl; } @@ -652,7 +1070,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) int ret = gnutls_x509_crt_import(cert, &buffer_datum, GNUTLS_X509_FMT_PEM); if (ret < 0) { - LOG(INFO) << "GnuTLS: Failed to import certificate: " << gnutls_strerror(ret); + LOG(WARNING) << "GnuTLS: Failed to import certificate: " << gnutls_strerror(ret); gnutls_x509_crt_deinit(cert); return false; } @@ -663,7 +1081,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) ret = gnutls_pubkey_import_x509(pubkey, cert, 0); if (ret < 0) { - LOG(INFO) << "GnuTLS: Failed to import public key: " << gnutls_strerror(ret); + LOG(WARNING) << "GnuTLS: Failed to import public key: " << gnutls_strerror(ret); gnutls_pubkey_deinit(pubkey); gnutls_x509_crt_deinit(cert); return false; @@ -676,7 +1094,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) std::ifstream crtFile(crtFilePath, std::ios::binary); if (!crtFile.is_open()) { - LOG(INFO) << "OpenSSL: Unable to open file: " << crtFilePath; + LOG(WARNING) << "OpenSSL: Unable to open file: " << crtFilePath; return false; } @@ -685,13 +1103,13 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size()); if (!bio) { - LOG(INFO) << "OpenSSL: Unable to create BIO for file: " << crtFilePath; + LOG(WARNING) << "OpenSSL: Unable to create BIO for file: " << crtFilePath; return false; } X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); if (!cert) { - LOG(INFO) << "OpenSSL: Unable to read certificate from file: " << crtFilePath; + LOG(WARNING) << "OpenSSL: Unable to read certificate from file: " << crtFilePath; BIO_free(bio); return false; } @@ -701,7 +1119,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) #if USE_OPENSSL_3 if (!pubkey) { - LOG(INFO) << "OpenSSL: Failed to extract the public key"; + LOG(WARNING) << "OpenSSL: Failed to extract the public key"; X509_free(cert); return false; } @@ -712,7 +1130,7 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) EVP_PKEY_free(pubkey); if (!ec_pubkey) { - LOG(INFO) << "OpenSSL: Failed to extract the public key"; + LOG(WARNING) << "OpenSSL: Failed to extract the public key"; X509_free(cert); return false; } @@ -728,203 +1146,11 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) } -bool Gnss_Crypto::verify_signature(const std::vector& message, const std::vector& signature) const -{ - std::vector digest = this->computeSHA256(message); - if (!have_public_key()) - { - std::cerr << "Galileo OSNMA KROOT verification error: Public key is not available" << std::endl; - return false; - } - bool success = false; -#if USE_GNUTLS_FALLBACK -#if HAVE_GNUTLS_SIGN_ECDSA_SHA256 - // Convert signature to DER format - std::vector der_sig; - if (!convert_raw_to_der_ecdsa(signature, der_sig)) - { - std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl; - return false; - } - - // Prepare the digest datum - gnutls_datum_t digest_data = {const_cast(digest.data()), static_cast(digest.size())}; - gnutls_datum_t der_sig_data = {der_sig.data(), static_cast(der_sig.size())}; - - // Verify the DER-encoded signature - int ret = gnutls_pubkey_verify_hash2(d_PublicKey, GNUTLS_SIGN_ECDSA_SHA256, 0, &digest_data, &der_sig_data); - success = (ret >= 0); - if (success) - { - LOG(INFO) << "GnuTLS: OSNMA signature authenticated successfully"; - } - else - { - std::cerr << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret) << std::endl; - LOG(WARNING) << "GnuTLS: OSNMA message authentication failed: " << gnutls_strerror(ret); - } -#endif -#else // OpenSSL -#if USE_OPENSSL_3 - EVP_PKEY_CTX* ctx; - ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); - bool do_operation = true; - - if (!ctx) - { - do_operation = false; - } - // convert raw signature into DER format - size_t half_size = signature.size() / 2; - std::vector raw_r(signature.begin(), signature.begin() + half_size); - std::vector raw_s(signature.begin() + half_size, signature.end()); - - // Convert raw R and S to BIGNUMs - BIGNUM* r = BN_bin2bn(raw_r.data(), raw_r.size(), nullptr); - BIGNUM* s = BN_bin2bn(raw_s.data(), raw_s.size(), nullptr); - - ECDSA_SIG* sig = ECDSA_SIG_new(); - if (r == nullptr || s == nullptr || sig == nullptr) - { - std::cerr << "Failed to allocate memory for BIGNUMs or ECDSA_SIG" << std::endl; - return false; - } - - if (ECDSA_SIG_set0(sig, r, s) != 1) - { - std::cerr << "Failed to set R and S values in ECDSA_SIG" << std::endl; - ECDSA_SIG_free(sig); // Free the ECDSA_SIG struct as it is no longer needed - return false; - } - - std::vector derSignature; - unsigned char* derSig = nullptr; - int derSigLength = i2d_ECDSA_SIG(sig, &derSig); - - if (derSigLength <= 0) - { - std::cerr << "Failed to convert ECDSA_SIG to DER format" << std::endl; - return false; - } - - derSignature.assign(derSig, derSig + derSigLength); - - if (EVP_PKEY_verify_init(ctx) <= 0) - { - do_operation = false; - } - if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) - { - do_operation = false; - } - int verification = 0; - if (do_operation) - { - verification = EVP_PKEY_verify(ctx, derSignature.data(), derSignature.size(), digest.data(), digest.size()); - } - EVP_PKEY_CTX_free(ctx); - OPENSSL_free(derSig); - ECDSA_SIG_free(sig); - if (verification == 1) - { - success = true; - LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; - } - else - { - unsigned long errCode = ERR_get_error(); - char* err = ERR_error_string(errCode, nullptr); - std::cerr << "OpenSSL: OSNMA message authentication failed: " << err << std::endl; - LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err; - } -#else // OpenSSL 1.x - std::vector der_sig; - if (!convert_raw_to_der_ecdsa(signature, der_sig)) - { - std::cerr << "Failed to convert raw ECDSA signature to DER format" << std::endl; - return false; - } - int verification = ECDSA_verify(0, digest.data(), SHA256_DIGEST_LENGTH, der_sig.data(), static_cast(der_sig.size()), d_PublicKey); - if (verification == 1) - { - success = true; - LOG(INFO) << "OpenSSL: OSNMA signature authenticated successfully"; - } - else if (verification == 0) - { - std::cerr << "OpenSSL: invalid signature found when verifying message" << std::endl; - LOG(WARNING) << "OpenSSL: invalid signature found when verifying message"; - } - else - { - std::cerr << "OpenSSL: OSNMA message authentication failed" << std::endl; - LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; - } -#endif -#endif - return success; -} - - -void Gnss_Crypto::set_public_key(const std::vector& publicKey) -{ -#if USE_GNUTLS_FALLBACK - gnutls_pubkey_t pubkey; - gnutls_datum_t pemDatum = {const_cast(publicKey.data()), static_cast(publicKey.size())}; - gnutls_pubkey_init(&pubkey); - int ret = gnutls_pubkey_import(pubkey, &pemDatum, GNUTLS_X509_FMT_PEM); - if (ret != GNUTLS_E_SUCCESS) - { - gnutls_pubkey_deinit(pubkey); - std::cerr << "GnuTLS: error setting the public key" << std::endl; - std::cerr << "GnuTLS error: " << gnutls_strerror(ret) << std::endl; - return; - } - pubkey_copy(pubkey, &d_PublicKey); - gnutls_pubkey_deinit(pubkey); -#else // OpenSSL - BIO* bio = nullptr; - EVP_PKEY* pkey = nullptr; - bio = BIO_new_mem_buf(const_cast(publicKey.data()), publicKey.size()); - if (!bio) - { - std::cerr << "Failed to create BIO for key \n"; - return; - } - - pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); - BIO_free(bio); - - if (!pkey) - { - std::cerr << "OpenSSL: error setting the OSNMA public key." << std::endl; - LOG(INFO) << "OpenSSL: error setting the OSNMA public key."; - return; - } -#if USE_OPENSSL_3 - if (!pubkey_copy(pkey, &d_PublicKey)) - { - return; - } -#else - EC_KEY* ec_pkey = EVP_PKEY_get1_EC_KEY(pkey); - if (!pubkey_copy(ec_pkey, &d_PublicKey)) - { - return; - } - EC_KEY_free(ec_pkey); -#endif // OpenSSL 1.x - EVP_PKEY_free(pkey); -#endif - LOG(INFO) << "OSNMA Public Key successfully set up."; -} - - bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector& raw_signature, std::vector& der_signature) const { if (raw_signature.size() % 2 != 0) { - std::cerr << "Invalid raw ECDSA signature size" << std::endl; + LOG(WARNING) << "Invalid raw ECDSA signature size"; return false; } @@ -968,6 +1194,27 @@ bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector& raw_signa } +std::vector Gnss_Crypto::convert_from_hex_str(const std::string& input) const +{ + std::vector result; + + // Iterate over the input string in pairs + for (size_t i = 0; i < input.length(); i += 2) + { + // Extract two hexadecimal characters from the input string + std::string hexByte = input.substr(i, 2); + + // Convert the hexadecimal string to an integer value + auto value = static_cast(std::stoul(hexByte, nullptr, 16)); + + // Append the value to the result vector + result.push_back(value); + } + + return result; +} + + #if USE_GNUTLS_FALLBACK // GnuTLS-specific functions bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) { @@ -1026,7 +1273,7 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) // Read the data from the memory buffer char* bio_data; - long data_len = BIO_get_mem_data(mem_bio, &bio_data); + int64_t data_len = BIO_get_mem_data(mem_bio, &bio_data); // Create a new memory buffer and load the data into it BIO* mem_bio2 = BIO_new_mem_buf(bio_data, data_len); @@ -1051,9 +1298,7 @@ bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) return true; } - -#else // OpenSSL 1.x - +#else // OpenSSL 1.x bool Gnss_Crypto::pubkey_copy(EC_KEY* src, EC_KEY** dest) { // Open a memory buffer @@ -1097,122 +1342,5 @@ bool Gnss_Crypto::pubkey_copy(EC_KEY* src, EC_KEY** dest) return true; } +#endif // OpenSSL #endif -#endif - - -bool Gnss_Crypto::store_public_key(const std::string& pubKeyFilePath) const -{ - if (!have_public_key()) - { - return false; - } - std::ofstream pubKeyFile(pubKeyFilePath, std::ios::binary); - if (!pubKeyFile.is_open()) - { - LOG(INFO) << "Unable to open file: " << pubKeyFilePath; - return false; - } -#if USE_GNUTLS_FALLBACK - gnutls_datum_t pem_data; -#if HAVE_GNUTLS_PUBKEY_EXPORT2 - int ret = gnutls_pubkey_export2(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data); -#else - size_t output_stata_size; - int ret = gnutls_pubkey_export(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data, &output_stata_size); -#endif - if (ret != GNUTLS_E_SUCCESS) - { - LOG(INFO) << "GnuTLS: Failed to export public key: " << gnutls_strerror(ret); - return false; - } - - pubKeyFile.write((const char*)pem_data.data, pem_data.size); - pubKeyFile.close(); - gnutls_free(pem_data.data); -#else // OpenSSL - BIO* bio = BIO_new(BIO_s_mem()); - if (!bio) - { - LOG(INFO) << "OpenSSL: Failed to create BIO"; - return false; - } -#if USE_OPENSSL_3 - if (!PEM_write_bio_PUBKEY(bio, d_PublicKey)) -#else // OpenSSL 1.x - if (!PEM_write_bio_EC_PUBKEY(bio, d_PublicKey)) -#endif - { - LOG(INFO) << "OpenSSL: Failed to write public key to BIO"; - BIO_free(bio); - return false; - } - - char* bio_data; - auto bio_len = BIO_get_mem_data(bio, &bio_data); - if (bio_len <= 0) - { - LOG(INFO) << "OpenSSL: Failed to get BIO data"; - BIO_free(bio); - return false; - } - - pubKeyFile.write(bio_data, bio_len); - pubKeyFile.close(); - BIO_free(bio); -#endif - return true; -} - - -std::vector Gnss_Crypto::getPublicKey() const -{ - if (!have_public_key()) - { - return {}; - } -#if USE_GNUTLS_FALLBACK - gnutls_datum_t pem_data = {nullptr, 0}; - - int ret = gnutls_pubkey_export2(d_PublicKey, GNUTLS_X509_FMT_PEM, &pem_data); - if (ret != GNUTLS_E_SUCCESS) - { - LOG(INFO) << "GnuTLS: Failed to export public key to PEM format."; - return {}; - } - std::vector output(pem_data.data, pem_data.data + pem_data.size); - - // Free the allocated memory by gnutls_pubkey_export2 - gnutls_free(pem_data.data); -#else // OpenSSL - // Create a BIO for the memory buffer - BIO* mem = BIO_new(BIO_s_mem()); - if (!mem) - { - LOG(INFO) << "OpenSSL: Failed to create BIO."; - return {}; - } -#if USE_OPENSSL_3 - if (!PEM_write_bio_PUBKEY(mem, d_PublicKey)) -#else // OpenSSL 1.x - if (!PEM_write_bio_EC_PUBKEY(mem, d_PublicKey)) -#endif - { - BIO_free(mem); - LOG(INFO) << "OpenSSL: Failed to write public key to PEM format."; - return {}; - } - - // Get the length of the data in the BIO - BUF_MEM* mem_ptr; - BIO_get_mem_ptr(mem, &mem_ptr); - - // Copy the data from the BIO to a std::vector - std::vector output(mem_ptr->length); - memcpy(output.data(), mem_ptr->data, mem_ptr->length); - - // Clean up the BIO - BIO_free(mem); -#endif - return output; -} \ No newline at end of file diff --git a/src/core/system_parameters/gnss_crypto.h b/src/core/system_parameters/gnss_crypto.h index b8164e0ac..8e89f1525 100644 --- a/src/core/system_parameters/gnss_crypto.h +++ b/src/core/system_parameters/gnss_crypto.h @@ -34,31 +34,43 @@ /** \addtogroup System_Parameters * \{ */ +/*! + * \brief Class implementing cryptographic functions + * for Navigation Message Authentication + */ class Gnss_Crypto { public: - Gnss_Crypto(); + Gnss_Crypto(); //!< Default constructor + + /*! + * Constructor with a .crt or .pem file for the ECDSA Public Key + * and a XML file for the Merkle Tree root. + * Files can be downloaded by registering at https://www.gsc-europa.eu/ + */ Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath); - ~Gnss_Crypto(); + ~Gnss_Crypto(); //!< Default destructor - void set_public_key(const std::vector& publickey); - bool have_public_key() const; - bool verify_signature(const std::vector& message, const std::vector& signature) const; + bool have_public_key() const; //!< Returns true if the ECDSA Public Key is already loaded + + /*! + * Stores the ECDSA Public Key in a .pem file, which is read in a following run if the .crt file is not found + */ bool store_public_key(const std::string& pubKeyFilePath) const; - std::vector getPublicKey() const; - std::vector computeSHA256(const std::vector& input) const; - std::vector computeSHA3_256(const std::vector& input) const; - std::vector computeHMAC_SHA_256(const std::vector& key, const std::vector& input) const; - std::vector computeCMAC_AES(const std::vector& key, const std::vector& input) const; - inline std::vector getMerkleRoot() const - { - return d_x_4_0; - } - inline void setMerkleRoot(const std::vector& v) - { - d_x_4_0 = v; - } + bool verify_signature_ecdsa_p256(const std::vector& message, const std::vector& signature) const; //!< Verify ECDSA-P256 signature (message in plain hex, signature in raw format) + bool verify_signature_ecdsa_p521(const std::vector& message, const std::vector& signature) const; //!< Verify ECDSA-P521 signature (message in plain hex, signature in raw format) + + std::vector compute_SHA_256(const std::vector& input) const; //!< Computes SHA-256 hash + std::vector compute_SHA3_256(const std::vector& input) const; //!< Computes SHA3-256 hash + std::vector compute_HMAC_SHA_256(const std::vector& key, const std::vector& input) const; //!< Computes HMAC-SHA-256 message authentication code + std::vector compute_CMAC_AES(const std::vector& key, const std::vector& input) const; //!< Computes CMAC-AES message authentication code + + std::vector get_public_key() const; //!< Gets the ECDSA Public Key in PEM format + std::vector get_merkle_root() const; //!< Gets the Merkle Tree root node (\f$ x_{4,0} \f$) + + void set_public_key(const std::vector& publickey); //!< Sets the ECDSA Public Key (publickey in PEM format) + void set_merkle_root(const std::vector& v); //!< Sets the Merkle Tree root node x(\f$ x_{4,0} \f$) private: void read_merkle_xml(const std::string& merkleFilePath); @@ -79,10 +91,6 @@ private: #endif #endif std::vector d_x_4_0; - std::vector d_x_3_1; - std::vector d_x_2_1; - std::vector d_x_1_1; - std::vector d_x_0_1; }; /** \} */ diff --git a/src/core/system_parameters/osnma_data.h b/src/core/system_parameters/osnma_data.h index 105c4cbc2..484fa0162 100644 --- a/src/core/system_parameters/osnma_data.h +++ b/src/core/system_parameters/osnma_data.h @@ -82,7 +82,7 @@ class DSM_PKR_message public: DSM_PKR_message() = default; - std::array itn; // bitset<1024> + std::array itn{}; // bitset<1024> std::vector npk; std::vector p_dp; uint8_t nb_dp{}; diff --git a/src/core/system_parameters/osnma_helper.cc b/src/core/system_parameters/osnma_helper.cc index 2002c72ca..f8650ed3f 100644 --- a/src/core/system_parameters/osnma_helper.cc +++ b/src/core/system_parameters/osnma_helper.cc @@ -1,17 +1,17 @@ /*! -* \file osnma_helper.h -* \brief Class for auxiliary osnma functions -* \author Carles Fernandez-Prades, 2024 cfernandez(at)cttc.es -* -* ----------------------------------------------------------------------------- -* -* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. -* This file is part of GNSS-SDR. -* -* Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) -* SPDX-License-Identifier: GPL-3.0-or-later -* -* ----------------------------------------------------------------------------- + * \file osnma_helper.h + * \brief Class for auxiliary osnma functions + * \author Carles Fernandez-Prades, 2024 cfernandez(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- */ #include "osnma_helper.h" @@ -26,6 +26,7 @@ uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const return GST; } + std::vector Osnma_Helper::gst_to_uint8(uint32_t GST) const { std::vector res; @@ -37,6 +38,7 @@ std::vector Osnma_Helper::gst_to_uint8(uint32_t GST) const return res; } + /** * @brief Convert a binary string to a vector of bytes. * @@ -47,7 +49,8 @@ std::vector Osnma_Helper::gst_to_uint8(uint32_t GST) const * @param binaryString The binary string to be converted. * @return The vector of bytes converted from the binary string. */ -std::vector Osnma_Helper::bytes(const std::string& binaryString) const { +std::vector Osnma_Helper::bytes(const std::string& binaryString) const +{ std::vector bytes; // Determine the size of the padding needed. @@ -55,12 +58,14 @@ std::vector Osnma_Helper::bytes(const std::string& binaryString) const std::string padded_binary = binaryString; - if (padding_size != 0) { - padding_size = 8 - padding_size; // Compute padding size + if (padding_size != 0) + { + padding_size = 8 - padding_size; // Compute padding size padded_binary.append(padding_size, '0'); // Append zeros to the binary string } - for (size_t i = 0; i < padded_binary.size(); i += 8) { + for (size_t i = 0; i < padded_binary.size(); i += 8) + { uint8_t byte = std::bitset<8>(padded_binary.substr(i, 8)).to_ulong(); bytes.push_back(byte); } @@ -68,37 +73,49 @@ std::vector Osnma_Helper::bytes(const std::string& binaryString) const return bytes; } -std::string Osnma_Helper::verification_status_str(const int& status) const + +std::string Osnma_Helper::verification_status_str(int status) const { - switch (status) { - case 0: return "SUCCESS"; - case 1: return "FAIL"; - case 2: return "UNVERIFIED"; - default: return "UNKNOWN"; - } + switch (status) + { + case 0: + return "SUCCESS"; + case 1: + return "FAIL"; + case 2: + return "UNVERIFIED"; + default: + return "UNKNOWN"; + } } + + std::string Osnma_Helper::convert_to_hex_string(const std::vector& vector) const { std::stringstream ss; ss << std::hex << std::setfill('0'); - for (auto byte : vector) { + for (auto byte : vector) + { ss << std::setw(2) << static_cast(byte); } return ss.str(); } + std::vector Osnma_Helper::convert_from_hex_string(const std::string& hex_string) const { std::vector result; std::string adjusted_hex_string = hex_string; - if (hex_string.length() % 2 != 0) { + if (hex_string.length() % 2 != 0) + { adjusted_hex_string = "0" + hex_string; } - for (std::size_t i = 0; i < adjusted_hex_string.length(); i += 2) { + for (std::size_t i = 0; i < adjusted_hex_string.length(); i += 2) + { std::string byte_string = adjusted_hex_string.substr(i, 2); - uint8_t byte = static_cast(std::stoul(byte_string, nullptr, 16)); + auto byte = static_cast(std::stoul(byte_string, nullptr, 16)); result.push_back(byte); } diff --git a/src/core/system_parameters/osnma_helper.h b/src/core/system_parameters/osnma_helper.h index 761306efc..686ef5e99 100644 --- a/src/core/system_parameters/osnma_helper.h +++ b/src/core/system_parameters/osnma_helper.h @@ -29,7 +29,7 @@ public: uint32_t compute_gst(uint32_t WN, uint32_t TOW) const; std::vector gst_to_uint8(uint32_t GST) const; std::vector bytes(const std::string& binaryString) const; - std::string verification_status_str(const int& status) const; + std::string verification_status_str(int status) const; std::string convert_to_hex_string(const std::vector& vector) const ; std::vector convert_from_hex_string(const std::string& hex_string) const; // TODO remove similar function in gnss_crypto }; diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index 04b2a0622..c58266231 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -26,7 +26,8 @@ if(ENABLE_GLOG_AND_GFLAGS) target_link_libraries(gnss-sdr PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(gnss-sdr PUBLIC -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(gnss-sdr PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize absl::log_sink absl::log_sink_registry) + target_link_libraries(gnss-sdr PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize absl::log_sink absl::log_sink_registry) + target_link_libraries(gnss-sdr INTERFACE "$") endif() if(NOT ENABLE_LOG) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index f1491b032..d7bbab2ee 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -624,7 +624,8 @@ if(ENABLE_UNIT_TESTING) target_link_libraries(run_tests PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(run_tests PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(run_tests PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(run_tests PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(run_tests INTERFACE "$") endif() target_include_directories(run_tests INTERFACE @@ -774,7 +775,8 @@ if(ENABLE_FPGA) target_link_libraries(gps_l1_ca_dll_pll_tracking_test_fpga PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(gps_l1_ca_dll_pll_tracking_test_fpga PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(gps_l1_ca_dll_pll_tracking_test_fpga PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(gps_l1_ca_dll_pll_tracking_test_fpga PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(gps_l1_ca_dll_pll_tracking_test_fpga INTERFACE "$") endif() target_include_directories(gps_l1_ca_dll_pll_tracking_test_fpga INTERFACE ${GNSSSDR_SOURCE_DIR}/src/tests/common-files @@ -815,6 +817,9 @@ function(add_system_test executable) INTERFACE ${GNSSSDR_SOURCE_DIR}/src/tests/common-files ) target_link_libraries(${executable} PRIVATE ${OPT_LIBS_} algorithms_libs) + if(NOT ENABLE_GLOG_AND_GFLAGS) + target_link_libraries(${executable} INTERFACE "$") + endif() if(GNURADIO_USES_STD_POINTERS) target_compile_definitions(${executable} PRIVATE -DGNURADIO_USES_STD_POINTERS=1 @@ -873,7 +878,7 @@ if(ENABLE_SYSTEM_TESTING) if(ENABLE_GLOG_AND_GFLAGS) set(OPT_LIBS_ ${OPT_LIBS_} Gflags::gflags Glog::glog) else() - set(OPT_LIBS_ ${OPT_LIBS_} absl::flags_parse absl::flags absl::log $ absl::log_initialize absl::log_sink absl::log_sink_registry) + set(OPT_LIBS_ ${OPT_LIBS_} absl::flags_parse absl::flags absl::log absl::log_initialize absl::log_sink absl::log_sink_registry) endif() if(NOT ENABLE_PACKAGING) add_system_test(ttff @@ -897,7 +902,7 @@ if(ENABLE_SYSTEM_TESTING) if(ENABLE_GLOG_AND_GFLAGS) set(OPT_LIBS_ ${OPT_LIBS_} Gflags::gflags Glog::glog) else() - set(OPT_LIBS_ ${OPT_LIBS_} absl::flags_parse absl::log $ absl::log_initialize absl::log_sink absl::log_sink_registry) + set(OPT_LIBS_ ${OPT_LIBS_} absl::flags_parse absl::log absl::log_initialize absl::log_sink absl::log_sink_registry) endif() add_system_test(position_test CMAKE_ARGS -DCMAKE_BUILD_TYPE=$<$:Debug>$<$:Release>$<$:RelWithDebInfo>$<$:MinSizeRel>$<$:Debug>$<$:Debug>$<$:RelWithDebInfo>$<$:RelWithDebInfo>$<$:Debug> @@ -970,7 +975,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(flowgraph_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(flowgraph_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(flowgraph_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(flowgraph_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(flowgraph_test INTERFACE "$") endif() target_include_directories(flowgraph_test @@ -1027,7 +1033,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(gnss_block_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(gnss_block_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(gnss_block_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(gnss_block_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(gnss_block_test INTERFACE "$") endif() target_include_directories(gnss_block_test @@ -1079,7 +1086,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(gnuradio_block_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(gnuradio_block_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(gnuradio_block_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(gnuradio_block_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(gnuradio_block_test INTERFACE "$") endif() xcode_remove_warning_duplicates(gnuradio_block_test) @@ -1115,7 +1123,8 @@ if(ENABLE_GLOG_AND_GFLAGS) target_link_libraries(matio_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(matio_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(matio_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(matio_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(matio_test INTERFACE "$") endif() target_include_directories(matio_test @@ -1165,7 +1174,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(acq_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(acq_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(acq_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(acq_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(acq_test INTERFACE "$") endif() target_include_directories(acq_test INTERFACE @@ -1251,7 +1261,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(trk_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(trk_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(trk_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(trk_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(trk_test INTERFACE "$") endif() if(USE_GENERIC_LAMBDAS) set(has_generic_lambdas HAS_GENERIC_LAMBDA=1) @@ -1314,7 +1325,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(control_thread_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(control_thread_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(control_thread_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(control_thread_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(control_thread_test INTERFACE "$") endif() xcode_remove_warning_duplicates(control_thread_test) @@ -1375,7 +1387,8 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) target_link_libraries(osnma_msg_receiver_test PRIVATE Gflags::gflags Glog::glog) target_compile_definitions(osnma_msg_receiver_test PRIVATE -DUSE_GLOG_AND_GFLAGS=1) else() - target_link_libraries(osnma_msg_receiver_test PRIVATE absl::flags absl::flags_parse absl::log $ absl::log_initialize) + target_link_libraries(osnma_msg_receiver_test PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize) + target_link_libraries(osnma_msg_receiver_test INTERFACE "$") endif() xcode_remove_warning_duplicates(osnma_msg_receiver_test) # TODO - unsure if needed diff --git a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc index 5095269c7..2d7355fd7 100644 --- a/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/osnma/gnss_crypto_test.cc @@ -1,3 +1,21 @@ +/*! + * \file gnss_crypto_test.cc + * \brief Tests for the Gnss_Crypto class. + * \author Carles Fernandez, 2023-2024. cfernandez(at)cttc.es + * Cesare Ghionoiu Martinez, 2023-2024. c.ghionoiu-martinez@tu-braunschweig.de + * + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + #include "gnss_crypto.h" #include "gnss_sdr_filesystem.h" #include "gnss_sdr_make_unique.h" @@ -10,74 +28,26 @@ class GnssCryptoTest : public ::testing::Test }; -TEST(GnssCryptoTest, TestComputeSHA_256) -{ - auto d_crypto = std::make_unique(); - std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world - - std::vector expected_output = { - 0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7, - 0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04, 0xB2, - 0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7, 0xC4, 0x8F}; - - std::vector output = d_crypto->computeSHA256(message); - - ASSERT_EQ(expected_output, output); -} - - -TEST(GnssCryptoTest, TestComputeSHA3_256) -{ - auto d_crypto = std::make_unique(); - std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world - - std::vector expected_output = { - 0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB, - 0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B, - 0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6, 0x3B, 0x3F}; - - std::vector output = d_crypto->computeSHA3_256(message); - - ASSERT_EQ(expected_output, output); -} - - -TEST(GnssCryptoTest, VerifySignature) -{ - auto d_crypto = std::make_unique(); - - // RG example - import crt certificate - result: FAIL - std::vector message = {0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; - std::vector signature = {0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, 0x28, 0xC1, 0x77, 0xFB}; - std::vector publicKey{// PEM format - 1000 bits - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, - 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, - 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, - 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, - 0x0A, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; - - d_crypto->set_public_key(publicKey); - bool result = d_crypto->verify_signature(message, signature); - - ASSERT_TRUE(result); -} - - TEST(GnssCryptoTest, VerifyPubKeyImport) { auto d_crypto = std::make_unique(); - std::vector publicKey{// PEM - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, - 0x4D, 0x46, - 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, - 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E, - 0x73, 0x66, 0x78, 0x2F, 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30, - 0x48, 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, 0x69, 0x79, - 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, - 0x2D, 0x2D, 0x2D, 0x0A}; + // PEM format + std::vector publicKey = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, + 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, + 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, + 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, + 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, + 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E, 0x73, 0x66, 0x78, 0x2F, + 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, + 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30, 0x48, + 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, + 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, + 0x69, 0x79, 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, + 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, + 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; d_crypto->set_public_key(publicKey); @@ -92,14 +62,22 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage) const std::string f1("./osnma_test_file1.pem"); const std::string f2("./osnma_test_file2.pem"); - std::vector publicKey{ - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, - 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, - 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, - 0x46, 0x6B, 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, 0x2B, 0x37, - 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, - 0x4C, 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, 0x3D, 0x3D, 0x0A, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; + // PEM format + std::vector publicKey = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x55, + 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x0A, 0x4D, 0x46, 0x6B, 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, + 0x7A, 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, + 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, 0x67, 0x41, 0x45, 0x53, 0x76, + 0x50, 0x75, 0x4F, 0x70, 0x51, 0x6C, 0x4A, 0x54, 0x31, 0x56, 0x77, 0x6C, 0x72, + 0x43, 0x4C, 0x63, 0x38, 0x55, 0x54, 0x54, 0x6B, 0x4E, 0x73, 0x66, 0x78, 0x2F, + 0x0A, 0x4D, 0x56, 0x6F, 0x71, 0x47, 0x61, 0x35, 0x4F, 0x31, 0x73, 0x75, 0x6D, + 0x57, 0x64, 0x61, 0x5A, 0x66, 0x4F, 0x69, 0x39, 0x48, 0x30, 0x4D, 0x30, 0x48, + 0x46, 0x6E, 0x5A, 0x32, 0x63, 0x72, 0x44, 0x37, 0x6C, 0x6A, 0x6C, 0x36, 0x74, + 0x4E, 0x56, 0x52, 0x4F, 0x71, 0x4A, 0x63, 0x57, 0x58, 0x51, 0x6B, 0x6E, 0x4B, + 0x69, 0x79, 0x44, 0x79, 0x48, 0x58, 0x51, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, + 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, + 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; d_crypto->set_public_key(publicKey); bool result = d_crypto->store_public_key(f1); @@ -118,7 +96,7 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage) ASSERT_EQ(content_file, content_file2); - std::vector readkey = d_crypto2->getPublicKey(); + std::vector readkey = d_crypto2->get_public_key(); ASSERT_EQ(publicKey, readkey); errorlib::error_code ec; @@ -127,6 +105,40 @@ TEST(GnssCryptoTest, VerifyPublicKeyStorage) } +TEST(GnssCryptoTest, TestComputeSHA_256) +{ + auto d_crypto = std::make_unique(); + std::vector message{ + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world + + std::vector expected_output = { + 0x18, 0x94, 0xA1, 0x9C, 0x85, 0xBA, 0x15, 0x3A, 0xCB, 0xF7, + 0x43, 0xAC, 0x4E, 0x43, 0xFC, 0x00, 0x4C, 0x89, 0x16, 0x04, 0xB2, + 0x6F, 0x8C, 0x69, 0xE1, 0xE8, 0x3E, 0xA2, 0xAF, 0xC7, 0xC4, 0x8F}; + + std::vector output = d_crypto->compute_SHA_256(message); + + ASSERT_EQ(expected_output, output); +} + + +TEST(GnssCryptoTest, TestComputeSHA3_256) +{ + auto d_crypto = std::make_unique(); + std::vector message{ + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world + + std::vector expected_output = { + 0xCC, 0xB8, 0xF9, 0x23, 0x5F, 0x4A, 0x93, 0x2C, 0xA0, 0xAB, + 0xBB, 0x2C, 0x24, 0x36, 0x72, 0x5E, 0x2E, 0x8D, 0xC7, 0x5B, + 0x99, 0xE7, 0xF6, 0xC4, 0x50, 0x5B, 0x2A, 0x93, 0x6E, 0xB6, 0x3B, 0x3F}; + + std::vector output = d_crypto->compute_SHA3_256(message); + + ASSERT_EQ(expected_output, output); +} + + // Unit test for computeHMAC_SHA_256 function. TEST(GnssCryptoTest, TestComputeHMACSHA256) { @@ -138,14 +150,16 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256) 0xEB, 0x62, 0x3E, 0x95, 0x6B, 0x2B, 0xCE, 0xA3, 0xB4, 0xD4, 0xDB, 0x31, 0xEE, 0x96, 0xAB, 0xFA}; - std::vector message{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world con 0x0A + std::vector message{ + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x0A}; // Hello world + std::vector expected_output = { 0xC3, 0x51, 0xF6, 0xFD, 0xDD, 0xC9, 0x8B, 0x41, 0xD6, 0xF4, 0x77, 0x6D, 0xAC, 0xE8, 0xE0, 0x14, 0xB2, 0x7A, 0xCC, 0x22, 0x00, 0xAA, 0xD2, 0x37, 0xD0, 0x79, 0x06, 0x12, 0x83, 0x40, 0xB7, 0xA6}; - std::vector output = d_crypto->computeHMAC_SHA_256(key, message); + std::vector output = d_crypto->compute_HMAC_SHA_256(key, message); ASSERT_EQ(expected_output, output); } @@ -156,23 +170,31 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_m0) // key and message generated from RG A.6.5.1 auto d_crypto = std::make_unique(); - std::vector key = {// RG K4 @ 345690 + // RG K4 @ 345690 + std::vector key = { 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; - std::vector message{// m0 - 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B, - 0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21, - 0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D, - 0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00, - 0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, 0xF7, 0xFC, 0x00}; + // m0 + std::vector message = { + 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x01, 0x83, 0xA5, + 0x91, 0x05, 0x1D, 0x69, 0x25, 0x80, 0x07, 0x6B, + 0x3E, 0xEA, 0x81, 0x41, 0xBF, 0x03, 0xAD, 0xCB, + 0x5A, 0xAD, 0xB2, 0x77, 0xAF, 0x6F, 0xCF, 0x21, + 0xFB, 0x98, 0xFF, 0x7E, 0x83, 0xAF, 0xFC, 0x37, + 0x02, 0x03, 0xB0, 0xD8, 0xE1, 0x0E, 0xB1, 0x4D, + 0x11, 0x18, 0xE6, 0xB0, 0xE8, 0x20, 0x01, 0xA0, + 0x00, 0xE5, 0x91, 0x00, 0x06, 0xD3, 0x1F, 0x00, + 0x02, 0x68, 0x05, 0x4A, 0x02, 0xC2, 0x26, 0x07, + 0xF7, 0xFC, 0x00}; std::vector expected_output = { 0xE3, 0x7B, 0xC4, 0xF8, 0x58, 0xAE, 0x1E, 0x5C, - 0xFD, 0xC4, 0x6F, 0x05, 0x4B, 0x1F, 0x47, 0xB9, 0xD2, 0xEA, 0x61, 0xE1, - 0xEF, 0x09, 0x11, 0x5C, 0xFE, 0x70, 0x68, 0x52, 0xBF, 0xF2, 0x3A, 0x83}; + 0xFD, 0xC4, 0x6F, 0x05, 0x4B, 0x1F, 0x47, 0xB9, + 0xD2, 0xEA, 0x61, 0xE1, 0xEF, 0x09, 0x11, 0x5C, + 0xFE, 0x70, 0x68, 0x52, 0xBF, 0xF2, 0x3A, 0x83}; - std::vector output = d_crypto->computeHMAC_SHA_256(key, message); + std::vector output = d_crypto->compute_HMAC_SHA_256(key, message); ASSERT_EQ(expected_output, output); } @@ -183,21 +205,24 @@ TEST(GnssCryptoTest, TestComputeHMACSHA256_adkd4) // key and message generated from RG A.6.5.2 auto d_crypto = std::make_unique(); - std::vector key = {// RG K4 @ 345690 + // RG K4 @ 345690 + std::vector key = { 0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; - std::vector message{ + std::vector message = { 0x02, 0x02, 0x4E, 0x05, 0x46, 0x3C, 0x03, 0xBF, - 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x44, 0x92, 0x38, - 0x22, 0x78, 0x97, 0xFD, 0xEF, 0xF9, 0x30, 0x40}; + 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x44, 0x92, + 0x38, 0x22, 0x78, 0x97, 0xFD, 0xEF, 0xF9, 0x30, + 0x40}; std::vector expected_output = { - 0x7B, 0xB2, 0x38, 0xC8, 0x83, 0xC0, 0x6A, 0x2B, 0x50, 0x8F, - 0xE6, 0x3F, 0xB7, 0xF4, 0xF5, 0x4D, 0x44, 0xAB, 0xEE, 0x4D, - 0xCE, 0xB9, 0x3D, 0xCF, 0x65, 0xCB, 0x3A, 0x5B, 0x81, 0x4A, 0x34, 0xE9}; + 0x7B, 0xB2, 0x38, 0xC8, 0x83, 0xC0, 0x6A, 0x2B, + 0x50, 0x8F, 0xE6, 0x3F, 0xB7, 0xF4, 0xF5, 0x4D, + 0x44, 0xAB, 0xEE, 0x4D, 0xCE, 0xB9, 0x3D, 0xCF, + 0x65, 0xCB, 0x3A, 0x5B, 0x81, 0x4A, 0x34, 0xE9}; - std::vector output = d_crypto->computeHMAC_SHA_256(key, message); + std::vector output = d_crypto->compute_HMAC_SHA_256(key, message); ASSERT_EQ(expected_output, output); } @@ -220,7 +245,122 @@ TEST(GnssCryptoTest, TestComputeCMAC_AES) 0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C}; - std::vector output = d_crypto->computeCMAC_AES(key, message); + std::vector output = d_crypto->compute_CMAC_AES(key, message); ASSERT_EQ(expected_output, output); -} \ No newline at end of file +} + + +TEST(GnssCryptoTest, VerifySignatureP256) +{ + auto d_crypto = std::make_unique(); + + // RG example - import crt certificate + std::vector message = { + 0x82, 0x10, 0x49, 0x22, 0x04, 0xE0, 0x60, 0x61, 0x0B, 0xDF, + 0x26, 0xD7, 0x7B, 0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, + 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; + + // ECDSA P-256 signature, raw format + std::vector signature = { + 0xF8, 0xCD, 0x88, 0x29, 0x9F, 0xA4, 0x60, 0x58, 0x00, 0x20, + 0x7B, 0xFE, 0xBE, 0xAC, 0x55, 0x02, 0x40, 0x53, 0xF3, 0x0F, + 0x7C, 0x69, 0xB3, 0x5C, 0x15, 0xE6, 0x08, 0x00, 0xAC, 0x3B, + 0x6F, 0xE3, 0xED, 0x06, 0x39, 0x95, 0x2F, 0x7B, 0x02, 0x8D, + 0x86, 0x86, 0x74, 0x45, 0x96, 0x1F, 0xFE, 0x94, 0xFB, 0x22, + 0x6B, 0xFF, 0x70, 0x06, 0xE0, 0xC4, 0x51, 0xEE, 0x3F, 0x87, + 0x28, 0xC1, 0x77, 0xFB}; + + // PEM format + std::vector publicKey = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, + 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, + 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x46, 0x6B, + 0x77, 0x45, 0x77, 0x59, 0x48, 0x4B, 0x6F, 0x5A, 0x49, 0x7A, + 0x6A, 0x30, 0x43, 0x41, 0x51, 0x59, 0x49, 0x4B, 0x6F, 0x5A, + 0x49, 0x7A, 0x6A, 0x30, 0x44, 0x41, 0x51, 0x63, 0x44, 0x51, + 0x67, 0x41, 0x45, 0x41, 0x37, 0x4C, 0x4F, 0x5A, 0x4C, 0x77, + 0x67, 0x65, 0x39, 0x32, 0x4C, 0x78, 0x4E, 0x2B, 0x46, 0x6B, + 0x59, 0x66, 0x38, 0x74, 0x6F, 0x59, 0x79, 0x44, 0x57, 0x50, + 0x2F, 0x0A, 0x6F, 0x4A, 0x46, 0x42, 0x44, 0x38, 0x46, 0x59, + 0x2B, 0x37, 0x64, 0x35, 0x67, 0x4F, 0x71, 0x49, 0x61, 0x45, + 0x32, 0x52, 0x6A, 0x50, 0x41, 0x6E, 0x4B, 0x49, 0x36, 0x38, + 0x73, 0x2F, 0x4F, 0x4B, 0x2F, 0x48, 0x50, 0x67, 0x6F, 0x4C, + 0x6B, 0x4F, 0x32, 0x69, 0x6A, 0x51, 0x38, 0x78, 0x41, 0x5A, + 0x79, 0x44, 0x64, 0x50, 0x42, 0x31, 0x64, 0x48, 0x53, 0x51, + 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, + 0x44, 0x20, 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, + 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A}; + + d_crypto->set_public_key(publicKey); + bool result = d_crypto->verify_signature_ecdsa_p256(message, signature); + ASSERT_TRUE(result); + + std::vector wrong_signature = signature; + wrong_signature[1] = 1; + bool result2 = d_crypto->verify_signature_ecdsa_p256(message, wrong_signature); + ASSERT_TRUE(!result2); +} + + +TEST(GnssCryptoTest, VerifySignatureP521) +{ + std::unique_ptr d_crypto = std::make_unique(); + + // Message to be verified + std::vector message = { + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 // "Hello World" + }; + + // Public key in PEM format + std::vector publicKey = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, + 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, + 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x47, 0x62, 0x4D, 0x42, 0x41, 0x47, 0x42, + 0x79, 0x71, 0x47, 0x53, 0x4D, 0x34, 0x39, 0x41, 0x67, 0x45, 0x47, 0x42, + 0x53, 0x75, 0x42, 0x42, 0x41, 0x41, 0x6A, 0x41, 0x34, 0x47, 0x47, 0x41, + 0x41, 0x51, 0x41, 0x6F, 0x35, 0x76, 0x77, 0x66, 0x6E, 0x47, 0x57, 0x47, + 0x33, 0x44, 0x63, 0x59, 0x75, 0x2B, 0x2F, 0x61, 0x58, 0x47, 0x32, 0x7A, + 0x74, 0x65, 0x41, 0x46, 0x50, 0x54, 0x33, 0x0A, 0x48, 0x36, 0x4C, 0x76, + 0x4F, 0x4C, 0x76, 0x49, 0x51, 0x6A, 0x61, 0x2B, 0x6A, 0x74, 0x57, 0x73, + 0x70, 0x4F, 0x38, 0x37, 0x6F, 0x50, 0x32, 0x4E, 0x6D, 0x72, 0x34, 0x6E, + 0x50, 0x68, 0x76, 0x62, 0x53, 0x58, 0x52, 0x4D, 0x37, 0x6A, 0x49, 0x69, + 0x46, 0x38, 0x47, 0x70, 0x6B, 0x75, 0x58, 0x6A, 0x75, 0x4E, 0x7A, 0x34, + 0x72, 0x61, 0x56, 0x4F, 0x65, 0x49, 0x4D, 0x42, 0x77, 0x45, 0x2B, 0x61, + 0x0A, 0x30, 0x4C, 0x76, 0x7A, 0x37, 0x69, 0x54, 0x4D, 0x5A, 0x46, 0x41, + 0x41, 0x51, 0x64, 0x2B, 0x70, 0x47, 0x72, 0x56, 0x54, 0x47, 0x77, 0x66, + 0x53, 0x48, 0x49, 0x72, 0x49, 0x49, 0x45, 0x78, 0x74, 0x5A, 0x35, 0x77, + 0x30, 0x38, 0x51, 0x4F, 0x43, 0x58, 0x2F, 0x75, 0x46, 0x65, 0x2B, 0x30, + 0x78, 0x52, 0x78, 0x4C, 0x64, 0x2F, 0x33, 0x36, 0x42, 0x4E, 0x74, 0x63, + 0x74, 0x69, 0x2F, 0x45, 0x4C, 0x0A, 0x4B, 0x31, 0x35, 0x67, 0x2B, 0x4B, + 0x32, 0x71, 0x67, 0x2F, 0x6C, 0x39, 0x46, 0x42, 0x47, 0x67, 0x4D, 0x2B, + 0x51, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, + 0x50, 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, + 0x2D, 0x2D, 0x2D, 0x0A}; + + // ECDSA P-521 signature, raw format + std::vector signature = { + 0x01, 0x7B, 0x59, 0xAC, 0x3A, 0x03, 0x5C, 0xB4, 0x07, 0xCD, + 0xC1, 0xEB, 0xBE, 0xE5, 0xA6, 0xCB, 0xDA, 0x0A, 0xFF, 0x4D, + 0x38, 0x61, 0x16, 0x0F, 0xB3, 0x77, 0xE5, 0x8A, 0xDC, 0xF3, + 0xFD, 0x79, 0x38, 0x1E, 0xE8, 0x08, 0x3D, 0x5D, 0xBC, 0xC2, + 0x80, 0x6E, 0xE9, 0x2B, 0xC3, 0xEF, 0x07, 0x3D, 0x0C, 0x82, + 0x4C, 0x9B, 0x7A, 0x5C, 0x2E, 0xD5, 0x46, 0xBD, 0x22, 0x21, + 0x13, 0x8A, 0xB2, 0xCA, 0x96, 0x3D, 0x01, 0xBA, 0x2A, 0xC4, + 0x3F, 0xDB, 0x66, 0x3C, 0x40, 0x26, 0xD9, 0xBC, 0x26, 0xD5, + 0x57, 0xD4, 0xBD, 0x15, 0x16, 0x88, 0x21, 0x3B, 0xAA, 0x07, + 0x89, 0xEF, 0x29, 0x8F, 0x2F, 0x85, 0x76, 0x58, 0x9D, 0xCA, + 0x00, 0xCC, 0xC8, 0x30, 0x88, 0x31, 0x99, 0xC1, 0x94, 0xB9, + 0xAF, 0x91, 0xDC, 0xC4, 0x6F, 0x19, 0x2B, 0x12, 0xA2, 0x82, + 0xA5, 0x66, 0x5E, 0x4B, 0xBB, 0xDF, 0x65, 0x81, 0x52, 0x14, + 0x01, 0xD7}; + + d_crypto->set_public_key(publicKey); + bool result = d_crypto->verify_signature_ecdsa_p521(message, signature); + ASSERT_TRUE(result); + + std::vector wrong_signature = signature; + wrong_signature[1] = 1; + bool result2 = d_crypto->verify_signature_ecdsa_p521(message, wrong_signature); + ASSERT_TRUE(!result2); +} diff --git a/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc b/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc index 6b7f280a4..d0df27a3b 100644 --- a/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/osnma/osnma_msg_receiver_test.cc @@ -83,7 +83,7 @@ TEST_F(OsnmaMsgReceiverTest, ComputeMerkleRoot) // Act // ---------- - computed_merkle_root = osnma->compute_merke_root(dsm_pkr_message,base_leaf); + computed_merkle_root = osnma->compute_merkle_root(dsm_pkr_message, base_leaf); // Assert // ---------- @@ -102,7 +102,7 @@ TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf) // Act // ---------- - std::vector computed_base_leaf = osnma->compute_base_leaf(dsm_pkr_message); + std::vector computed_base_leaf = osnma->get_merkle_tree_leaves(dsm_pkr_message); // Assert // ---------- @@ -112,7 +112,7 @@ TEST_F(OsnmaMsgReceiverTest, ComputeBaseLeaf) TEST_F(OsnmaMsgReceiverTest, VerifyPublicKey){ // values taken from RG A.7 // Arrange // ---------- - osnma->d_crypto->setMerkleRoot(helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D")); + osnma->d_crypto->set_merkle_root(helper.convert_from_hex_string("A10C440F3AA62453526DB4AF76DF8D9410D35D8277397D7053C700D192702B0D")); DSM_PKR_message dsm_pkr_message; dsm_pkr_message.npkt = 0x01; dsm_pkr_message.npktid = 0x2; diff --git a/src/utils/nav-listener/CMakeLists.txt b/src/utils/nav-listener/CMakeLists.txt index 048a862f4..cc86a7bf4 100644 --- a/src/utils/nav-listener/CMakeLists.txt +++ b/src/utils/nav-listener/CMakeLists.txt @@ -4,7 +4,7 @@ # SPDX-FileCopyrightText: 2021 C. Fernandez-Prades cfernandez(at)cttc.es # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.9...3.23) +cmake_minimum_required(VERSION 3.9...3.30) project(nav-msg-listener CXX) set(CMAKE_CXX_STANDARD 11) diff --git a/src/utils/rinex-tools/CMakeLists.txt b/src/utils/rinex-tools/CMakeLists.txt index 7dd0352c6..695c369ee 100644 --- a/src/utils/rinex-tools/CMakeLists.txt +++ b/src/utils/rinex-tools/CMakeLists.txt @@ -34,7 +34,7 @@ if("${ARMADILLO_VERSION_STRING}" VERSION_GREATER "9.800" OR (NOT ARMADILLO_FOUND endif() target_include_directories(obsdiff PUBLIC ${GNSSSDR_SOURCE_DIR}/src/tests/common-files) - if("${GNSSTK_VERSION}" VERSION_LESS 3.0.1) + if(GNSSTK_VERSION AND "${GNSSTK_VERSION}" VERSION_LESS 3.0.1) set_property(TARGET obsdiff PROPERTY CXX_STANDARD 14) # Required by GPSTk v3.0.0 endif() # Do not show warnings raised by GPSTk v3.0.0 diff --git a/src/utils/rinex2assist/CMakeLists.txt b/src/utils/rinex2assist/CMakeLists.txt index 39f690be5..277a924b1 100644 --- a/src/utils/rinex2assist/CMakeLists.txt +++ b/src/utils/rinex2assist/CMakeLists.txt @@ -19,7 +19,19 @@ if(NOT GNSSTK_FOUND OR ENABLE_OWN_GNSSTK) endif() endif() -find_package(Boost COMPONENTS iostreams serialization QUIET) +if(CMAKE_VERSION VERSION_LESS 3.30) + find_package(Boost COMPONENTS iostreams serialization QUIET) +else() + find_package(Boost COMPONENTS iostreams serialization) + if(NOT TARGET Boost::iostreams) + message(STATUS "Trying deprecated FindBoost Module ...") + if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) + find_package(Boost COMPONENTS iostreams serialization) + endif() + endif() +endif() + if(CMAKE_VERSION VERSION_LESS 3.5) if(NOT TARGET Boost::iostreams) add_library(Boost::iostreams IMPORTED SHARED) @@ -47,7 +59,7 @@ find_program(UNCOMPRESS_EXECUTABLE uncompress /usr/sbin ) -if(Boost_FOUND) +if(TARGET Boost::iostreams AND TARGET Boost::serialization) message(STATUS "The rinex2assist utility tool will be built when doing '${CMAKE_MAKE_PROGRAM_PRETTY_NAME}'") if(USE_CMAKE_TARGET_SOURCES) add_executable(rinex2assist) @@ -59,7 +71,7 @@ if(Boost_FOUND) add_executable(rinex2assist ${CMAKE_CURRENT_SOURCE_DIR}/main.cc) endif() - if("${GNSSTK_VERSION}" VERSION_LESS 3.0.1) + if(GNSSTK_VERSION AND "${GNSSTK_VERSION}" VERSION_LESS 3.0.1) set_property(TARGET rinex2assist PROPERTY CXX_STANDARD 14) # Required by GPSTk v3.0.0 endif()