From 1d815f0bbf1ab797857a997b59764621dfdf25c2 Mon Sep 17 00:00:00 2001 From: cesaaargm <cesare.martinez@proton.me> Date: Wed, 26 Jun 2024 15:01:05 +0200 Subject: [PATCH 01/14] [TAS-227] [BUG] Tag verification fails for .dat files (WIP) WIP --- .../galileo_telemetry_decoder_gs.cc | 56 +- src/core/libs/osnma_msg_receiver.cc | 78 ++- src/core/libs/osnma_msg_receiver.h | 2 +- .../system_parameters/galileo_inav_message.cc | 2 +- src/core/system_parameters/osnma_helper.cc | 11 + src/core/system_parameters/osnma_helper.h | 1 + .../osnma/osnma_msg_receiver_test.cc | 513 ++++++++++-------- 7 files changed, 369 insertions(+), 294 deletions(-) diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc index a404a100a..3b3d4b06a 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc @@ -439,6 +439,35 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in } // 4. Push the new navigation data to the queues + // extract OSNMA bits, reset container. + bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549; + if(check_size_is_ok) + { + std::cout << "Galileo OSNMA: new ADKD=0/12 navData from " << d_satellite << " at TOW_sf=" << d_inav_nav.get_TOW5() - 25 <<std::endl; + const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> + d_satellite.get_PRN(), + d_inav_nav.get_osnma_adkd_0_12_nav_bits(), + d_inav_nav.get_TOW5() - 25); + this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma)); + LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW5() - 25) <<")";//: 0b" << d_inav_nav.get_osnma_adkd_0_12_nav_bits(); + d_inav_nav.reset_osnma_nav_bits_adkd0_12(); + } + + check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; + if(check_size_is_ok) + { + std::cout << "Galileo OSNMA: new ADKD=4 navData from " << d_satellite <<" at TOW_sf=" << d_inav_nav.get_TOW6() - 5 <<std::endl; + + const auto tmp_obj = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> // TODO conversion from W6 to W_Start_of_subframe + d_satellite.get_PRN(), + d_inav_nav.get_osnma_adkd_4_nav_bits(), + d_inav_nav.get_TOW6() - 5); + this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj)); + LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(d_satellite.get_PRN()) << ", TOW=" << static_cast<int>(d_inav_nav.get_TOW6() - 5) <<")";//: 0b" << d_inav_nav.get_osnma_adkd_4_nav_bits(); + d_inav_nav.reset_osnma_nav_bits_adkd4(); + } + + if (d_inav_nav.have_new_ephemeris() == true) // C: tells if W1-->W4 available from same blcok (and W5!) { // get object for this SV (mandatory) @@ -472,20 +501,6 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in d_first_eph_sent = true; // do not send reduced CED anymore, since we have the full ephemeris set // d_flag_osnma_adkd_0_12 = true; // W1-> W5 available - // extract bits, reset container. - bool check_size_is_ok = d_inav_nav.get_osnma_adkd_0_12_nav_bits().size() == 549; - if(check_size_is_ok) - { - std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << d_satellite.get_PRN() << ") " << "TOW_sf=" << d_inav_nav.get_TOW5() - 24 <<std::endl; - const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> - d_satellite.get_PRN(), - d_inav_nav.get_osnma_adkd_0_12_nav_bits(), - d_inav_nav.get_TOW5() - 24); - this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj_osnma)); - d_inav_nav.reset_osnma_nav_bits_adkd0_12(); - } - - } else { @@ -615,19 +630,6 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, in // bool adkd_4_nav_data_available = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; // newApproach: let decoder decide when block starts and let it fill the data, and just check for length if(adkd_4_nav_data_available /*&& d_inav_nav.is_TOW5_set() not needed cause W6 has TOW also.*/) { - bool check_size_is_ok = d_inav_nav.get_osnma_adkd_4_nav_bits().size() == 141; - if(check_size_is_ok) - { - std::cout << "Galileo OSNMA: sending ADKD=4 navData, PRN_d (" << d_satellite.get_PRN() << ") " << "TOW_sf=" << d_inav_nav.get_TOW6() - 4 <<std::endl; - - const auto tmp_obj = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> // TODO conversion from W6 to W_Start_of_subframe - d_satellite.get_PRN(), - d_inav_nav.get_osnma_adkd_4_nav_bits(), - d_inav_nav.get_TOW6() - 4); - this->message_port_pub(pmt::mp("OSNMA_from_TLM"), pmt::make_any(tmp_obj)); - d_inav_nav.reset_osnma_nav_bits_adkd4(); - } - } auto newOSNMA = d_inav_nav.have_new_nma(); if (d_band == '1' && newOSNMA) diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index 4a5e95ac9..45ad958ee 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -62,13 +62,13 @@ osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, osnma_msg_receiver::osnma_msg_receiver( - const std::string& pemFilePath, + const std::string& crtFilePath, const std::string& merkleFilePath) : gr::block("osnma_msg_receiver", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) { d_dsm_reader = std::make_unique<OSNMA_DSM_Reader>(); - d_crypto = std::make_unique<Gnss_Crypto>(pemFilePath, merkleFilePath); + d_crypto = std::make_unique<Gnss_Crypto>(crtFilePath, merkleFilePath); d_helper = std::make_unique<Osnma_Helper>(); // register OSNMA input message port from telemetry blocks this->message_port_register_in(pmt::mp("OSNMA_from_TLM")); @@ -101,13 +101,13 @@ 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: Subframe received starting at " - << "WN=" - << nma_msg->WN_sf0 - << ", TOW=" - << nma_msg->TOW_sf0 - << ", from satellite " - << sat; + output_message << "Galileo OSNMA: complete OSNMA message received starting at " + << "WN=" + << nma_msg->WN_sf0 + << ", TOW=" + << nma_msg->TOW_sf0 + << ", from satellite " + << sat; LOG(WARNING) << output_message.str(); std::cout << output_message.str() << std::endl; @@ -125,14 +125,14 @@ void osnma_msg_receiver::msg_handler_osnma(const pmt::pmt_t& msg) // 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 @@ -322,8 +322,8 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr<OSNMA_msg { d_tags_allowed = tags_to_verify::all; d_tags_to_verify = {0, 4, 12}; - LOG(INFO) << "Galileo OSNMA: time constraint OK (" << delta_T; - LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS; + LOG(INFO) << "Galileo OSNMA: time constraint OK ( delta_T=" << delta_T << " s)"; +// LOG(INFO) << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << " d_GST_SIS: " << d_GST_SIS; // std::cout << "( |local_t - GST_SIS| < T_L ) [ |" << static_cast<int>(d_receiver_time - d_GST_SIS)<< " | < " << static_cast<int>(d_T_L) << " ]" << std::endl; // TODO set flag to false to avoid processing dsm and MACK messages @@ -914,13 +914,25 @@ void osnma_msg_receiver::process_mack_message() bool ret = verify_macseq(*mack); if (ret || d_flag_debug) { + LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa; for (std::size_t i = 0; i < mack->tag_and_info.size(); ++i) { // add tags of current mack to the verification queue auto& tag = mack->tag_and_info[i]; Tag t(tag, mack->TOW, mack->WN, mack->PRNa, i + 2); // tag0 (mack header) has CTR1, so first tag of MTI has CTR = 2. d_tags_awaiting_verify.insert(std::pair<uint32_t, Tag>(mack->TOW, t)); - LOG(WARNING) << "Galileo OSNMA: MACSEQ verification :: SUCCESS for Mack at TOW=" << mack->TOW << ", PRN" << mack->PRNa; + LOG(INFO) << "Galileo OSNMA: Add Tag Id= " + << t.tag_id + << ", value=0x" << std::setfill('0') << std::setw(10) << std::hex << std::uppercase + << t.received_tag << std::dec + << ", TOW=" + << t.TOW + << ", ADKD=" + << static_cast<unsigned>(t.ADKD) + << ", PRNa=" + << static_cast<unsigned>(t.PRNa) + << ", PRNd=" + << static_cast<unsigned>(t.PRN_d); } std::cout << "Galileo OSNMA: d_tags_awaiting_verify :: size: " << d_tags_awaiting_verify.size() << std::endl; mack = d_macks_awaiting_MACSEQ_verification.erase(mack); @@ -1070,6 +1082,11 @@ bool osnma_msg_receiver::verify_dsm_pkr(DSM_PKR_message message) bool osnma_msg_receiver::verify_tag(Tag& tag) { + // 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; // TODO case tag0, to be verified here?, PRNd not needed for it // build message std::vector<uint8_t> m = build_message(tag); @@ -1077,9 +1094,16 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) std::vector<uint8_t> mac; std::vector<uint8_t> applicable_key; if (tag.ADKD == 0 || tag.ADKD == 4) - applicable_key = d_tesla_keys[tag.TOW + 30]; - else // ADKD 12 - applicable_key = d_tesla_keys[tag.TOW + 330]; + { + applicable_key = d_tesla_keys[tag.TOW + 30]; + LOG(INFO) << "|---> Galileo OSNMA :: applicable key: 0x" << d_helper->convert_to_hex_string(applicable_key) << "TOW="<<static_cast<int>(tag.TOW + 30); + } + 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="<<static_cast<int>(tag.TOW + 330); + } + if (d_osnma_data.d_dsm_kroot_message.mf == 0) // C: HMAC-SHA-256 { @@ -1142,7 +1166,7 @@ bool osnma_msg_receiver::verify_tag(Tag& tag) << ", PRNa=" << static_cast<unsigned>(tag.PRNa) << ", PRNd=" - << static_cast<unsigned>(tag.PRN_d); + << static_cast<unsigned>(tag.PRN_d) << std::endl; return true; } return false; @@ -1171,10 +1195,12 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag) 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<int>(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<int>(tag.PRN_d) << ", TOW=" << tag.TOW - 30 <<"): 0b" << applicable_nav_data; } else LOG(WARNING) << "Galileo OSNMA :: Tag verification :: unknown ADKD"; @@ -1484,7 +1510,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) 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; + //LOG(INFO) << "Galileo OSNMA: hasData = true " << std::endl; std::map<uint32_t, NavData>& tow_map = prn_it->second; auto tow_it = tow_map.find(t.TOW - 30); if (tow_it != tow_map.end()) @@ -1500,7 +1526,7 @@ bool osnma_msg_receiver::tag_has_nav_data_available(Tag& t) else { // PRN was not found - LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl; + //LOG(INFO) << "Galileo OSNMA: hasData = false " << std::endl; return false; } return false; @@ -1519,7 +1545,7 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t) auto it = d_tesla_keys.find(t.TOW + 30); if (it != d_tesla_keys.end()) { - LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; + //LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; return true; } } @@ -1528,11 +1554,11 @@ bool osnma_msg_receiver::tag_has_key_available(Tag& t) auto it = d_tesla_keys.find(t.TOW + 330); if (it != d_tesla_keys.end()) { - LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; + //LOG(INFO) << "Galileo OSNMA: hasKey = true " << std::endl; return true; } } - LOG(INFO) << "Galileo OSNMA: hasKey = false "; + //LOG(INFO) << "Galileo OSNMA: hasKey = false "; return false; } @@ -1601,6 +1627,6 @@ std::vector<uint8_t> osnma_msg_receiver::hash_chain(uint32_t num_of_hashes_neede // compare computed current key against received key auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsed = end - start; - LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds."; +// LOG(INFO) << "Galileo OSNMA: TESLA verification (" << num_of_hashes_needed << " hashes) took " << elapsed.count() << " seconds."; return K_II; } diff --git a/src/core/libs/osnma_msg_receiver.h b/src/core/libs/osnma_msg_receiver.h index 4e662ef55..aef9fd91e 100644 --- a/src/core/libs/osnma_msg_receiver.h +++ b/src/core/libs/osnma_msg_receiver.h @@ -59,7 +59,7 @@ public: ~osnma_msg_receiver() = default; //!< Default destructor private: friend osnma_msg_receiver_sptr osnma_msg_receiver_make(const std::string& pemFilePath, const std::string& merkleFilePath); - osnma_msg_receiver(const std::string& pemFilePath, const std::string& merkleFilePath); + osnma_msg_receiver(const std::string& crtFilePath, const std::string& merkleFilePath); void msg_handler_osnma(const pmt::pmt_t& msg); void process_osnma_message(const std::shared_ptr<OSNMA_msg>& osnma_msg); diff --git a/src/core/system_parameters/galileo_inav_message.cc b/src/core/system_parameters/galileo_inav_message.cc index baa140149..a8509db23 100644 --- a/src/core/system_parameters/galileo_inav_message.cc +++ b/src/core/system_parameters/galileo_inav_message.cc @@ -1417,7 +1417,7 @@ OSNMA_msg Galileo_Inav_Message::get_osnma_msg() nma_position_filled = std::array<int8_t, 15>{}; // Fill TOW and WN nma_msg.WN_sf0 = WN_0; - int32_t TOW_sf0 = TOW_5 - 24; // according to OS SIS ICD, TOW of word 5 is 25 seconds after Sf start + int32_t TOW_sf0 = TOW_5 - 25;//- 24; // according to OS SIS ICD, TOW of word 5 is 25 seconds after Sf start TODO review if (TOW_sf0 < 0) { TOW_sf0 += 604800; diff --git a/src/core/system_parameters/osnma_helper.cc b/src/core/system_parameters/osnma_helper.cc index aa338f408..7cf3165c2 100644 --- a/src/core/system_parameters/osnma_helper.cc +++ b/src/core/system_parameters/osnma_helper.cc @@ -16,6 +16,8 @@ #include "osnma_helper.h" #include <bitset> +#include <iomanip> +#include <ios> uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const { @@ -74,3 +76,12 @@ std::string Osnma_Helper::verification_status_str(int status) default: return "UNKNOWN"; } } +std::string Osnma_Helper::convert_to_hex_string(const std::vector<uint8_t>& vector) +{ + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (auto byte : vector) { + ss << std::setw(2) << static_cast<int>(byte); + } + return ss.str(); +} diff --git a/src/core/system_parameters/osnma_helper.h b/src/core/system_parameters/osnma_helper.h index 2f8df078b..e78fdba0f 100644 --- a/src/core/system_parameters/osnma_helper.h +++ b/src/core/system_parameters/osnma_helper.h @@ -30,6 +30,7 @@ public: std::vector<uint8_t> gst_to_uint8(uint32_t GST) const; std::vector<uint8_t> bytes(const std::string& binaryString); std::string verification_status_str(int status); + std::string convert_to_hex_string(const std::vector<uint8_t>& vector); }; #endif // GNSS_SDR_OSNMA_HELPER_H 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 35cb9fd45..7b94baf0c 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 @@ -2,6 +2,7 @@ #include <bitset> #include <filesystem> #include <fstream> +#include <logging.h> #include <osnma_msg_receiver.h> #include <vector> @@ -14,42 +15,39 @@ struct TestVector }; // TODO - parametrize class for different configurations (config_1, config_2, etc.. potentially 5 or 6 more) an make sure wont affect current TEST_F +// note: until the test is parametrized for configuration 1 and 2, in order to change between them you have to comment/uncomment the respective calls in this test, identified with comments // conf. 1/2 +// log_name, input_time, crtFilePath, merkleFilePath, testVectors class OsnmaMsgReceiverTest : public ::testing::Test { protected: osnma_msg_receiver_sptr osnma; - Galileo_Inav_Message galileo_message; - uint8_t page_position_in_inav_subframe; - bool flag_CRC_test; - std::string page_even; OSNMA_msg osnma_msg{}; std::array<int8_t, 15> nma_position_filled; - uint32_t d_GST_SIS{}; // 16 AUG 2023 05 00 01 + uint32_t d_GST_SIS{}; uint32_t TOW{}; uint32_t WN{}; - std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm - const uint32_t LEAP_SECONDS = 0; // 13 + 5; + std::tm GST_START_EPOCH = {0, 0, 0, 22, 8 - 1, 1999 - 1900, 0}; // months start with 0 and years since 1900 in std::tm + const uint32_t LEAP_SECONDS = 0; //13 + 5; void set_time(std::tm& input); - // std::string log_name {"CONFIG1-2023-08-23-PKID1-OSNMA"}; - std::string log_name{"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; - // void initializeGoogleLog(); +// std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"}; + std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; + void initializeGoogleLog(); void SetUp() override { - flag_CRC_test = false; // TODO what for? - page_even = ""; - - // std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; - std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; + initializeGoogleLog(); +// std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; // conf. 1 + std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; // conf. 2 set_time(input_time); - // std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.pem"; - // std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml"; - std::string pemFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.pem"; +// std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230803105952_newPKID_1.crt"; // conf. 1 +// std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230803105953_newPKID_1.xml"; + std::string crtFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_PublicKey_20230720113300_newPKID_2.crt"; // conf. 2 std::string merkleFilePath = "/home/cgm/CLionProjects/osnma/data/OSNMA_MerkleTree_20230720113300_newPKID_2.xml"; - osnma = osnma_msg_receiver_make(pemFilePath, merkleFilePath); + osnma = osnma_msg_receiver_make(crtFilePath, merkleFilePath); } public: + static std::vector<uint8_t> parseNavBits(const std::string& hex); static std::vector<TestVector> readTestVectorsFromFile(const std::string& filename); std::string bytes_to_str(const std::vector<uint8_t>& bytes); @@ -57,85 +55,199 @@ public: }; -TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) +TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0) { + // Arrange + // ---------- + // m0 + std::vector<uint8_t> expected_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 + }; + + uint32_t TOW_Tag0 = 345660; + uint32_t TOW_NavData = TOW_Tag0 - 30; + uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; + uint32_t WN = 1248; + uint32_t PRNa = 2; + uint8_t CTR = 1; + + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; + osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; + osnma->d_osnma_data.d_nma_header.nmas = 0b10; + + MACK_tag_and_info MTI; + MTI.tag = static_cast<uint64_t>(0xE37BC4F858); + MTI.tag_info.PRN_d = 0x02; + MTI.tag_info.ADKD = 0x00; + MTI.tag_info.cop = 0x0F; + Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); + + + + // Act + // ---------- + auto computed_message = osnma->build_message(t0); + + + // Assert + // ---------- + ASSERT_TRUE(computed_message == expected_message); + +} + +TEST_F(OsnmaMsgReceiverTest, TagVerification) { + // Arrange + // ---------- + // Tag0 + uint32_t TOW_Tag0 = 345660; + uint32_t TOW_NavData = TOW_Tag0 - 30; + uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30 ; + uint32_t WN = 1248; + uint32_t PRNa = 2; + uint8_t CTR = 1; + + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; + osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; + osnma->d_osnma_data.d_nma_header.nmas = 0b10; + + MACK_tag_and_info MTI; + MTI.tag = static_cast<uint64_t>(0xE37BC4F858); + MTI.tag_info.PRN_d = 0x02; + MTI.tag_info.ADKD = 0x00; + MTI.tag_info.cop = 0x0F; + Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); + + + + // Act + // ---------- + bool result_tag0 = osnma->verify_tag(t0); + + + + + + // Assert + // ---------- + //ASSERT_TRUE(result_tag0); + + // Tag3 + uint32_t TOW_Tag3 = 345660; + uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30; + uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30 ; + WN = 1248; + PRNa = 2; + CTR = 3; + + osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit + osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 + osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; + osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 = + "111111111111111111111111111111110000000000000000000000010001001001001000" + "111000001000100111100010010111111111011110111111111001001100000100000000"; + osnma->d_osnma_data.d_nma_header.nmas = 0b10; + + MTI.tag = static_cast<uint64_t>(0x7BB238C883); + MTI.tag_info.PRN_d = 0x02; + MTI.tag_info.ADKD = 0x04; + MTI.tag_info.cop = 0x0F; + Tag t3(MTI, TOW_Tag0, WN, PRNa, CTR); + + bool result_tag3 = osnma->verify_tag(t3); + + ASSERT_TRUE(result_tag0 && result_tag3); + +} + +TEST_F(OsnmaMsgReceiverTest, TeslaKeyVerification) { // Arrange // ---------- osnma->d_tesla_key_verified = false; - osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30 - osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits + osnma->d_osnma_data.d_dsm_kroot_message.kroot = {0x5B, 0xF8, 0xC9, 0xCB, 0xFC, 0xF7, 0x04, 0x22, 0x08, 0x14, 0x75, 0xFD, 0x44, 0x5D, 0xF0, 0xFF}; // Kroot, TOW 345570 GST_0 - 30 + osnma->d_osnma_data.d_dsm_kroot_message.ks = 4; // TABLE 10 --> 128 bits osnma->d_osnma_data.d_dsm_kroot_message.alpha = 0x610BDF26D77B; // local_time_verification would do this operation. TODO - eliminate duplication. osnma->d_GST_SIS = (1248 & 0x00000FFF) << 20 | (345630 & 0x000FFFFF); - osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) - osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630; + osnma->d_GST_0 = ((1248 & 0x00000FFF) << 20 | (345600 & 0x000FFFFF)); // applicable time (GST_Kroot + 30) + osnma->d_receiver_time = osnma->d_GST_0 + 30 * std::floor((osnma->d_GST_SIS - osnma->d_GST_0) / 30); // Eq. 3 R.G.//345630; - osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600, {0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference. - std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2 + osnma->d_tesla_keys.insert((std::pair<uint32_t, std::vector<uint8_t>>(345600,{0xEF, 0xF9, 0x99, 0x04, 0x0E, 0x19, 0xB5, 0x70, 0x83, 0x50, 0x60, 0xBE, 0xBD, 0x23, 0xED, 0x92}))); // K1, not needed, just for reference. + std::vector<uint8_t> key = {0x2D, 0xC3, 0xA3, 0xCD, 0xB1, 0x17, 0xFA, 0xAD, 0xB8, 0x3B, 0x5F, 0x0B, 0x6F, 0xEA, 0x88, 0xEB}; // K2 uint32_t TOW = 345630; + + + // Act // ---------- bool result = osnma->verify_tesla_key(key, TOW); + + + + // Assert // ---------- ASSERT_TRUE(result); -} +} TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) { - // initializeGoogleLog(); // Arrange // ---------- - // std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); - std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv"); - if (testVectors.empty()) - { +// std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); // conf. 1 + std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/27_JUL_2023_GST_00_00_01.csv"); // conf. 2 + if (testVectors.empty()){ ASSERT_TRUE(false); } bool end_of_hex_stream{false}; int offset_byte{0}; - int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size - const int SIZE_PAGE_BYTES{240 / 8}; // total bytes of a page - const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe - const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES * SIZE_SUBFRAME_PAGES}; // total bytes of a subframe - const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds + int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size + const int SIZE_PAGE_BYTES{240/8}; // total bytes of a page + const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe + const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; // total bytes of a subframe + const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds const int DUMMY_PAGE{63}; bool flag_dummy_page{false}; - std::cout << "OsnmaTestVectorsSimulation:" - << " d_GST_SIS= " << d_GST_SIS - << ", TOW=" << TOW - << ", WN=" << WN << std::endl; + std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS + << ", TOW=" << TOW + << ", WN=" << WN << std::endl; + + + // Act // ---------- // loop over all bytes of data. Note: all TestVectors have same amount of data. - while (end_of_hex_stream == false) - { + while (end_of_hex_stream == false){ // loop over all SVs, extract a subframe - for (const TestVector& tv : testVectors) - { // loop over all SVs, extract a subframe - std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) " << tv.svId << std::endl; + for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe + std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl; auto osnmaMsg_sptr = std::make_shared<OSNMA_msg>(); std::array<uint8_t, 15> hkroot{}; std::array<uint32_t, 15> mack{}; - byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) - std::map<uint8_t, std::bitset<128>> words; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS> + byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) + std::map<uint8_t, std::bitset<128>> words_for_OSNMA; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS> - for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe + for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe { // extract bytes of complete page (odd+even) -- extract SIZE_PAGE from tv.navBits, starting from byte_index - std::vector<uint8_t> page_bytes = extract_page_bytes(tv, byte_index, SIZE_PAGE_BYTES); - if (page_bytes.empty()) - { - std::cout << "OsnmaTestVectorsSimulation: end of TestVectors \n" - << "byte_index=" << byte_index << " expected= " << 432000 / 8 << std::endl; + std::vector<uint8_t> page_bytes = extract_page_bytes(tv,byte_index,SIZE_PAGE_BYTES); + if(page_bytes.empty()){ + std::cout<< "OsnmaTestVectorsSimulation: end of TestVectors \n" << "byte_index="<<byte_index<< " expected= " << 432000/8 << std::endl; end_of_hex_stream = true; break; } @@ -143,37 +255,33 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) std::string page_bits = bytes_to_str(page_bytes); // Extract the 40 OSNMA bits starting from the 18th bit std::string even_page = page_bits.substr(0, page_bits.size() / 2); - ; - std::string odd_page = page_bits.substr(page_bits.size() / 2); - if (even_page.size() < 120 || odd_page.size() < 120) - { - std::cout << "OsnmaTestVectorsSimulation: error parsing pages" << std::endl; + std::string odd_page = page_bits.substr( page_bits.size() / 2); + if(even_page.size() < 120 || odd_page.size() < 120 ){ + std::cout<< "OsnmaTestVectorsSimulation: error parsing pages" << std::endl; } bool even_odd_OK = even_page[0] == '0' && odd_page[0] == '1'; bool page_type_OK = even_page[1] == '0' && odd_page[1] == '0'; bool tail_bits_OK = even_page.substr(even_page.size() - 6) == "000000" && odd_page.substr(odd_page.size() - 6) == "000000"; - if (!even_odd_OK || !page_type_OK || !tail_bits_OK) - std::cerr << "OsnmaTestVectorsSimulation: error parsing pages." << std::endl; + if(!even_odd_OK || !page_type_OK || !tail_bits_OK) + std::cerr<< "OsnmaTestVectorsSimulation: error parsing pages." << std::endl; - std::bitset<112> data_k(even_page.substr(2, 112)); - std::bitset<16> data_j(odd_page.substr(2, 16)); + std::bitset<112> data_k(even_page.substr(2,112)); + std::bitset<16> data_j(odd_page.substr(2,16)); std::bitset<112> shifted_data_k = data_k; - // uint8_t word_type = 0; - // for(int i = 0; i < 6; ++i) { - // word_type |= (data_k[104 + i] << i); - // } - uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word - std::cout << "OsnmaTestVectorsSimulation: received Word " << static_cast<int>(word_type) << std::endl; - if ((word_type >= 1 && word_type <= 5) || word_type == 6 || word_type == 10) + uint8_t word_type = static_cast<uint8_t>((shifted_data_k >>= 106).to_ulong()); // word type is the first 6 bits of the word + std::cout<< "OsnmaTestVectorsSimulation: received Word "<< static_cast<int>(word_type) << std::endl; + if( (word_type >= 1 && word_type <=5) || word_type == 6 || word_type == 10) { // store raw word std::bitset<128> data_combined(data_k.to_string() + data_j.to_string()); - words[word_type] = data_combined; + words_for_OSNMA[word_type] = data_combined; } - if (word_type == DUMMY_PAGE) + if(word_type == DUMMY_PAGE) flag_dummy_page = true; + // place it into osnma object. std::bitset<40> osnmaBits(odd_page.substr(18, 40)); + // Extract bits for hkroot and mack std::bitset<8> hkrootBits(osnmaBits.to_string().substr(0, 8)); std::bitset<32> mackBits(osnmaBits.to_string().substr(8, 32)); @@ -183,13 +291,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) byte_index += SIZE_PAGE_BYTES; } - std::cout << "----------" << std::endl; - if (end_of_hex_stream) + std::cout<< "----------" << std::endl; + if(end_of_hex_stream) break; - if (flag_dummy_page) - { + if(flag_dummy_page){ flag_dummy_page = false; - continue; // skip this SV + continue; // skip this SV } // Fill osnma object @@ -197,26 +304,26 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) osnmaMsg_sptr->mack = mack; osnmaMsg_sptr->TOW_sf0 = d_GST_SIS & 0x000FFFFF; - osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20; - osnmaMsg_sptr->PRN = tv.svId; // PRNa + osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ; + osnmaMsg_sptr->PRN = tv.svId; // PRNa // TODO - refactor this logic, currently it is split - // check if words 1--> 5 words are received => fill EphClockStatus data vector + // check if words_for_OSNMA 1--> 5 words_for_OSNMA are received => fill EphClockStatus data vector bool ephClockStatusWordsReceived = true; for (int i = 1; i <= 5; ++i) { - if (words.find(i) == words.end()) + if (words_for_OSNMA.find(i) == words_for_OSNMA.end()) { ephClockStatusWordsReceived = false; - std::cerr << "OsnmaTestVectorsSimulation: error parsing words 1->5. " - "Word " - << i << " should be received for each subframe but was not." << std::endl; + std::cerr<< "OsnmaTestVectorsSimulation: error parsing words_for_OSNMA 1->5. " + "Word "<< i << " should be received for each subframe but was not." << std::endl; } } // extract bits as needed by osnma block - if (ephClockStatusWordsReceived) + if(ephClockStatusWordsReceived) { + // Define the starting position and length of bits to extract for each word std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = { {1, {6, 120}}, @@ -226,41 +333,41 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) {5, {6, 67}}, }; - // Fill NavData bits -- Iterate over the extraction parameters // Fill NavData bits -- Iterate over the extraction parameters + // Fill NavData bits -- Iterate over the extraction parameters std::string nav_data_ADKD_0_12 = ""; - for (const auto& param : extractionParams) - { + for (const auto& param : extractionParams) { uint8_t wordKey = param.first; uint8_t start = param.second.first; uint8_t length = param.second.second; // Extract the required bits and fill osnma block - nav_data_ADKD_0_12 += words[wordKey].to_string().substr(start, length); + nav_data_ADKD_0_12 += words_for_OSNMA[wordKey].to_string().substr(start, length); } // send to osnma block bool check_size_is_ok = nav_data_ADKD_0_12.size() == 549; - if (check_size_is_ok) + if(check_size_is_ok) { - std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " - << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl; - const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> + std::cout << "Galileo OSNMA: sending ADKD=0/12 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl; + const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> tv.svId, nav_data_ADKD_0_12, osnmaMsg_sptr->TOW_sf0); + LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) <<"): 0b" << nav_data_ADKD_0_12; osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); + } } // check w6 && w10 is received => fill TimingData data vector - bool timingWordsReceived = words.find(6) != words.end() && - words.find(10) != words.end(); + bool timingWordsReceived = words_for_OSNMA.find(6) != words_for_OSNMA.end() && + words_for_OSNMA.find(10) != words_for_OSNMA.end(); // extract bits as needed by osnma block - if (timingWordsReceived) - { + if(timingWordsReceived){ // Define the starting position and length of bits to extract for each word std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = { {6, {6, 99}}, - {10, {86, 42}}}; + {10, {86, 42}} + }; std::string nav_data_ADKD_4 = ""; // Fill NavData bits -- Iterate over the extraction parameters @@ -271,42 +378,42 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) uint8_t length = param.second.second; // Extract the required bits and fill osnma block - nav_data_ADKD_4 += words[wordKey].to_string().substr( - start, length); + nav_data_ADKD_4 += words_for_OSNMA[wordKey].to_string().substr(start, length); } - // send to osnma block bool check_size_is_ok = nav_data_ADKD_4.size() == 141; - if (check_size_is_ok) + if(check_size_is_ok) { - std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " - << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 << std::endl; - const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string, uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> + std::cout << "Galileo OSNMA: sending ADKD=04 navData, PRN_d (" << tv.svId << ") " << "TOW_sf=" << osnmaMsg_sptr->TOW_sf0 <<std::endl; + const auto tmp_obj_osnma = std::make_shared<std::tuple<uint32_t, std::string,uint32_t>>( // < PRNd , navDataBits, TOW_Sosf> tv.svId, nav_data_ADKD_4, osnmaMsg_sptr->TOW_sf0); + LOG(INFO) << "|---> Galileo OSNMA :: Telemetry Decoder NavData (PRN_d="<< static_cast<int>(tv.svId) << ", TOW=" << static_cast<int>(osnmaMsg_sptr->TOW_sf0) <<"): 0b" << nav_data_ADKD_4; osnma->msg_handler_osnma(pmt::make_any(tmp_obj_osnma)); + } + } // Call the handler, as if it came from telemetry decoder block auto temp_obj = pmt::make_any(osnmaMsg_sptr); - osnma->msg_handler_osnma(temp_obj); // osnma entry point + osnma->msg_handler_osnma(temp_obj); // osnma entry point } - if (!end_of_hex_stream) - { - offset_byte = byte_index; // update offset for the next subframe + if(!end_of_hex_stream){ + offset_byte = byte_index; // update offset for the next subframe d_GST_SIS += DURATION_SUBFRAME; TOW = d_GST_SIS & 0x000FFFFF; - WN = (d_GST_SIS & 0xFFF00000) >> 20; - std::cout << "OsnmaTestVectorsSimulation:" - << " d_GST_SIS= " << d_GST_SIS + WN = (d_GST_SIS & 0xFFF00000) >> 20 ; + std::cout << "OsnmaTestVectorsSimulation:" << " d_GST_SIS= " << d_GST_SIS << ", TOW=" << TOW << ", WN=" << WN << std::endl; } + + } @@ -316,24 +423,22 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation) // TODO - create global vars with failed tags and compare to total tags (Tag Id for example) } - +// Auxiliary functions for the OsnmaTestVectorsSimulation test fixture. +// Essentially, they perform same work as the telemetry decoder block, but adapted to the osnma-test-vector files. std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename) { std::ifstream file(filename); std::vector<TestVector> testVectors; - if (!file.is_open()) - { - std::cerr << "Error reading the file \"" << filename << "\" \n"; + if (!file.is_open()) { + std::cerr<<"Error reading the file \"" << filename <<"\" \n"; return testVectors; } std::string line; std::getline(file, line); - if (line != "SVID,NumNavBits,NavBitsHEX\r") - { - std::cerr << "Error parsing first line" - << "\n"; - } + if (line != "SVID,NumNavBits,NavBitsHEX\r" ){ + std::cerr<<"Error parsing first line" <<"\n"; + } while (std::getline(file, line)) { @@ -356,35 +461,29 @@ std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std: return testVectors; } - - std::vector<uint8_t> OsnmaMsgReceiverTest::parseNavBits(const std::string& hex) { std::vector<uint8_t> bytes; - for (unsigned int i = 0; i < hex.length() - 1; i += 2) + for (unsigned int i = 0; i < hex.length()-1; i += 2) { std::string byteString = hex.substr(i, 2); - uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16); + uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16); bytes.push_back(byte); } return bytes; } - - std::string OsnmaMsgReceiverTest::bytes_to_str(const std::vector<uint8_t>& bytes) { std::string bit_string; bit_string.reserve(bytes.size() * 8); - for (const auto& byte : bytes) + for(const auto& byte : bytes) { std::bitset<8> bits(byte); bit_string += bits.to_string(); } return bit_string; } - - /** * @brief Extracts a range of bytes from a TestVector's navBits vector. * @@ -413,8 +512,6 @@ std::vector<uint8_t> OsnmaMsgReceiverTest::extract_page_bytes(const TestVector& return extracted_bytes; } - - /** * @brief Sets the time based on the given input. * @@ -438,118 +535,56 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input) uint32_t sec_in_week = 7 * 24 * 60 * 60; uint32_t week_number = duration_sec.count() / sec_in_week; uint32_t time_of_week = duration_sec.count() % sec_in_week; - this->WN = week_number; - this->TOW = time_of_week + LEAP_SECONDS; + this->WN = week_number; + this->TOW = time_of_week + LEAP_SECONDS; // Return the week number and time of week as a pair // TODO: d_GST_SIS or d_receiver_time? doubt // I am assuming that local realisation of receiver is identical to SIS GST time coming from W5 or W0 - this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF); + this->d_GST_SIS = (this->WN & 0x00000FFF) << 20 | (this->TOW & 0x000FFFFF); + + } - - -TEST_F(OsnmaMsgReceiverTest, BuildTagMessageM0) +void OsnmaMsgReceiverTest::initializeGoogleLog() { - // Arrange - // ---------- - // m0 - std::vector<uint8_t> expected_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}; - - uint32_t TOW_Tag0 = 345660; - uint32_t TOW_NavData = TOW_Tag0 - 30; - uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30; - uint32_t WN = 1248; - uint32_t PRNa = 2; - uint8_t CTR = 1; - - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDB, 0xBC, 0x73}; // K4 - osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; - osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; - osnma->d_osnma_data.d_nma_header.nmas = 0b10; - - MACK_tag_and_info MTI; - MTI.tag = static_cast<uint64_t>(0xE37BC4F858); - MTI.tag_info.PRN_d = 0x02; - MTI.tag_info.ADKD = 0x00; - MTI.tag_info.cop = 0x0F; - Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); - - - // Act - // ---------- - auto computed_message = osnma->build_message(t0); - - - // Assert - // ---------- - ASSERT_TRUE(computed_message == expected_message); + google::InitGoogleLogging(log_name.c_str()); + FLAGS_minloglevel = 0; // INFO + FLAGS_logtostderr = 0; // add this line + FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/build/src/tests/logs"; + if (FLAGS_log_dir.empty()) + { + std::cout << "Logging will be written at " + << std::filesystem::temp_directory_path() + << '\n' + << "Use gnss-sdr --log_dir=/path/to/log to change that.\n"; + } + else + { + try + { + const std::filesystem::path p(FLAGS_log_dir); + if (!std::filesystem::exists(p)) + { + std::cout << "The path " + << FLAGS_log_dir + << " does not exist, attempting to create it.\n"; + std::error_code ec; + if (!std::filesystem::create_directory(p, ec)) + { + std::cout << "Could not create the " << FLAGS_log_dir << " folder.\n"; + gflags::ShutDownCommandLineFlags(); + throw std::runtime_error("Could not create folder for logs"); + } + } + std::cout << "Logging will be written at " << FLAGS_log_dir << '\n'; + } + catch (const std::exception& e) + { + std::cerr << e.what() << '\n'; + std::cerr << "Could not create the " << FLAGS_log_dir << " folder.\n"; + gflags::ShutDownCommandLineFlags(); + throw; + } + } } - -TEST_F(OsnmaMsgReceiverTest, TagVerification) -{ - // Arrange - // ---------- - // Tag0 - uint32_t TOW_Tag0 = 345660; - uint32_t TOW_NavData = TOW_Tag0 - 30; - uint32_t TOW_Key_Tag0 = TOW_Tag0 + 30; - uint32_t WN = 1248; - uint32_t PRNa = 2; - uint8_t CTR = 1; - - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag0] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 - osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; - osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = "000011101001011001000100000101000111010110100100100101100000000000011101101011001111101110101010000001010000011011111100000011101011011100101101011010101011011011001001110111101011110110111111001111001000011111101110011000111111110111111010000011101011111111110000110111000000100000001110110000110110001110000100001110101100010100110100010001000110001110011010110000111010000010000000000001101000000000000011100101100100010000000000000110110100110001111100000000000000100110100000000101010010100000001011000010001001100000011111110111111111000000000"; - osnma->d_osnma_data.d_nma_header.nmas = 0b10; - - MACK_tag_and_info MTI; - MTI.tag = static_cast<uint64_t>(0xE37BC4F858); - MTI.tag_info.PRN_d = 0x02; - MTI.tag_info.ADKD = 0x00; - MTI.tag_info.cop = 0x0F; - Tag t0(MTI, TOW_Tag0, WN, PRNa, CTR); - - - // Act - // ---------- - bool result_tag0 = osnma->verify_tag(t0); - - - // Assert - // ---------- - // ASSERT_TRUE(result_tag0); - - // Tag3 - uint32_t TOW_Tag3 = 345660; - uint32_t TOW_NavData_Tag3 = TOW_Tag3 - 30; - uint32_t TOW_Key_Tag3 = TOW_Tag0 + 30; - WN = 1248; - PRNa = 2; - CTR = 3; - - osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit - osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 - osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; - osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 = - "111111111111111111111111111111110000000000000000000000010001001001001000" - "111000001000100111100010010111111111011110111111111001001100000100000000"; - osnma->d_osnma_data.d_nma_header.nmas = 0b10; - - MTI.tag = static_cast<uint64_t>(0x7BB238C883); - MTI.tag_info.PRN_d = 0x02; - MTI.tag_info.ADKD = 0x04; - MTI.tag_info.cop = 0x0F; - Tag t3(MTI, TOW_Tag0, WN, PRNa, CTR); - - bool result_tag3 = osnma->verify_tag(t3); - - ASSERT_TRUE(result_tag0 && result_tag3); -} From c38fb0fca5756884c7f3088742226b7fa9ba64ad Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@gmail.com> Date: Fri, 28 Jun 2024 10:51:10 +0200 Subject: [PATCH 02/14] Fix building (add missing include) --- src/core/system_parameters/osnma_helper.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/system_parameters/osnma_helper.cc b/src/core/system_parameters/osnma_helper.cc index 7cf3165c2..3feeb96cf 100644 --- a/src/core/system_parameters/osnma_helper.cc +++ b/src/core/system_parameters/osnma_helper.cc @@ -18,6 +18,7 @@ #include <bitset> #include <iomanip> #include <ios> +#include <sstream> uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const { @@ -25,6 +26,7 @@ uint32_t Osnma_Helper::compute_gst(uint32_t WN, uint32_t TOW) const return GST; } + std::vector<uint8_t> Osnma_Helper::gst_to_uint8(uint32_t GST) const { std::vector<uint8_t> res; @@ -36,6 +38,7 @@ std::vector<uint8_t> Osnma_Helper::gst_to_uint8(uint32_t GST) const return res; } + /** * @brief Convert a binary string to a vector of bytes. * @@ -67,6 +70,7 @@ std::vector<uint8_t> Osnma_Helper::bytes(const std::string& binaryString) { return bytes; } + std::string Osnma_Helper::verification_status_str(int status) { switch (status) { @@ -76,6 +80,8 @@ std::string Osnma_Helper::verification_status_str(int status) default: return "UNKNOWN"; } } + + std::string Osnma_Helper::convert_to_hex_string(const std::vector<uint8_t>& vector) { std::stringstream ss; From 359693c0e88b92b0b34443a52bb3a5f19c143276 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@gmail.com> Date: Fri, 28 Jun 2024 13:03:14 +0200 Subject: [PATCH 03/14] Add GNSS-SDR.osnma_enable configuration parameter, by default set to true --- src/core/receiver/gnss_flowgraph.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index acdea9df2..af1795ee0 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -121,7 +121,7 @@ void GNSSFlowgraph::init() galileo_tow_map_ = nullptr; } - if (configuration_->property("Channels_1B.count", 0) > 0) + if (configuration_->property("Channels_1B.count", 0) > 0 && configuration_->property("GNSS-SDR.osnma_enable", true)) { enable_osnma_rx_ = true; const auto certFilePath = configuration_->property("GNSS-SDR.osnma_public_key", CRTFILE_DEFAULT); From db5466832cfeae205ee0f6f18611583dfa18f222 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sat, 29 Jun 2024 11:10:35 +0200 Subject: [PATCH 04/14] Look for OpenSSL in the first place, fallback to GnuTLS if not found Fix test building in some environments --- CMakeLists.txt | 94 +--- cmake/Modules/GnssSdrCrypto.cmake | 152 ++++++ docs/CHANGELOG.md | 9 + src/core/libs/supl/CMakeLists.txt | 13 +- src/core/libs/supl/supl.h | 14 +- src/core/system_parameters/CMakeLists.txt | 49 +- src/core/system_parameters/gnss_crypto.cc | 436 +++++++++--------- src/core/system_parameters/gnss_crypto.h | 15 +- src/tests/CMakeLists.txt | 3 + .../osnma/osnma_msg_receiver_test.cc | 54 +-- 10 files changed, 410 insertions(+), 429 deletions(-) create mode 100644 cmake/Modules/GnssSdrCrypto.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a97dee597..4264195a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2196,99 +2196,9 @@ endif() ################################################################################ -# GnuTLS - https://www.gnutls.org/ +# OpenSSL https://www.openssl.org/ or GnuTLS - https://www.gnutls.org/ ################################################################################ -find_package(GnuTLS) -set_package_properties(GnuTLS PROPERTIES - URL "https://www.gnutls.org/" - PURPOSE "Used for the SUPL protocol implementation." - TYPE REQUIRED -) -if(GnuTLS_FOUND AND GNUTLS_VERSION_STRING) - set_package_properties(GnuTLS PROPERTIES - DESCRIPTION "Transport Layer Security Library (found: v${GNUTLS_VERSION_STRING})" - ) -else() - set_package_properties(GnuTLS PROPERTIES - DESCRIPTION "Transport Layer Security Library" - ) -endif() -find_library(GNUTLS_OPENSSL_LIBRARY - NAMES gnutls-openssl libgnutls-openssl.so.27 - PATHS - /usr/lib - /usr/lib64 - /usr/lib/x86_64-linux-gnu - /usr/lib/aarch64-linux-gnu - /usr/lib/arm-linux-gnueabihf - /usr/lib/arm-linux-gnueabi - /usr/lib/i386-linux-gnu - /usr/lib/alpha-linux-gnu - /usr/lib/hppa-linux-gnu - /usr/lib/i386-gnu - /usr/lib/i686-gnu - /usr/lib/i686-linux-gnu - /usr/lib/x86_64-kfreebsd-gnu - /usr/lib/i686-kfreebsd-gnu - /usr/lib/m68k-linux-gnu - /usr/lib/mips-linux-gnu - /usr/lib/mips64el-linux-gnuabi64 - /usr/lib/mipsel-linux-gnu - /usr/lib/powerpc-linux-gnu - /usr/lib/powerpc-linux-gnuspe - /usr/lib/powerpc64-linux-gnu - /usr/lib/powerpc64le-linux-gnu - /usr/lib/s390x-linux-gnu - /usr/lib/riscv64-linux-gnu - /usr/lib/sparc64-linux-gnu - /usr/lib/x86_64-linux-gnux32 - /usr/lib/sh4-linux-gnu - /usr/lib/loongarch64-linux-gnu - /usr/local/lib - /usr/local/lib64 - /opt/local/lib -) -#if(NOT GNUTLS_OPENSSL_LIBRARY) -if(GNUTLS_OPENSSL_LIBRARY) - if(GnuTLS_FOUND) - message(STATUS " But it was not built with openssl compatibility.") - endif() - message(STATUS " Looking for OpenSSL instead...") - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) # Trick for Homebrew - endif() - find_package(OpenSSL) - set_package_properties(OpenSSL PROPERTIES - URL "https://www.openssl.org" - DESCRIPTION "Cryptography and SSL/TLS Toolkit (found: v${OPENSSL_VERSION})" - PURPOSE "Used for the SUPL protocol implementation." - TYPE REQUIRED - ) - message("OPENSSL_FOUND: " ${OPENSSL_FOUND}) - if(OPENSSL_FOUND) - set_package_properties(GnuTLS PROPERTIES - PURPOSE "Not found, but OpenSSL can replace it." - ) - set(GNUTLS_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR}) - set(GNUTLS_LIBRARIES "") - set(GNUTLS_OPENSSL_LIBRARY ${OPENSSL_SSL_LIBRARY}) - else() - message(" The GnuTLS library with openssl compatibility enabled has not been found.") - message(" You can try to install the required libraries by typing:") - if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|kFreeBSD|GNU") - if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "Red Hat") - message(" sudo yum install openssl-devel") - else() - message(" sudo apt-get install libgnutls28-dev") - endif() - endif() - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - message(" 'sudo port install gnutls', if you are using Macports, or") - message(" 'brew install openssl', if you are using Homebrew.") - endif() - message(FATAL_ERROR "GnuTLS libraries with openssl compatibility are required to build gnss-sdr") - endif() -endif() +include(GnssSdrCrypto) diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake new file mode 100644 index 000000000..33e1aaab1 --- /dev/null +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -0,0 +1,152 @@ +# GNSS-SDR is a Global Navigation Satellite System software-defined receiver. +# This file is part of GNSS-SDR. +# +# SPDX-FileCopyrightText: 2024 C. Fernandez-Prades cfernandez(at)cttc.es +# SPDX-License-Identifier: BSD-3-Clause + + +################################################################################ +# OpenSSL https://www.openssl.org/ +################################################################################ +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) # Trick for Homebrew +endif() +find_package(OpenSSL) +set_package_properties(OpenSSL + PROPERTIES + URL "https://www.openssl.org" + PURPOSE "Used for the OSNMA and SUPL protocol implementations." + TYPE REQUIRED +) +if(OPENSSL_FOUND) + set_package_properties(OpenSSL + PROPERTIES + DESCRIPTION "Cryptography and SSL/TLS Toolkit (found: v${OPENSSL_VERSION})" + ) +else() + set_package_properties(OpenSSL + PROPERTIES + DESCRIPTION "OpenSSL has not been found, but GnuTLS with openssl compatibility can replace it" + ) + ################################################################################ + # GnuTLS - https://www.gnutls.org/ + ################################################################################ + find_package(GnuTLS) + set_package_properties(GnuTLS PROPERTIES + URL "https://www.gnutls.org/" + PURPOSE "Used for the OSNMA and SUPL protocol implementations." + TYPE REQUIRED + ) + if(GnuTLS_FOUND AND GNUTLS_VERSION_STRING) + set_package_properties(GnuTLS PROPERTIES + DESCRIPTION "Transport Layer Security Library (found: v${GNUTLS_VERSION_STRING})" + ) + else() + set_package_properties(GnuTLS PROPERTIES + DESCRIPTION "Transport Layer Security Library" + ) + endif() + find_library(GNUTLS_OPENSSL_LIBRARY + NAMES gnutls-openssl libgnutls-openssl.so.27 + PATHS + /usr/lib + /usr/lib64 + /usr/lib/x86_64-linux-gnu + /usr/lib/aarch64-linux-gnu + /usr/lib/arm-linux-gnueabihf + /usr/lib/arm-linux-gnueabi + /usr/lib/i386-linux-gnu + /usr/lib/alpha-linux-gnu + /usr/lib/hppa-linux-gnu + /usr/lib/i386-gnu + /usr/lib/i686-gnu + /usr/lib/i686-linux-gnu + /usr/lib/x86_64-kfreebsd-gnu + /usr/lib/i686-kfreebsd-gnu + /usr/lib/m68k-linux-gnu + /usr/lib/mips-linux-gnu + /usr/lib/mips64el-linux-gnuabi64 + /usr/lib/mipsel-linux-gnu + /usr/lib/powerpc-linux-gnu + /usr/lib/powerpc-linux-gnuspe + /usr/lib/powerpc64-linux-gnu + /usr/lib/powerpc64le-linux-gnu + /usr/lib/s390x-linux-gnu + /usr/lib/riscv64-linux-gnu + /usr/lib/sparc64-linux-gnu + /usr/lib/x86_64-linux-gnux32 + /usr/lib/sh4-linux-gnu + /usr/lib/loongarch64-linux-gnu + /usr/local/lib + /usr/local/lib64 + /opt/local/lib + ) + + if(NOT GNUTLS_OPENSSL_LIBRARY) + message(" The GnuTLS library with openssl compatibility enabled has not been found.") + message(" You can try to install the required libraries by typing:") + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|kFreeBSD|GNU") + if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "Red Hat") + message(" sudo yum install openssl-devel") + else() + message(" sudo apt-get install libgnutls28-dev") + endif() + endif() + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(" 'sudo port install gnutls', if you are using Macports, or") + message(" 'brew install openssl', if you are using Homebrew.") + endif() + message(FATAL_ERROR "OpenSSL or the GnuTLS libraries with openssl compatibility are required to build gnss-sdr") + endif() +endif() + +################################################################################ + +function(link_to_crypto_dependencies target) + if(OPENSSL_FOUND) + if(TARGET OpenSSL::SSL) + target_link_libraries(core_system_parameters + PUBLIC + OpenSSL::SSL + ) + if(TARGET OpenSSL::Crypto) + target_link_libraries(core_system_parameters + PUBLIC + OpenSSL::Crypto + ) + endif() + else() + target_link_libraries(core_system_parameters + PUBLIC + ${OPENSSL_LIBRARIES} + "${OPENSSL_CRYPTO_LIBRARIES}" + ) + target_include_directories(core_system_parameters + PUBLIC + ${OPENSSL_INCLUDE_DIR} + ) + endif() + if(OPENSSL_VERSION) + if(OPENSSL_VERSION VERSION_GREATER "3.0.0") + target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_3=1) + else() + if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1") + target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_111=1) + else() + endif() + endif() + else() + endif() + else() # GnuTLS + target_link_libraries(core_system_parameters + PUBLIC + ${GNUTLS_LIBRARIES} + ${GNUTLS_OPENSSL_LIBRARY} + ) + target_include_directories(core_system_parameters + PUBLIC + ${GNUTLS_INCLUDE_DIR} + ) + target_compile_definitions(${target} PUBLIC -DUSE_GNUTLS_FALLBACK=1) + endif() +endfunction() diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e7e594fb9..1812c76b7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -55,6 +55,15 @@ All notable changes to GNSS-SDR will be documented in this file. This change has a downside in maintainability, since the source code becomes plagued with preprocessor directives required to maintain compatibility both with gflags and glog, and with Abseil. +- Historically, GNSS-SDR linked against the GnuTLS library for cryptographic + functions. If GnuTLS was not found, then the building system looked for and + linked against OpenSSL as a fallback. This was due to the OpenSSL 1.x dual + license scheme, which was incompatible with GPL v3.0 license, preventing it + from being a mandatory dependency for GNSS-SDR in most GNU/Linux + distributions. This issue was solved with the release of OpenSSL 3.0.0, which + transitioned to the Apache License 2.0, fully compatible with GPL v3.0. + Accordingly, the GNSS-SDR building system now looks for OpenSSL in the first + place and, if not found, then it looks for GnuTLS as a fallback. ### Improvements in Usability: diff --git a/src/core/libs/supl/CMakeLists.txt b/src/core/libs/supl/CMakeLists.txt index 743852047..78ab2b80e 100644 --- a/src/core/libs/supl/CMakeLists.txt +++ b/src/core/libs/supl/CMakeLists.txt @@ -46,16 +46,9 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU" AND (CMAKE_VERSION VERSION_GREATER "3 target_compile_options(core_libs_supl PUBLIC $<$<COMPILE_LANGUAGE:C>:${MY_C_FLAGS}>) endif() -if(OPENSSL_FOUND) - target_compile_definitions(core_libs_supl PUBLIC -DUSE_OPENSSL_FALLBACK=1) -endif() -message("OPENSSL_FOUND: " ${OPENSSL_FOUND}) -message("USE_OPENSSL_FALLBACK:" ${USE_OPENSSL_FALLBACK}) -target_link_libraries(core_libs_supl - PUBLIC - ${GNUTLS_LIBRARIES} - ${GNUTLS_OPENSSL_LIBRARY} -) +# links to the appropriate library and defines +# USE_GNUTLS_FALLBACK, USE_OPENSSL_3, or USE_OPENSSL_111 accordingly. +link_to_crypto_dependencies(core_libs_supl) target_include_directories(core_libs_supl PUBLIC diff --git a/src/core/libs/supl/supl.h b/src/core/libs/supl/supl.h index c879112f6..8c9bef533 100644 --- a/src/core/libs/supl/supl.h +++ b/src/core/libs/supl/supl.h @@ -24,18 +24,18 @@ #define EXPORT #endif // clang-format off -#if USE_OPENSSL_FALLBACK -#include <openssl/crypto.h> -#include <openssl/x509.h> -#include <openssl/pem.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#else +#if USE_GNUTLS_FALLBACK #include <gnutls/gnutls.h> #include <gnutls/compat.h> #include <gnutls/crypto.h> #include <gnutls/openssl.h> #include <gnutls/x509.h> +#else +#include <openssl/crypto.h> +#include <openssl/x509.h> +#include <openssl/pem.h> +#include <openssl/ssl.h> +#include <openssl/err.h> #endif // clang-format on #include <PDU.h> diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt index 0ef4cf22e..055ff256e 100644 --- a/src/core/system_parameters/CMakeLists.txt +++ b/src/core/system_parameters/CMakeLists.txt @@ -124,7 +124,7 @@ target_link_libraries(core_system_parameters Boost::date_time Boost::serialization PRIVATE - Pugixml::pugixml + Pugixml::pugixml ) if(ENABLE_GLOG_AND_GFLAGS) @@ -140,50 +140,9 @@ target_include_directories(core_system_parameters ${GNSSSDR_SOURCE_DIR}/src/algorithms/libs ) -if(OPENSSL_FOUND) - message("OPENSSL_FOUND: " ${OPENSSL_FOUND}) - if(TARGET OpenSSL::SSL) - target_link_libraries(core_system_parameters - PUBLIC - OpenSSL::SSL - ) - else() - target_link_libraries(core_system_parameters - PUBLIC - ${OPENSSL_LIBRARIES} - ) - target_include_directories(core_system_parameters - PUBLIC - ${OPENSSL_INCLUDE_DIR} - ) - endif() - if(OPENSSL_VERSION) - message("OPENSSL_VERSION: " ${OPENSSL_VERSION}) - if(OPENSSL_VERSION VERSION_GREATER "3.0.0") - target_compile_definitions(core_system_parameters PUBLIC -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_3=1) - message("USE_OPENSSL_3: " ${DUSE_OPENSSL_3}) - message("USE_OPENSSL_FALLBACK:" ${USE_OPENSSL_FALLBACK}) - else() - if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1") - target_compile_definitions(core_system_parameters PRIVATE -DUSE_OPENSSL_FALLBACK=1 -DUSE_OPENSSL_111=1) - endif() - endif() - endif() - -else() - target_link_libraries(core_system_parameters - PUBLIC - ${GNUTLS_LIBRARIES} - ${GNUTLS_OPENSSL_LIBRARY} - ) - target_include_directories(core_system_parameters - PUBLIC - ${GNUTLS_INCLUDE_DIR} - ) -endif() -if(OPENSSL_FOUND) - target_compile_definitions(core_system_parameters PUBLIC -DUSE_OPENSSL_FALLBACK=1) -endif() +# links to the appropriate library and defines +# USE_GNUTLS_FALLBACK, USE_OPENSSL_3, or USE_OPENSSL_111 accordingly. +link_to_crypto_dependencies(core_system_parameters) if(ENABLE_CLANG_TIDY) if(CLANG_TIDY_EXE) diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 0f1774271..a50e2f00b 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -25,7 +25,12 @@ #include <iostream> #include <iterator> -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK +#include <cstring> +#include <gnutls/abstract.h> +#include <gnutls/crypto.h> +#include <gnutls/x509.h> +#else // OpenSSL #include <openssl/cmac.h> #include <openssl/ecdsa.h> #include <openssl/hmac.h> @@ -40,14 +45,9 @@ #include <openssl/param_build.h> #include <openssl/params.h> #define OPENSSL_ENGINE nullptr -#else +#else // OpenSSL 1.x #include <openssl/sha.h> #endif -#else // GnuTLS -#include <cstring> -#include <gnutls/abstract.h> -#include <gnutls/crypto.h> -#include <gnutls/x509.h> #endif #if USE_GLOG_AND_GFLAGS @@ -59,28 +59,28 @@ Gnss_Crypto::Gnss_Crypto() { -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + gnutls_global_init(); +#else // OpenSSL #if !(USE_OPENSSL_3 || USE_OPENSSL_111) LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL" << " and rebuild GNSS-SDR against it."; #endif -#else // GnuTLS - gnutls_global_init(); #endif } Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& merkleTreePath) { -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + gnutls_global_init(); +#else // OpenSSL #if !(USE_OPENSSL_3 || USE_OPENSSL_111) LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of OpenSSL" << " and rebuild GNSS-SDR against it."; #endif -#else // GnuTLS - gnutls_global_init(); #endif if (!readPublicKeyFromCRT(certFilePath)) { @@ -92,31 +92,30 @@ Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& mer Gnss_Crypto::~Gnss_Crypto() { -#if USE_OPENSSL_FALLBACK -#if USE_OPENSSL_3 -#else - if (d_PublicKey != nullptr) - { - EC_KEY_free(d_PublicKey); - } -#endif -#else // GnuTLS +#if USE_GNUTLS_FALLBACK if (d_PublicKey != nullptr) { gnutls_pubkey_deinit(d_PublicKey); d_PublicKey = nullptr; } gnutls_global_deinit(); +#else // OpenSSL +#if !USE_OPENSSL_3 + if (d_PublicKey != nullptr) + { + EC_KEY_free(d_PublicKey); + } +#endif #endif } bool Gnss_Crypto::have_public_key() const { -#if USE_OPENSSL_FALLBACK - return (d_PublicKey != nullptr); -#else // GnuTLS +#if USE_GNUTLS_FALLBACK return (d_PublicKey != gnutls_pubkey_t{}); +#else // OpenSSL + return (d_PublicKey != nullptr); #endif } @@ -260,7 +259,15 @@ void Gnss_Crypto::read_merkle_xml(const std::string& merkleFilePath) std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& input) const { std::vector<uint8_t> output(32); // SHA256 hash size -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + std::vector<uint8_t> output_aux(32); + gnutls_hash_hd_t hashHandle; + gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256); + gnutls_hash(hashHandle, input.data(), input.size()); + gnutls_hash_output(hashHandle, output_aux.data()); + output = output_aux; + gnutls_hash_deinit(hashHandle, output_aux.data()); +#else // OpenSSL #if USE_OPENSSL_3 unsigned int mdLen; EVP_MD_CTX* mdCtx = EVP_MD_CTX_new(); @@ -283,20 +290,12 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu return output; } EVP_MD_CTX_free(mdCtx); -#else +#else // OpenSSL 1.x SHA256_CTX sha256Context; SHA256_Init(&sha256Context); SHA256_Update(&sha256Context, input.data(), input.size()); SHA256_Final(output.data(), &sha256Context); #endif -#else // GnuTLS - std::vector<uint8_t> output_aux(32); - gnutls_hash_hd_t hashHandle; - gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA256); - gnutls_hash(hashHandle, input.data(), input.size()); - gnutls_hash_output(hashHandle, output_aux.data()); - output = output_aux; - gnutls_hash_deinit(hashHandle, output_aux.data()); #endif return output; } @@ -305,7 +304,15 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA256(const std::vector<uint8_t>& inpu std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& input) const { std::vector<uint8_t> output(32); // SHA256 hash size -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + std::vector<uint8_t> output_aux(32); + gnutls_hash_hd_t hashHandle; + gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256); + gnutls_hash(hashHandle, input.data(), input.size()); + gnutls_hash_output(hashHandle, output_aux.data()); + output = output_aux; + gnutls_hash_deinit(hashHandle, output_aux.data()); +#else // OpenSSL #if USE_OPENSSL_3 || USE_OPENSSL_111 EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); const EVP_MD* md = EVP_sha3_256(); @@ -314,21 +321,13 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in EVP_DigestUpdate(mdctx, input.data(), input.size()); EVP_DigestFinal_ex(mdctx, output.data(), nullptr); EVP_MD_CTX_free(mdctx); -#else +#else // OpenSSL 1.x // SHA3-256 not implemented in OpenSSL 1.0, it was introduced in OpenSSL 1.1.1 if (!input.empty()) { // do nothing } #endif -#else // GnuTLS - std::vector<uint8_t> output_aux(32); - gnutls_hash_hd_t hashHandle; - gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256); - gnutls_hash(hashHandle, input.data(), input.size()); - gnutls_hash_output(hashHandle, output_aux.data()); - output = output_aux; - gnutls_hash_deinit(hashHandle, output_aux.data()); #endif return output; } @@ -337,7 +336,15 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const { std::vector<uint8_t> output(32); -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + std::vector<uint8_t> output_aux(32); + gnutls_hmac_hd_t hmac; + gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size()); + gnutls_hmac(hmac, input.data(), input.size()); + gnutls_hmac_output(hmac, output_aux.data()); + output = output_aux; + gnutls_hmac_deinit(hmac, output_aux.data()); +#else // OpenSSL #if USE_OPENSSL_3 std::vector<uint8_t> hmac(EVP_MAX_MD_SIZE); size_t output_length = 0; @@ -393,7 +400,7 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t> EVP_MAC_free(mac); hmac.resize(output_length); output = hmac; -#else +#else // OpenSSL 1.x unsigned int outputLength = EVP_MAX_MD_SIZE; unsigned char* result = HMAC(EVP_sha256(), key.data(), key.size(), input.data(), input.size(), output.data(), &outputLength); if (result == nullptr) @@ -405,14 +412,6 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t> // Resize the output vector to the actual length of the HMAC-SHA256 output output.resize(outputLength); #endif -#else // GnuTLS - std::vector<uint8_t> output_aux(32); - gnutls_hmac_hd_t hmac; - gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size()); - gnutls_hmac(hmac, input.data(), input.size()); - gnutls_hmac_output(hmac, output_aux.data()); - output = output_aux; - gnutls_hmac_deinit(hmac, output_aux.data()); #endif return output; } @@ -421,7 +420,18 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t> std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& key, const std::vector<uint8_t>& input) const { std::vector<uint8_t> output(16); -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + gnutls_cipher_hd_t cipher; + std::vector<uint8_t> mac(16); + std::vector<uint8_t> message = input; + gnutls_datum_t key_data = {const_cast<uint8_t*>(key.data()), static_cast<unsigned int>(key.size())}; + gnutls_cipher_init(&cipher, GNUTLS_CIPHER_AES_128_CBC, &key_data, nullptr); + gnutls_cipher_set_iv(cipher, nullptr, 16); // Set IV to zero + gnutls_cipher_encrypt(cipher, message.data(), message.size()); // Encrypt the message with AES-128 + gnutls_cipher_tag(cipher, mac.data(), mac.size()); // Get the CMAC-AES tag + output = mac; + gnutls_cipher_deinit(cipher); +#else // OpenSSL #if USE_OPENSSL_3 std::vector<uint8_t> aux(EVP_MAX_MD_SIZE); // CMAC-AES output size size_t output_length = 0; @@ -479,7 +489,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke aux.resize(output_length); output = aux; -#else +#else // OpenSSL 1.x std::vector<uint8_t> mac(16); // CMAC-AES output size // Create CMAC context @@ -495,17 +505,6 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke output = mac; #endif -#else // GnuTLS - gnutls_cipher_hd_t cipher; - std::vector<uint8_t> mac(16); - std::vector<uint8_t> message = input; - gnutls_datum_t key_data = {const_cast<uint8_t*>(key.data()), static_cast<unsigned int>(key.size())}; - gnutls_cipher_init(&cipher, GNUTLS_CIPHER_AES_128_CBC, &key_data, nullptr); - gnutls_cipher_set_iv(cipher, nullptr, 16); // Set IV to zero - gnutls_cipher_encrypt(cipher, message.data(), message.size()); // Encrypt the message with AES-128 - gnutls_cipher_tag(cipher, mac.data(), mac.size()); // Get the CMAC-AES tag - output = mac; - gnutls_cipher_deinit(cipher); #endif return output; } @@ -526,27 +525,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) return; } std::string pemContent((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>()); -#if USE_OPENSSL_FALLBACK - // Create a BIO object from the string data - BIO* bio = BIO_new_mem_buf(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; - return; - } -#if USE_OPENSSL_3 - d_PublicKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); -#else - d_PublicKey = PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr); -#endif - BIO_free(bio); - 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"; - return; - } -#else // GnuTLS +#if USE_GNUTLS_FALLBACK // Import the PEM data gnutls_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(pemContent.data())), static_cast<unsigned int>(pemContent.size())}; gnutls_pubkey_t pubkey; @@ -566,6 +545,26 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) pubkey_copy(pubkey, &d_PublicKey); gnutls_pubkey_deinit(pubkey); +#else // OpenSSL + // Create a BIO object from the string data + BIO* bio = BIO_new_mem_buf(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; + return; + } +#if USE_OPENSSL_3 + d_PublicKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr); +#else // OpenSSL 1.x + d_PublicKey = PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr); +#endif + BIO_free(bio); + 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"; + return; + } #endif std::cout << "OSNMA Public key successfully read from file " << pemFilePath << std::endl; LOG(INFO) << "OSNMA Public key successfully read from file " << pemFilePath; @@ -574,57 +573,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) { -#if USE_OPENSSL_FALLBACK - // Open the .crt file - std::ifstream crtFile(crtFilePath, std::ios::binary); - if (!crtFile.is_open()) - { - std::cerr << "Unable to open file: " << crtFilePath << std::endl; - return false; - } - - // Read certificate - std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>()); - BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size()); - if (!bio) - { - std::cerr << "Unable to create BIO for file: " << crtFilePath << std::endl; - return false; - } - X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); - if (!cert) - { - std::cerr << "Unable to read certificate from file: " << crtFilePath << std::endl; - BIO_free(bio); - return false; - } - - // Read the public key from the certificate - EVP_PKEY* pubkey = X509_get_pubkey(cert); -#if USE_OPENSSL_3 - if (!pubkey) - { - std::cerr << "Failed to extract the public key" << std::endl; - X509_free(cert); - return false; - } - pubkey_copy(pubkey, &d_PublicKey); - EVP_PKEY_free(pubkey); -#else - EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey); - EVP_PKEY_free(pubkey); - if (!ec_pubkey) - { - std::cerr << "Failed to extract the public key" << std::endl; - X509_free(cert); - return false; - } - pubkey_copy(ec_pubkey, &d_PublicKey); - EC_KEY_free(ec_pubkey); -#endif - BIO_free(bio); - X509_free(cert); -#else // GnuTLS +#if USE_GNUTLS_FALLBACK // Open the .crt file std::ifstream crtFile(crtFilePath, std::ios::binary); if (!crtFile.is_open()) @@ -664,6 +613,56 @@ bool Gnss_Crypto::readPublicKeyFromCRT(const std::string& crtFilePath) pubkey_copy(pubkey, &d_PublicKey); gnutls_x509_crt_deinit(cert); gnutls_pubkey_deinit(pubkey); +#else // OpenSSL + // Open the .crt file + std::ifstream crtFile(crtFilePath, std::ios::binary); + if (!crtFile.is_open()) + { + std::cerr << "Unable to open file: " << crtFilePath << std::endl; + return false; + } + + // Read certificate + std::vector<char> buffer((std::istreambuf_iterator<char>(crtFile)), std::istreambuf_iterator<char>()); + BIO* bio = BIO_new_mem_buf(buffer.data(), buffer.size()); + if (!bio) + { + std::cerr << "Unable to create BIO for file: " << crtFilePath << std::endl; + return false; + } + X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); + if (!cert) + { + std::cerr << "Unable to read certificate from file: " << crtFilePath << std::endl; + BIO_free(bio); + return false; + } + + // Read the public key from the certificate + EVP_PKEY* pubkey = X509_get_pubkey(cert); +#if USE_OPENSSL_3 + if (!pubkey) + { + std::cerr << "Failed to extract the public key" << std::endl; + X509_free(cert); + return false; + } + pubkey_copy(pubkey, &d_PublicKey); + EVP_PKEY_free(pubkey); +#else // OpenSSL 1.x + EC_KEY* ec_pubkey = EVP_PKEY_get1_EC_KEY(pubkey); + EVP_PKEY_free(pubkey); + if (!ec_pubkey) + { + std::cerr << "Failed to extract the public key" << std::endl; + X509_free(cert); + return false; + } + pubkey_copy(ec_pubkey, &d_PublicKey); + EC_KEY_free(ec_pubkey); +#endif + BIO_free(bio); + X509_free(cert); #endif std::cout << "OSNMA Public key successfully read from file " << crtFilePath << std::endl; LOG(INFO) << "OSNMA Public key successfully read from file " << crtFilePath; @@ -680,7 +679,32 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st return false; } bool success = false; -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + // Convert signature to DER format + std::vector<uint8_t> 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<unsigned char*>(digest.data()), static_cast<unsigned int>(digest.size())}; + gnutls_datum_t der_sig_data = {der_sig.data(), static_cast<unsigned int>(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); + } +#else // OpenSSL #if USE_OPENSSL_3 EVP_PKEY_CTX* ctx; ctx = EVP_PKEY_CTX_new(d_PublicKey, nullptr); @@ -753,7 +777,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st std::cerr << "OpenSSL: OSNMA message authentication failed: " << err << std::endl; LOG(WARNING) << "OpenSSL: OSNMA message authentication failed: " << err; } -#else +#else // OpenSSL 1.x std::vector<uint8_t> der_sig; if (!convert_raw_to_der_ecdsa(signature, der_sig)) { @@ -777,31 +801,6 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st LOG(WARNING) << "OpenSSL: OSNMA message authentication failed"; } #endif -#else // GnuTLS - // Convert signature to DER format - std::vector<uint8_t> 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<unsigned char*>(digest.data()), static_cast<unsigned int>(digest.size())}; - gnutls_datum_t der_sig_data = {der_sig.data(), static_cast<unsigned int>(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 return success; } @@ -845,7 +844,21 @@ std::vector<uint8_t> Gnss_Crypto::getMerkleRoot(const std::vector<std::vector<ui void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey) { -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + gnutls_pubkey_t pubkey; + gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(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(publicKey.data(), publicKey.size()); @@ -876,22 +889,8 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey) return; } EC_KEY_free(ec_pkey); -#endif +#endif // OpenSSL 1.x EVP_PKEY_free(pkey); -#else // GnuTLS - gnutls_pubkey_t pubkey; - gnutls_datum_t pemDatum = {const_cast<unsigned char*>(publicKey.data()), static_cast<unsigned int>(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); #endif LOG(INFO) << "OSNMA Public Key successfully set up."; } @@ -945,7 +944,40 @@ bool Gnss_Crypto::convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signa } -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK // GnuTLS-specific functions +bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) +{ + gnutls_datum_t key_datum; + + // Export the public key from src to memory + int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum); + if (ret < 0) + { + gnutls_free(key_datum.data); + return false; + } + + // Initialize dest + ret = gnutls_pubkey_init(dest); + if (ret < 0) + { + gnutls_free(key_datum.data); + return false; + } + + // Import the public key data from key_datum to dest + ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM); + gnutls_free(key_datum.data); + + if (ret < 0) + { + gnutls_pubkey_deinit(*dest); + return false; + } + + return true; +} +#else // OpenSSL #if USE_OPENSSL_3 bool Gnss_Crypto::pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest) { @@ -1036,41 +1068,5 @@ bool Gnss_Crypto::pubkey_copy(EC_KEY* src, EC_KEY** dest) return true; } - #endif - -#else // GnuTLS-specific functions - -bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) -{ - gnutls_datum_t key_datum; - - // Export the public key from src to memory - int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum); - if (ret < 0) - { - gnutls_free(key_datum.data); - return false; - } - - // Initialize dest - ret = gnutls_pubkey_init(dest); - if (ret < 0) - { - gnutls_free(key_datum.data); - return false; - } - - // Import the public key data from key_datum to dest - ret = gnutls_pubkey_import(*dest, &key_datum, GNUTLS_X509_FMT_PEM); - gnutls_free(key_datum.data); - - if (ret < 0) - { - gnutls_pubkey_deinit(*dest); - return false; - } - - return true; -} #endif diff --git a/src/core/system_parameters/gnss_crypto.h b/src/core/system_parameters/gnss_crypto.h index bbcac1afa..7e0527750 100644 --- a/src/core/system_parameters/gnss_crypto.h +++ b/src/core/system_parameters/gnss_crypto.h @@ -22,10 +22,10 @@ #include <cstdint> #include <string> #include <vector> -#if USE_OPENSSL_FALLBACK -#include <openssl/ec.h> -#else +#if USE_GNUTLS_FALLBACK #include <gnutls/gnutls.h> +#else // OpenSSL +#include <openssl/ec.h> #endif /** \addtogroup Core @@ -60,7 +60,10 @@ private: bool readPublicKeyFromCRT(const std::string& crtFilePath); bool convert_raw_to_der_ecdsa(const std::vector<uint8_t>& raw_signature, std::vector<uint8_t>& der_signature) const; std::vector<uint8_t> convert_from_hex_str(const std::string& input) const; -#if USE_OPENSSL_FALLBACK +#if USE_GNUTLS_FALLBACK + bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest); + gnutls_pubkey_t d_PublicKey{}; +#else // OpenSSL #if USE_OPENSSL_3 bool pubkey_copy(EVP_PKEY* src, EVP_PKEY** dest); EVP_PKEY* d_PublicKey{}; @@ -68,9 +71,6 @@ private: bool pubkey_copy(EC_KEY* src, EC_KEY** dest); EC_KEY* d_PublicKey = nullptr; #endif -#else // GnuTLS - bool pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest); - gnutls_pubkey_t d_PublicKey{}; #endif std::vector<uint8_t> d_x_4_0; std::vector<uint8_t> d_x_3_1; @@ -82,4 +82,5 @@ private: /** \} */ /** \} */ + #endif // GNSS_SDR_GNSS_CRYPTO_H \ No newline at end of file diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 8de611f5f..f1491b032 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1367,6 +1367,9 @@ if(NOT ENABLE_PACKAGING AND NOT ENABLE_FPGA) GTest::GTest GTest::Main core_libs + Gnuradio::blocks + Gnuradio::runtime + Gnuradio::filter # workaround for old systems ) if(ENABLE_GLOG_AND_GFLAGS) target_link_libraries(osnma_msg_receiver_test PRIVATE Gflags::gflags Glog::glog) 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 7b94baf0c..743c2b877 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 @@ -1,11 +1,14 @@ #include <gtest/gtest.h> #include <bitset> -#include <filesystem> #include <fstream> -#include <logging.h> -#include <osnma_msg_receiver.h> #include <vector> +#include "osnma_msg_receiver.h" +#if USE_GLOG_AND_GFLAGS +#include <glog/logging.h> // for LOG +#else +#include <absl/log/log.h> +#endif struct TestVector { @@ -31,11 +34,9 @@ protected: void set_time(std::tm& input); // std::string log_name {"CONFIG1-2023-08-16-PKID1-OSNMA"}; std::string log_name {"CONFIG2-2023-07-27-PKID2-MT2-OSNMA"}; - void initializeGoogleLog(); void SetUp() override { - initializeGoogleLog(); // std::tm input_time = {0, 0, 5, 16, 8 - 1, 2023 - 1900, 0}; // conf. 1 std::tm input_time = {0, 0, 0, 27, 7 - 1, 2023 - 1900, 0}; // conf. 2 set_time(input_time); @@ -545,46 +546,3 @@ void OsnmaMsgReceiverTest::set_time(std::tm& input) } -void OsnmaMsgReceiverTest::initializeGoogleLog() -{ - google::InitGoogleLogging(log_name.c_str()); - FLAGS_minloglevel = 0; // INFO - FLAGS_logtostderr = 0; // add this line - FLAGS_log_dir = "/home/cgm/CLionProjects/osnma/build/src/tests/logs"; - if (FLAGS_log_dir.empty()) - { - std::cout << "Logging will be written at " - << std::filesystem::temp_directory_path() - << '\n' - << "Use gnss-sdr --log_dir=/path/to/log to change that.\n"; - } - else - { - try - { - const std::filesystem::path p(FLAGS_log_dir); - if (!std::filesystem::exists(p)) - { - std::cout << "The path " - << FLAGS_log_dir - << " does not exist, attempting to create it.\n"; - std::error_code ec; - if (!std::filesystem::create_directory(p, ec)) - { - std::cout << "Could not create the " << FLAGS_log_dir << " folder.\n"; - gflags::ShutDownCommandLineFlags(); - throw std::runtime_error("Could not create folder for logs"); - } - } - std::cout << "Logging will be written at " << FLAGS_log_dir << '\n'; - } - catch (const std::exception& e) - { - std::cerr << e.what() << '\n'; - std::cerr << "Could not create the " << FLAGS_log_dir << " folder.\n"; - gflags::ShutDownCommandLineFlags(); - throw; - } - } -} - From a530981d5bc7fb97b09e8f76fa28da50880fbff0 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sat, 29 Jun 2024 11:41:28 +0200 Subject: [PATCH 05/14] Update README.md with openssl --- README.md | 30 ++++++++++++++---------------- cmake/Modules/GnssSdrCrypto.cmake | 2 +- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index a904764b0..5b7bc9dfd 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ information about this open-source, software-defined GNSS receiver. - [Install Armadillo, a C++ linear algebra library](#install-armadillo-a-c-linear-algebra-library) - [Install Gflags, a commandline flags processing module for C++](#install-gflags-a-commandline-flags-processing-module-for-c) - [Install Glog, a library that implements application-level logging](#install-glog-a-library-that-implements-application-level-logging) - - [Install the GnuTLS or OpenSSL libraries](#install-the-gnutls-or-openssl-libraries) + - [Install the OpenSSL libraries](#install-the-openssl-libraries) - [Install Matio, MATLAB MAT file I/O library](#install-matio-matlab-mat-file-io-library) - [Install Protocol Buffers, a portable mechanism for serialization of structured data](#install-protocol-buffers-a-portable-mechanism-for-serialization-of-structured-data) - [Install Pugixml, a light-weight C++ XML processing library](#install-pugixml-a-light-weight-c-xml-processing-library) @@ -168,16 +168,19 @@ $ sudo apt-get install build-essential cmake git pkg-config libboost-dev libboos libboost-system-dev libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev \ libboost-serialization-dev liblog4cpp5-dev libuhd-dev gnuradio-dev gr-osmosdr \ libblas-dev liblapack-dev libarmadillo-dev libgflags-dev libgoogle-glog-dev \ - libgnutls-openssl-dev libpcap-dev libmatio-dev libpugixml-dev libgtest-dev \ - libprotobuf-dev protobuf-compiler python3-mako + libssl-dev libpcap-dev libmatio-dev libpugixml-dev libgtest-dev \ + libprotobuf-dev libcpu-features-dev protobuf-compiler python3-mako ``` Please note that the required files from `libgtest-dev` were named `googletest` in Debian 9 "stretch" and Ubuntu 18.04 "bionic", and renamed to `libgtest-dev` in Debian 10 "buster" and above. -Since Ubuntu 21.04 Hirsute / Debian 11, the package `libcpu-features-dev` is -also required. +In distributions older than Ubuntu 21.04 Hirsute / Debian 11, the package +`libcpu-features-dev` is not required. + +In distributions older than Ubuntu 22.04 Jammy / Debian 12, the package +`libssl-dev` must be replaced by `libgnutls-openssl-dev`. **Note for Ubuntu 14.04 LTS "trusty" users:** you will need to build from source and install GNU Radio manually, as explained below, since GNSS-SDR requires @@ -451,20 +454,15 @@ Please note that Glog is replaced by the [Abseil Logging Library](https://abseil.io/docs/cpp/guides/logging) if Abseil >= v20240116 is available in your system. -#### Install the GnuTLS or OpenSSL libraries +#### Install the OpenSSL libraries ``` -$ sudo apt-get install libgnutls-openssl-dev # For Debian/Ubuntu/LinuxMint -$ sudo yum install openssl-devel # For Fedora/CentOS/RHEL -$ sudo zypper install openssl-devel # For OpenSUSE -$ sudo pacman -S openssl # For Arch Linux +$ sudo apt-get install libssl-dev # For Debian/Ubuntu/LinuxMint +$ sudo yum install openssl-devel # For Fedora/CentOS/RHEL +$ sudo zypper install openssl-devel # For OpenSUSE +$ sudo pacman -S openssl # For Arch Linux ``` -In case the [GnuTLS](https://www.gnutls.org/ "GnuTLS's Homepage") library with -openssl extensions package is not available in your GNU/Linux distribution, -GNSS-SDR can also work well with -[OpenSSL](https://www.openssl.org/ "OpenSSL's Homepage"). - #### Install [Matio](https://github.com/tbeu/matio "Matio's Homepage"), MATLAB MAT file I/O library ``` @@ -838,7 +836,7 @@ In a terminal, type: ``` $ sudo port selfupdate $ sudo port upgrade outdated -$ sudo port install armadillo cmake pkgconfig protobuf3-cpp pugixml gnutls +$ sudo port install armadillo cmake pkgconfig protobuf3-cpp pugixml openssl3 $ sudo port install gnuradio +uhd +grc +zeromq $ sudo port install boost matio libad9361-iio libiio $ sudo port install py311-mako diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index 33e1aaab1..c873c6bc3 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -93,7 +93,7 @@ else() endif() endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - message(" 'sudo port install gnutls', if you are using Macports, or") + message(" 'sudo port install openssl3', if you are using Macports, or") message(" 'brew install openssl', if you are using Homebrew.") endif() message(FATAL_ERROR "OpenSSL or the GnuTLS libraries with openssl compatibility are required to build gnss-sdr") From 609b85b8641b7603f2a2d0b5411be0504bd126b0 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sat, 29 Jun 2024 11:45:00 +0200 Subject: [PATCH 06/14] Fix cmakelint formatting --- cmake/Modules/GnssSdrCrypto.cmake | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index c873c6bc3..7c427bab2 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -20,12 +20,12 @@ set_package_properties(OpenSSL ) if(OPENSSL_FOUND) set_package_properties(OpenSSL - PROPERTIES + PROPERTIES DESCRIPTION "Cryptography and SSL/TLS Toolkit (found: v${OPENSSL_VERSION})" ) else() set_package_properties(OpenSSL - PROPERTIES + PROPERTIES DESCRIPTION "OpenSSL has not been found, but GnuTLS with openssl compatibility can replace it" ) ################################################################################ @@ -114,7 +114,7 @@ function(link_to_crypto_dependencies target) PUBLIC OpenSSL::Crypto ) - endif() + endif() else() target_link_libraries(core_system_parameters PUBLIC @@ -131,10 +131,9 @@ function(link_to_crypto_dependencies target) target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_3=1) else() if(NOT OPENSSL_VERSION VERSION_LESS "1.1.1") - target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_111=1) - else() + target_compile_definitions(${target} PUBLIC -DUSE_OPENSSL_111=1) endif() - endif() + endif() else() endif() else() # GnuTLS From 668ca7a5d8d6db1aa3c57bc6920c04064239544f Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sat, 29 Jun 2024 11:52:06 +0200 Subject: [PATCH 07/14] Fix link_to_crypto_dependencies function --- cmake/Modules/GnssSdrCrypto.cmake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index 7c427bab2..67648d702 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -105,23 +105,23 @@ endif() function(link_to_crypto_dependencies target) if(OPENSSL_FOUND) if(TARGET OpenSSL::SSL) - target_link_libraries(core_system_parameters + target_link_libraries(${target} PUBLIC OpenSSL::SSL ) if(TARGET OpenSSL::Crypto) - target_link_libraries(core_system_parameters + target_link_libraries(${target} PUBLIC OpenSSL::Crypto ) endif() else() - target_link_libraries(core_system_parameters + target_link_libraries(${target} PUBLIC ${OPENSSL_LIBRARIES} "${OPENSSL_CRYPTO_LIBRARIES}" ) - target_include_directories(core_system_parameters + target_include_directories(${target} PUBLIC ${OPENSSL_INCLUDE_DIR} ) @@ -137,12 +137,12 @@ function(link_to_crypto_dependencies target) else() endif() else() # GnuTLS - target_link_libraries(core_system_parameters + target_link_libraries(${target} PUBLIC ${GNUTLS_LIBRARIES} ${GNUTLS_OPENSSL_LIBRARY} ) - target_include_directories(core_system_parameters + target_include_directories(${target} PUBLIC ${GNUTLS_INCLUDE_DIR} ) From 22b6d703185b85bcb5e41213d13a4f345fbe2478 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sun, 30 Jun 2024 09:45:51 +0200 Subject: [PATCH 08/14] Fix building of benchmarks in some environments --- src/tests/benchmarks/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/benchmarks/CMakeLists.txt b/src/tests/benchmarks/CMakeLists.txt index 133174871..28bddd050 100644 --- a/src/tests/benchmarks/CMakeLists.txt +++ b/src/tests/benchmarks/CMakeLists.txt @@ -104,10 +104,15 @@ macro(add_benchmark) ) endmacro() +set(EXTRA_BENCHMARK_DEPENDENCIES "") +if(ENABLE_GLOG_AND_GFLAGS) + set(EXTRA_BENCHMARK_DEPENDENCIES "Gflags::gflags;Glog::glog") +endif() + add_benchmark(benchmark_copy) -add_benchmark(benchmark_preamble core_system_parameters) -add_benchmark(benchmark_detector core_system_parameters) -add_benchmark(benchmark_reed_solomon core_system_parameters) +add_benchmark(benchmark_preamble core_system_parameters ${EXTRA_BENCHMARK_DEPENDENCIES}) +add_benchmark(benchmark_detector core_system_parameters ${EXTRA_BENCHMARK_DEPENDENCIES}) +add_benchmark(benchmark_reed_solomon core_system_parameters ${EXTRA_BENCHMARK_DEPENDENCIES}) add_benchmark(benchmark_atan2 Gnuradio::runtime) if(has_std_plus_void) From 413e5309ba9ed29772c46d06da9517953d746ee7 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sun, 30 Jun 2024 10:10:03 +0200 Subject: [PATCH 09/14] Add missing include --- .../signal-processing-blocks/osnma/osnma_msg_receiver_test.cc | 1 + 1 file changed, 1 insertion(+) 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 743c2b877..dc3e69684 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 @@ -1,5 +1,6 @@ #include <gtest/gtest.h> #include <bitset> +#include <chrono> #include <fstream> #include <vector> #include "osnma_msg_receiver.h" From d984822b453d7ba3fdac7182bebead653aecd985 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sun, 30 Jun 2024 10:24:21 +0200 Subject: [PATCH 10/14] Fix for cross-compilation --- src/core/libs/osnma_msg_receiver.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libs/osnma_msg_receiver.cc b/src/core/libs/osnma_msg_receiver.cc index 45ad958ee..955712c76 100644 --- a/src/core/libs/osnma_msg_receiver.cc +++ b/src/core/libs/osnma_msg_receiver.cc @@ -317,7 +317,7 @@ void osnma_msg_receiver::local_time_verification(const std::shared_ptr<OSNMA_msg // std::cout << "Galileo OSNMA: d_receiver_time: " << d_receiver_time << std::endl; } // verify time constraint - std::time_t delta_T = abs(d_receiver_time - d_GST_SIS); + std::time_t delta_T = std::abs(static_cast<int64_t>(d_receiver_time - d_GST_SIS)); if (delta_T <= d_T_L) { d_tags_allowed = tags_to_verify::all; From c2bb06076af3dc20b819a0cdc75fc2c2f0a2bb4a Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Sun, 30 Jun 2024 12:04:57 +0200 Subject: [PATCH 11/14] Fix for old OpenSSL --- src/core/system_parameters/gnss_crypto.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index a50e2f00b..322e4acdd 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -547,7 +547,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) gnutls_pubkey_deinit(pubkey); #else // OpenSSL // Create a BIO object from the string data - BIO* bio = BIO_new_mem_buf(pemContent.c_str(), pemContent.length()); + BIO* bio = BIO_new_mem_buf(const_cast<char*>(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; @@ -861,7 +861,7 @@ void Gnss_Crypto::set_public_key(const std::vector<uint8_t>& publicKey) #else // OpenSSL BIO* bio = nullptr; EVP_PKEY* pkey = nullptr; - bio = BIO_new_mem_buf(publicKey.data(), publicKey.size()); + bio = BIO_new_mem_buf(const_cast<uint8_t*>(publicKey.data()), publicKey.size()); if (!bio) { std::cerr << "Failed to create BIO for key \n"; From 95e3329f1011779628bd75baf97f99035c7ff3fb Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Mon, 1 Jul 2024 01:31:09 +0200 Subject: [PATCH 12/14] Fix for old GnuTLS --- cmake/Modules/GnssSdrCrypto.cmake | 37 +++++++++++++++++++ src/core/system_parameters/gnss_crypto.cc | 45 +++++++++++++++++------ src/core/system_parameters/gnss_crypto.h | 1 + 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index 67648d702..a5e383790 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -82,6 +82,15 @@ else() /opt/local/lib ) + find_path(GNUTLS_INCLUDE_DIR NAMES gnutls/gnutls.h + PATHS + /usr/include + /usr/local/include + /opt/local/include # default location in Macports + /opt/homebrew/opt/gnutls/include/ + ${GNUTLS_ROOT_DIR}/include/ + ) + if(NOT GNUTLS_OPENSSL_LIBRARY) message(" The GnuTLS library with openssl compatibility enabled has not been found.") message(" You can try to install the required libraries by typing:") @@ -98,6 +107,22 @@ else() endif() message(FATAL_ERROR "OpenSSL or the GnuTLS libraries with openssl compatibility are required to build gnss-sdr") endif() + + # Test GnuTLS capabilities + file(READ "${GNUTLS_INCLUDE_DIR}/gnutls/gnutls.h" gnutls_gnutls_file_contents) + if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_SIGN_ECDSA_SHA256") + set(GNUTLS_SIGN_ECDSA_SHA256 TRUE) + endif() + if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_DIG_SHA3_256") + set(GNUTLS_DIG_SHA3_256 TRUE) + endif() + if("${gnutls_gnutls_file_contents}" MATCHES "#define GNUTLS_VERSION_MAJOR 2") + set(GNUTLS_HMAC_INIT_WITH_DIGEST TRUE) + endif() + file(READ "${GNUTLS_INCLUDE_DIR}/gnutls/abstract.h" gnutls_abstract_file_contents) + if("${gnutls_abstract_file_contents}" MATCHES "gnutls_pubkey_export2") + set(GNUTLS_PUBKEY_EXPORT2 TRUE) + endif() endif() ################################################################################ @@ -147,5 +172,17 @@ function(link_to_crypto_dependencies target) ${GNUTLS_INCLUDE_DIR} ) target_compile_definitions(${target} PUBLIC -DUSE_GNUTLS_FALLBACK=1) + if(GNUTLS_SIGN_ECDSA_SHA256) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_SIGN_ECDSA_SHA256=1) + endif() + if(GNUTLS_DIG_SHA3_256) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_DIG_SHA3_256=1) + endif() + if(GNUTLS_PUBKEY_EXPORT2) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_PUBKEY_EXPORT2=1) + endif() + if(GNUTLS_HMAC_INIT_WITH_DIGEST) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_HMAC_INIT_WITH_DIGEST=1) + endif() endif() endfunction() diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 322e4acdd..8ad7e55bb 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -27,7 +27,6 @@ #if USE_GNUTLS_FALLBACK #include <cstring> -#include <gnutls/abstract.h> #include <gnutls/crypto.h> #include <gnutls/x509.h> #else // OpenSSL @@ -61,6 +60,11 @@ Gnss_Crypto::Gnss_Crypto() { #if USE_GNUTLS_FALLBACK gnutls_global_init(); +#if !HAVE_GNUTLS_SIGN_ECDSA_SHA256 + LOG(WARNING) << "The GnuTLS library version you are linking against is too old for some OSNMA functions." + << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of GnuTLS or OpenSSL" + << " and rebuild GNSS-SDR against it."; +#endif #else // OpenSSL #if !(USE_OPENSSL_3 || USE_OPENSSL_111) LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." @@ -75,6 +79,11 @@ Gnss_Crypto::Gnss_Crypto(const std::string& certFilePath, const std::string& mer { #if USE_GNUTLS_FALLBACK gnutls_global_init(); +#if !HAVE_GNUTLS_SIGN_ECDSA_SHA256 + LOG(WARNING) << "The GnuTLS library version you are linking against is too old for some OSNMA functions." + << " Please do not trust OSNMA ouputs or upgrade your system to a newer version of GnuTLS or OpenSSL" + << " and rebuild GNSS-SDR against it."; +#endif #else // OpenSSL #if !(USE_OPENSSL_3 || USE_OPENSSL_111) LOG(WARNING) << "The OpenSSL library version you are linking against is too old for some OSNMA functions." @@ -305,6 +314,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in { std::vector<uint8_t> output(32); // SHA256 hash size #if USE_GNUTLS_FALLBACK +#if HAVE_GNUTLS_DIG_SHA3_256 std::vector<uint8_t> output_aux(32); gnutls_hash_hd_t hashHandle; gnutls_hash_init(&hashHandle, GNUTLS_DIG_SHA3_256); @@ -312,6 +322,7 @@ std::vector<uint8_t> Gnss_Crypto::computeSHA3_256(const std::vector<uint8_t>& in gnutls_hash_output(hashHandle, output_aux.data()); output = output_aux; gnutls_hash_deinit(hashHandle, output_aux.data()); +#endif #else // OpenSSL #if USE_OPENSSL_3 || USE_OPENSSL_111 EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); @@ -339,7 +350,11 @@ std::vector<uint8_t> Gnss_Crypto::computeHMAC_SHA_256(const std::vector<uint8_t> #if USE_GNUTLS_FALLBACK std::vector<uint8_t> output_aux(32); gnutls_hmac_hd_t hmac; +#if HAVE_GNUTLS_HMAC_INIT_WITH_DIGEST + gnutls_hmac_init(&hmac, GNUTLS_DIG_SHA256, key.data(), key.size()); +#else gnutls_hmac_init(&hmac, GNUTLS_MAC_SHA256, key.data(), key.size()); +#endif gnutls_hmac(hmac, input.data(), input.size()); gnutls_hmac_output(hmac, output_aux.data()); output = output_aux; @@ -421,16 +436,15 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke { std::vector<uint8_t> output(16); #if USE_GNUTLS_FALLBACK - gnutls_cipher_hd_t cipher; - std::vector<uint8_t> mac(16); - std::vector<uint8_t> message = input; - gnutls_datum_t key_data = {const_cast<uint8_t*>(key.data()), static_cast<unsigned int>(key.size())}; - gnutls_cipher_init(&cipher, GNUTLS_CIPHER_AES_128_CBC, &key_data, nullptr); - gnutls_cipher_set_iv(cipher, nullptr, 16); // Set IV to zero - gnutls_cipher_encrypt(cipher, message.data(), message.size()); // Encrypt the message with AES-128 - gnutls_cipher_tag(cipher, mac.data(), mac.size()); // Get the CMAC-AES tag - output = mac; - gnutls_cipher_deinit(cipher); + // CMAC-AES not implemented in GnuTLS + if (!key.empty()) + { + // do nothing + } + if (!input.empty()) + { + // do nothing + } #else // OpenSSL #if USE_OPENSSL_3 std::vector<uint8_t> aux(EVP_MAX_MD_SIZE); // CMAC-AES output size @@ -527,7 +541,7 @@ void Gnss_Crypto::readPublicKeyFromPEM(const std::string& pemFilePath) std::string pemContent((std::istreambuf_iterator<char>(pemFile)), std::istreambuf_iterator<char>()); #if USE_GNUTLS_FALLBACK // Import the PEM data - gnutls_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(pemContent.data())), static_cast<unsigned int>(pemContent.size())}; + gnutls_datum_t pemDatum = {const_cast<unsigned char*>(reinterpret_cast<unsigned char*>(const_cast<char*>(pemContent.data()))), static_cast<unsigned int>(pemContent.size())}; gnutls_pubkey_t pubkey; gnutls_pubkey_init(&pubkey); @@ -680,6 +694,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st } bool success = false; #if USE_GNUTLS_FALLBACK +#if HAVE_GNUTLS_SIGN_ECDSA_SHA256 // Convert signature to DER format std::vector<uint8_t> der_sig; if (!convert_raw_to_der_ecdsa(signature, der_sig)) @@ -704,6 +719,7 @@ bool Gnss_Crypto::verify_signature(const std::vector<uint8_t>& message, const st 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; @@ -950,7 +966,12 @@ bool Gnss_Crypto::pubkey_copy(gnutls_pubkey_t src, gnutls_pubkey_t* dest) gnutls_datum_t key_datum; // Export the public key from src to memory +#if HAVE_GNUTLS_PUBKEY_EXPORT2 int ret = gnutls_pubkey_export2(src, GNUTLS_X509_FMT_PEM, &key_datum); +#else + size_t output_stata_size; + int ret = gnutls_pubkey_export(src, GNUTLS_X509_FMT_PEM, &key_datum, &output_stata_size); +#endif if (ret < 0) { gnutls_free(key_datum.data); diff --git a/src/core/system_parameters/gnss_crypto.h b/src/core/system_parameters/gnss_crypto.h index 7e0527750..69df8d45d 100644 --- a/src/core/system_parameters/gnss_crypto.h +++ b/src/core/system_parameters/gnss_crypto.h @@ -23,6 +23,7 @@ #include <string> #include <vector> #if USE_GNUTLS_FALLBACK +#include <gnutls/abstract.h> #include <gnutls/gnutls.h> #else // OpenSSL #include <openssl/ec.h> From 2f475d6aafbe01113fcb75f8e80a95036ee18b3a Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Mon, 1 Jul 2024 02:44:22 +0200 Subject: [PATCH 13/14] Fix CMAC-AES algorithm for OpenSSL 1.x --- src/core/system_parameters/gnss_crypto.cc | 37 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 8ad7e55bb..2062b0674 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -504,20 +504,45 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke aux.resize(output_length); output = aux; #else // OpenSSL 1.x - std::vector<uint8_t> mac(16); // CMAC-AES output size + size_t mac_length = 0; // to hold the length of the MAC output // Create CMAC context CMAC_CTX* cmacCtx = CMAC_CTX_new(); - CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr); + if (!cmacCtx) + { + LOG(INFO) << "OSNMA CMAC-AES: Failed to create CMAC context"; + return output; + } - // Compute CMAC-AES - CMAC_Update(cmacCtx, input.data(), input.size()); - CMAC_Final(cmacCtx, mac.data(), nullptr); + // Initialize the CMAC context with the key and cipher + if (1 != CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr)) + { + LOG(INFO) << "OSNMA CMAC-AES: MAC_Init failed"; + CMAC_CTX_free(cmacCtx); + return output; + } + + // Compute the CMAC + if (1 != CMAC_Update(cmacCtx, input.data(), input.size())) + { + LOG(INFO) << "OSNMA CMAC-AES: CMAC_Update failed"; + CMAC_CTX_free(cmacCtx); + return output; + } + + // Finalize the CMAC computation and retrieve the output + if (1 != CMAC_Final(cmacCtx, output.data(), &mac_length)) + { + LOG(INFO) << "OSNMA CMAC-AES:CMAC_Final failed"; + CMAC_CTX_free(cmacCtx); + return output; + } // Clean up CMAC context CMAC_CTX_free(cmacCtx); - output = mac; + // Ensure the output vector is properly sized according to the actual MAC length + output.resize(mac_length); #endif #endif return output; From 4b4f6b9d7f9e1a255c5109979d7d34d4d2c72578 Mon Sep 17 00:00:00 2001 From: Carles Fernandez <carles.fernandez@cttc.es> Date: Mon, 1 Jul 2024 22:43:54 +0200 Subject: [PATCH 14/14] Fix CMAC-AES with GnuTLS --- cmake/Modules/GnssSdrCrypto.cmake | 6 ++++ src/core/system_parameters/gnss_crypto.cc | 36 +++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/cmake/Modules/GnssSdrCrypto.cmake b/cmake/Modules/GnssSdrCrypto.cmake index a5e383790..9649da9da 100644 --- a/cmake/Modules/GnssSdrCrypto.cmake +++ b/cmake/Modules/GnssSdrCrypto.cmake @@ -119,6 +119,9 @@ else() if("${gnutls_gnutls_file_contents}" MATCHES "#define GNUTLS_VERSION_MAJOR 2") set(GNUTLS_HMAC_INIT_WITH_DIGEST TRUE) endif() + if("${gnutls_gnutls_file_contents}" MATCHES "GNUTLS_MAC_AES_CMAC_128") + set(GNUTLS_MAC_AES_CMAC_128 TRUE) + endif() file(READ "${GNUTLS_INCLUDE_DIR}/gnutls/abstract.h" gnutls_abstract_file_contents) if("${gnutls_abstract_file_contents}" MATCHES "gnutls_pubkey_export2") set(GNUTLS_PUBKEY_EXPORT2 TRUE) @@ -184,5 +187,8 @@ function(link_to_crypto_dependencies target) if(GNUTLS_HMAC_INIT_WITH_DIGEST) target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_HMAC_INIT_WITH_DIGEST=1) endif() + if(GNUTLS_MAC_AES_CMAC_128) + target_compile_definitions(${target} PRIVATE -DHAVE_GNUTLS_MAC_AES_CMAC_128=1) + endif() endif() endfunction() diff --git a/src/core/system_parameters/gnss_crypto.cc b/src/core/system_parameters/gnss_crypto.cc index 2062b0674..055bd0382 100644 --- a/src/core/system_parameters/gnss_crypto.cc +++ b/src/core/system_parameters/gnss_crypto.cc @@ -436,7 +436,32 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke { std::vector<uint8_t> output(16); #if USE_GNUTLS_FALLBACK - // CMAC-AES not implemented in GnuTLS +#if HAVE_GNUTLS_MAC_AES_CMAC_128 + gnutls_hmac_hd_t hmac; + + // Initialize the HMAC context with the CMAC algorithm and key + 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); + return output; + } + + // Update the HMAC context with the input data + ret = gnutls_hmac(hmac, input.data(), input.size()); + if (ret != GNUTLS_E_SUCCESS) + { + LOG(INFO) << "OSNMA CMAC-AES: gnutls_hmac failed: " << gnutls_strerror(ret); + gnutls_hmac_deinit(hmac, nullptr); + return output; + } + + // Retrieve the HMAC output + gnutls_hmac_output(hmac, output.data()); + + // Clean up the HMAC context + gnutls_hmac_deinit(hmac, nullptr); +#else if (!key.empty()) { // do nothing @@ -445,6 +470,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke { // do nothing } +#endif #else // OpenSSL #if USE_OPENSSL_3 std::vector<uint8_t> aux(EVP_MAX_MD_SIZE); // CMAC-AES output size @@ -515,7 +541,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke } // Initialize the CMAC context with the key and cipher - if (1 != CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr)) + if (CMAC_Init(cmacCtx, key.data(), key.size(), EVP_aes_128_cbc(), nullptr) != 1) { LOG(INFO) << "OSNMA CMAC-AES: MAC_Init failed"; CMAC_CTX_free(cmacCtx); @@ -523,7 +549,7 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke } // Compute the CMAC - if (1 != CMAC_Update(cmacCtx, input.data(), input.size())) + if (CMAC_Update(cmacCtx, input.data(), input.size()) != 1) { LOG(INFO) << "OSNMA CMAC-AES: CMAC_Update failed"; CMAC_CTX_free(cmacCtx); @@ -531,9 +557,9 @@ std::vector<uint8_t> Gnss_Crypto::computeCMAC_AES(const std::vector<uint8_t>& ke } // Finalize the CMAC computation and retrieve the output - if (1 != CMAC_Final(cmacCtx, output.data(), &mac_length)) + if (CMAC_Final(cmacCtx, output.data(), &mac_length) != 1) { - LOG(INFO) << "OSNMA CMAC-AES:CMAC_Final failed"; + LOG(INFO) << "OSNMA CMAC-AES: CMAC_Final failed"; CMAC_CTX_free(cmacCtx); return output; }